/// <summary> /// Request OTC (One-Time-Code) if 2FA via Email, Mobile phone or MS Authenticator v2 is desired. /// </summary> /// <param name="authMethod">Auth method to use</param> /// <param name="proof">Proof Verification, used by mobile phone and email-method, for MS Authenticator provide `null`</param> /// <param name="authData">Authentication data for this provided, specific authorization method</param> /// <returns>Returns instance of OtcResponse</returns> private async Task <Model.OtcResponse> RequestOtc( Model.TwoFactorAuthMethod authMethod, string proof, string authData ) { const string GetOnetimeCodeUrl = "https://login.live.com/pp1600/GetOneTimeCode.srf"; var otcRequest = new Model.OtcRequest() { Login = Email, Flowtoken = FlowToken, Purpose = "eOTT_OneTimePassword", UiMode = "11" }; otcRequest.SetAuthData(authData); if (!String.IsNullOrEmpty(proof)) { otcRequest.ProofConfirmation = proof; } if (Model.TwoFactorAuthMethod.Email == authMethod) { otcRequest.Channel = "Email"; otcRequest.SetPostFieldName("AltEmailE"); } else if (Model.TwoFactorAuthMethod.SMS == authMethod) { otcRequest.Channel = "SMS"; otcRequest.SetPostFieldName("MobileNumE"); } else if (Model.TwoFactorAuthMethod.Voice == authMethod) { otcRequest.Channel = "Voice"; otcRequest.SetPostFieldName("MobileNumE"); } else if (Model.TwoFactorAuthMethod.TOTPAuthenticatorV2 == authMethod) { otcRequest.Channel = "PushNotifications"; otcRequest.SetPostFieldName("SAPId"); } else { logger.LogError("Unsupported TwoFactor Auth-Type: {}", authMethod); throw new Exception(String.Format("Unsupported TwoFactor Auth-Type: {}", authMethod)); } var request = new HttpRequestMessage(HttpMethod.Post, GetOnetimeCodeUrl); request.Content = new FormUrlEncodedContent(otcRequest.GetFormContent()); var response = await _client.SendAsync(request); return(await response.Content.ReadAsJsonAsync <Model.OtcResponse>()); }
/// <summary> /// Finish the Two-Factor-Authentication. If it succeeds we are provided with Access and Refresh-Token. /// </summary> /// <param name="authMethod">Auth method to use</param> /// <param name="authData">Authentication data for this provided, specific authorization method</param> /// <param name="otc">One-Time-Code, required for every method except MS Authenticator v2</param> /// <param name="proofConfirmation">Confirmation of Email or mobile phone number, if that method was chosen</param> public async Task <HttpResponseMessage> FinishAuth( Model.TwoFactorAuthMethod authMethod, string authData, string otc, string proofConfirmation ) { var finishAuthPostBody = new Model.FinishAuthRequest() { Login = Email, PPFT = FlowToken, SentProofIDE = authData, Sacxt = 1, Saav = 0, Purpose = "eOTT_OneTimePassword", I18 = "__DefaultSAStrings|1,__DefaultSA_Core|1,__DefaultSA_Wizard|1", Otc = otc, Slk = SessionLookupKey, ProofConfirmation = proofConfirmation }; if (Model.TwoFactorAuthMethod.SMS == authMethod || Model.TwoFactorAuthMethod.Voice == authMethod || Model.TwoFactorAuthMethod.Email == authMethod) { finishAuthPostBody.Type = 18; finishAuthPostBody.GeneralVerify = "false"; } else if (Model.TwoFactorAuthMethod.TOTPAuthenticator == authMethod) { finishAuthPostBody.Type = 19; finishAuthPostBody.GeneralVerify = "false"; } else if (Model.TwoFactorAuthMethod.TOTPAuthenticatorV2 == authMethod) { finishAuthPostBody.Type = 22; finishAuthPostBody.GeneralVerify = ""; } else { throw new Exception(String.Format("Unhandled case for submitting OTC, method: {}", authMethod)); } var request = new HttpRequestMessage(HttpMethod.Post, PostUrl); request.Content = new FormUrlEncodedContent(finishAuthPostBody.GetFormContent()); return(await _client.SendAsync(request)); }