/// <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);
        }
示例#4
0
        /// <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);
        }
示例#6
0
        /// <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);
            }
        }
示例#7
0
        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);
        }