/// <summary> /// Attempts to acquire access token from the token cache silently by calling AcquireTokenSilentAsync /// </summary> internal async Task <AuthenticationResult> GetAccessTokenSilentAsync(MsalAuthenticationProviderOption msalAuthProviderOption) { IAccount account = null; if (msalAuthProviderOption.UserAccount?.ObjectId != null) { // Parse GraphUserAccount to IAccount instance account = new GraphAccount(msalAuthProviderOption.UserAccount); } else { // If no graph user account is passed, try get the one in cache. IEnumerable <IAccount> accounts = await ClientApplication.GetAccountsAsync(); account = accounts.FirstOrDefault(); } if (account == null) { return(null); } try { return(await ClientApplication.AcquireTokenSilentAsync( msalAuthProviderOption.Scopes ?? Scopes, account, ClientApplication.Authority, msalAuthProviderOption.ForceRefresh)); } catch (MsalUiRequiredException msalUiEx) { return(null); } catch (MsalServiceException serviceException) { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Message.UnexpectedMsalException }, serviceException); } catch (Exception exception) { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Message.UnexpectedException }, exception); } }
/// <summary> /// Sets <see cref="UserAssertion"/> for this request. /// This should only be used with <see cref="OnBehalfOfProvider"/>. /// </summary> /// <param name="baseRequest">The <see cref="IBaseRequest"/>.</param> /// <param name="userAssertion">A <see cref="UserAssertion"/> for the user.</param> public static T WithUserAssertion <T>(this T baseRequest, UserAssertion userAssertion) where T : IBaseRequest { string authHandlerOptionKey = typeof(AuthenticationHandlerOption).ToString(); AuthenticationHandlerOption authHandlerOptions = baseRequest.MiddlewareOptions[authHandlerOptionKey] as AuthenticationHandlerOption; MsalAuthenticationProviderOption msalAuthProviderOption = authHandlerOptions.AuthenticationProviderOption as MsalAuthenticationProviderOption ?? new MsalAuthenticationProviderOption(); msalAuthProviderOption.UserAssertion = userAssertion; authHandlerOptions.AuthenticationProviderOption = msalAuthProviderOption; baseRequest.MiddlewareOptions[authHandlerOptionKey] = authHandlerOptions; return(baseRequest); }
/// <summary> /// Sets MSAL's force refresh flag to <see cref="IAuthenticationProvider"/> for this request. If set to true, <see cref="IAuthenticationProvider"/> will refresh existing access token in cahce. /// This defaults to false if not set. /// </summary> /// <param name="baseRequest">The <see cref="IBaseRequest"/>.</param> /// <param name="forceRefresh">A <see cref="bool"/> flag to determine whether refresh access token or not.</param> public static T WithForceRefresh <T>(this T baseRequest, bool forceRefresh) where T : IBaseRequest { string authHandlerOptionKey = typeof(AuthenticationHandlerOption).ToString(); AuthenticationHandlerOption authHandlerOptions = baseRequest.MiddlewareOptions[authHandlerOptionKey] as AuthenticationHandlerOption; MsalAuthenticationProviderOption msalAuthProviderOption = authHandlerOptions.AuthenticationProviderOption as MsalAuthenticationProviderOption ?? new MsalAuthenticationProviderOption(); msalAuthProviderOption.ForceRefresh = forceRefresh; authHandlerOptions.AuthenticationProviderOption = msalAuthProviderOption; baseRequest.MiddlewareOptions[authHandlerOptionKey] = authHandlerOptions; return(baseRequest); }
/// <summary> /// Adds an authentication header to the incoming request by checking the application's <see cref="TokenCache"/> /// for an unexpired access token. If a token is not found or expired, it gets a new one. /// </summary> /// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to authenticate</param> public async Task AuthenticateRequestAsync(HttpRequestMessage httpRequestMessage) { MsalAuthenticationProviderOption msalAuthProviderOption = httpRequestMessage.GetMsalAuthProviderOption(); int retryCount = 0; do { try { AuthenticationResult authenticationResult = await(ClientApplication as IConfidentialClientApplication).AcquireTokenForClientAsync(new string[] { _resourceUrl }, msalAuthProviderOption.ForceRefresh); if (!string.IsNullOrEmpty(authenticationResult?.AccessToken)) { httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(CoreConstants.Headers.Bearer, authenticationResult.AccessToken); } break; } catch (MsalServiceException serviceException) { if (serviceException.ErrorCode == ErrorConstants.Codes.TemporarilyUnavailable) { TimeSpan delay = this.GetRetryAfter(serviceException); retryCount++; // pause execution await Task.Delay(delay); } else { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Message.UnexpectedMsalException }, serviceException); } } catch (Exception exception) { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Message.UnexpectedException }, exception); } } while (retryCount < MaxRetry); }
/// <summary> /// Sets a username (email) and password of an Azure AD account to authenticate. /// This should only be used with <see cref="UsernamePasswordProvider"/>. /// This provider is NOT RECOMMENDED because it exposes the users password. /// We recommend you use <see cref="IntegratedWindowsAuthenticationProvider"/> instead. /// </summary> /// <param name="baseRequest">The <see cref="IBaseRequest"/>.</param> /// <param name="email">Email address of the user to authenticate.</param> /// <param name="password">Password of the user to authenticate.</param> public static T WithUsernamePassword <T>(this T baseRequest, string email, string password) where T : IBaseRequest { string authHandlerOptionKey = typeof(AuthenticationHandlerOption).ToString(); AuthenticationHandlerOption authHandlerOptions = baseRequest.MiddlewareOptions[authHandlerOptionKey] as AuthenticationHandlerOption; MsalAuthenticationProviderOption msalAuthProviderOption = authHandlerOptions.AuthenticationProviderOption as MsalAuthenticationProviderOption ?? new MsalAuthenticationProviderOption(); msalAuthProviderOption.Password = password; msalAuthProviderOption.UserAccount = new GraphUserAccount { Email = email }; authHandlerOptions.AuthenticationProviderOption = msalAuthProviderOption; baseRequest.MiddlewareOptions[authHandlerOptionKey] = authHandlerOptions; return(baseRequest); }
/// <summary> /// Adds an authentication header to the incoming request by checking the application's <see cref="TokenCache"/> /// for an unexpired access token. If a token is not found or expired, it gets a new one. /// </summary> /// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to authenticate.</param> public async Task AuthenticateRequestAsync(HttpRequestMessage httpRequestMessage) { GraphRequestContext requestContext = httpRequestMessage.GetRequestContext(); MsalAuthenticationProviderOption msalAuthProviderOption = httpRequestMessage.GetMsalAuthProviderOption(); AuthenticationResult authenticationResult = await GetAccessTokenSilentAsync(msalAuthProviderOption); if (authenticationResult == null) { authenticationResult = await GetNewAccessTokenAsync(msalAuthProviderOption); } if (!string.IsNullOrEmpty(authenticationResult.AccessToken)) { httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(CoreConstants.Headers.Bearer, authenticationResult.AccessToken); } }
private async Task <AuthenticationResult> GetNewAccessTokenAsync(MsalAuthenticationProviderOption msalAuthProviderOption) { AuthenticationResult authenticationResult = null; int retryCount = 0; do { try { authenticationResult = await(ClientApplication as IPublicClientApplication) .AcquireTokenByUsernamePasswordAsync(msalAuthProviderOption.Scopes ?? Scopes, msalAuthProviderOption.UserAccount?.Email, ToSecureString(msalAuthProviderOption.Password)); break; } catch (MsalServiceException serviceException) { if (serviceException.ErrorCode == ErrorConstants.Codes.TemporarilyUnavailable) { TimeSpan delay = this.GetRetryAfter(serviceException); retryCount++; // pause execution await Task.Delay(delay); } else { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Message.UnexpectedMsalException }, serviceException); } } catch (Exception exception) { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.GeneralException, Message = ErrorConstants.Message.UnexpectedException }, exception); } } while (retryCount < MaxRetry); return(authenticationResult); }
/// <summary> /// Adds an authentication header to the incoming request by checking the application's <see cref="TokenCache"/> /// for an unexpired access token. /// If an access token doesn't exist, it will throw a <see cref="AuthenticationException"/> /// and the web app must handle this and perform a challange. /// </summary> /// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to authenticate.</param> public async Task AuthenticateRequestAsync(HttpRequestMessage httpRequestMessage) { MsalAuthenticationProviderOption msalAuthProviderOption = httpRequestMessage.GetMsalAuthProviderOption(); AuthenticationResult authenticationResult = await GetAccessTokenSilentAsync(msalAuthProviderOption); if (string.IsNullOrEmpty(authenticationResult?.AccessToken)) { throw new AuthenticationException( new Error { Code = ErrorConstants.Codes.AuthenticationChallengeRequired, Message = ErrorConstants.Message.AuthenticationChallengeRequired }); } httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(CoreConstants.Headers.Bearer, authenticationResult.AccessToken); }