Skip to content

Commit

Permalink
Merge pull request #1355 from hejfelix/feature/aad-mfa-token
Browse files Browse the repository at this point in the history
pass mfa-token in AzureAD provider
  • Loading branch information
mapkon authored Oct 21, 2024
2 parents 36ab9ae + cd7b0c3 commit 148bb41
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 6 deletions.
16 changes: 10 additions & 6 deletions pkg/provider/aad/aad.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ AuthProcessor:
res, err = ac.processKmsiInterrupt(res, resBodyStr)
case strings.Contains(resBodyStr, "ConvergedTFA"):
logger.Debug("processing ConvergedTFA")
res, err = ac.processConvergedTFA(res, resBodyStr)
res, err = ac.processConvergedTFA(res, resBodyStr, loginDetails)
case strings.Contains(resBodyStr, "SAMLRequest"):
logger.Debug("processing SAMLRequest")
res, err = ac.processSAMLRequest(res, resBodyStr)
Expand Down Expand Up @@ -407,7 +407,7 @@ func (ac *Client) processKmsiInterrupt(res *http.Response, srcBodyStr string) (*
return res, nil
}

func (ac *Client) processConvergedTFA(res *http.Response, srcBodyStr string) (*http.Response, error) {
func (ac *Client) processConvergedTFA(res *http.Response, srcBodyStr string, loginDetails *creds.LoginDetails) (*http.Response, error) {
var convergedResponse *ConvergedResponse
var err error

Expand All @@ -425,7 +425,7 @@ func (ac *Client) processConvergedTFA(res *http.Response, srcBodyStr string) (*h
}
} else if len(mfas) != 0 {
// there's no explicit option to skip MFA, and MFA options are available
res, err = ac.processMfa(mfas, convergedResponse)
res, err = ac.processMfa(mfas, convergedResponse, loginDetails)
if err != nil {
return res, err
}
Expand All @@ -434,7 +434,7 @@ func (ac *Client) processConvergedTFA(res *http.Response, srcBodyStr string) (*h
return res, nil
}

func (ac *Client) processMfa(mfas []userProof, convergedResponse *ConvergedResponse) (*http.Response, error) {
func (ac *Client) processMfa(mfas []userProof, convergedResponse *ConvergedResponse, loginDetails *creds.LoginDetails) (*http.Response, error) {
var res *http.Response
var err error
var mfaResp mfaResponse
Expand All @@ -457,8 +457,12 @@ func (ac *Client) processMfa(mfas []userProof, convergedResponse *ConvergedRespo
SessionID: mfaResp.SessionID,
}
if mfaReq.AuthMethodID == "PhoneAppOTP" || mfaReq.AuthMethodID == "OneWaySMS" {
verifyCode := prompter.StringRequired("Enter verification code")
mfaReq.AdditionalAuthData = verifyCode
if loginDetails.MFAToken != "" {
mfaReq.AdditionalAuthData = loginDetails.MFAToken
} else {
verifyCode := prompter.StringRequired("Enter verification code")
mfaReq.AdditionalAuthData = verifyCode
}
}
if mfaReq.AuthMethodID == "PhoneAppNotification" && i == 0 {
if mfaResp.Entropy == 0 {
Expand Down
46 changes: 46 additions & 0 deletions pkg/provider/aad/aad_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,52 @@ func Test_Authenticate(t *testing.T) {
require.Nil(t, err)
require.NotEmpty(t, got)
})
t.Run("Pass mfa-token via loginDetails", func(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/index", "/applications/redirecttofederatedapplication.aspx":
writeFixtureBytes(t, w, r, "ConvergedSignIn.html", FixtureData{
UrlPost: "/defaultLogin",
UrlGetCredentialType: "/getCredentialType",
})
case "/getCredentialType":
writeFixtureBytes(t, w, r, "GetCredentialType_default.json", FixtureData{})
case "/defaultLogin":
writeFixtureBytes(t, w, r, "KmsiInterrupt.html", FixtureData{
UrlPost: "/hForm",
})
case "/hForm":
writeFixtureBytes(t, w, r, "HiddenForm.html", FixtureData{
UrlHiddenForm: "/sRequest",
})
case "/sRequest":
writeFixtureBytes(t, w, r, "SAMLRequest.html", FixtureData{
UrlSamlRequest: "/sResponse?SAMLRequest=ExampleValue",
})
case "/sResponse":
writeFixtureBytes(t, w, r, "ConvergedTFA.html", FixtureData{
UrlPost: "/processAuth",
UrlBeginAuth: "/beginAuth",
UrlEndAuth: "/endAuth",
})
case "/beginAuth":
writeFixtureBytes(t, w, r, "BeginAuth.json", FixtureData{})
case "/endAuth":
writeFixtureBytes(t, w, r, "EndAuth.json", FixtureData{})
case "/processAuth":
writeFixtureBytes(t, w, r, "SAMLResponse.html", FixtureData{})
default:
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
}
}))
defer ts.Close()

ac, loginDetails := setupTestClient(t, ts)
loginDetails.MFAToken = "000000"
got, err := ac.Authenticate(loginDetails)
require.Nil(t, err)
require.NotEmpty(t, got)
})
t.Run("Default login with KMSI and MFA but Authenticator required", func(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
Expand Down

0 comments on commit 148bb41

Please sign in to comment.