in pkg/provider/aad/aad.go [436:501]
func (ac *Client) processMfa(mfas []userProof, convergedResponse *ConvergedResponse) (*http.Response, error) {
var res *http.Response
var err error
var mfaResp mfaResponse
if len(mfas) == 0 {
return res, fmt.Errorf("MFA not found")
}
mfaResp, err = ac.processMfaBeginAuth(mfas, convergedResponse)
if err != nil {
return res, errors.Wrap(err, "error processing MFA BeginAuth")
}
for i := 0; ; i++ {
mfaReq := mfaRequest{
AuthMethodID: mfaResp.AuthMethodID,
Method: "EndAuth",
Ctx: mfaResp.Ctx,
FlowToken: mfaResp.FlowToken,
SessionID: mfaResp.SessionID,
}
if mfaReq.AuthMethodID == "PhoneAppOTP" || mfaReq.AuthMethodID == "OneWaySMS" {
verifyCode := prompter.StringRequired("Enter verification code")
mfaReq.AdditionalAuthData = verifyCode
}
if mfaReq.AuthMethodID == "PhoneAppNotification" && i == 0 {
if mfaResp.Entropy == 0 {
prompter.Display("Phone approval required.")
} else {
prompter.Display(fmt.Sprintf("Phone approval required. Entropy is: %d", mfaResp.Entropy))
}
}
mfaResp, err = ac.processMfaEndAuth(mfaReq, convergedResponse)
if err != nil {
return res, errors.Wrap(err, "error processing MFA EndAuth")
}
if mfaResp.ErrCode != 0 {
return res, fmt.Errorf("error processing MFA, errcode: %d, message: %v", mfaResp.ErrCode, mfaResp.Message)
}
if mfaResp.Success {
break
}
if !mfaResp.Retry {
break
}
// if mfaResp.Retry == true then
// must exist convergedResponse.OPerAuthPollingInterval[mfaResp.AuthMethodID]
time.Sleep(time.Duration(convergedResponse.OPerAuthPollingInterval[mfaResp.AuthMethodID]) * time.Second)
}
if !mfaResp.Success {
return res, fmt.Errorf("error processing MFA")
}
res, err = ac.processMfaAuth(mfaResp, convergedResponse)
if err != nil {
return res, errors.Wrap(err, "error processing MFA ProcessAuth")
}
return res, nil
}