Beispiel #1
0
        internal async Task <AuthenticationResult> HandleTokenRefreshErrorAsync(MsalServiceException e, MsalAccessTokenCacheItem cachedAccessTokenItem)
        {
            var  logger           = AuthenticationRequestParameters.RequestContext.Logger;
            bool isAadUnavailable = e.IsAadUnavailable();

            logger.Warning($"Fetching a new AT failed. Is AAD down? {isAadUnavailable}. Is there an AT in the cache that is usable? {cachedAccessTokenItem != null}");

            if (cachedAccessTokenItem != null && isAadUnavailable)
            {
                logger.Info("Returning existing access token. It is not expired, but should be refreshed. ");

                var idToken = await CacheManager.GetIdTokenCacheItemAsync(cachedAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

                var tenantProfiles = await CacheManager.GetTenantProfilesAsync(cachedAccessTokenItem.HomeAccountId).ConfigureAwait(false);

                return(new AuthenticationResult(
                           cachedAccessTokenItem,
                           idToken,
                           tenantProfiles?.Values,
                           AuthenticationRequestParameters.AuthenticationScheme,
                           AuthenticationRequestParameters.RequestContext.CorrelationId,
                           TokenSource.Cache,
                           AuthenticationRequestParameters.RequestContext.ApiEvent));
            }

            logger.Warning("Either the exception does not indicate a problem with AAD or the token cache does not have an AT that is usable. ");
            throw e;
        }
Beispiel #2
0
        private async Task <AuthenticationResult> CreateAuthenticationResultAsync(MsalAccessTokenCacheItem cachedAccessTokenItem)
        {
            var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(cachedAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

            return(new AuthenticationResult(
                       cachedAccessTokenItem,
                       msalIdTokenItem,
                       AuthenticationRequestParameters.AuthenticationScheme,
                       AuthenticationRequestParameters.RequestContext.CorrelationId));
        }
Beispiel #3
0
        internal override async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            if (TokenCache == null)
            {
                throw new MsalUiRequiredException(
                          MsalUiRequiredException.TokenCacheNullError,
                          "Token cache is set to null. Silent requests cannot be executed.");
            }

            MsalAccessTokenCacheItem msalAccessTokenItem = null;

            // Look for access token
            if (!ForceRefresh)
            {
                msalAccessTokenItem =
                    await TokenCache.FindAccessTokenAsync(AuthenticationRequestParameters).ConfigureAwait(false);
            }

            if (msalAccessTokenItem != null)
            {
                var msalIdTokenItem = TokenCache.GetIdTokenCacheItem(
                    msalAccessTokenItem.GetIdTokenItemKey(),
                    AuthenticationRequestParameters.RequestContext);

                return(new AuthenticationResult(msalAccessTokenItem, msalIdTokenItem));
            }

            var msalRefreshTokenItem =
                await TokenCache.FindRefreshTokenAsync(AuthenticationRequestParameters).ConfigureAwait(false);

            if (msalRefreshTokenItem == null)
            {
                AuthenticationRequestParameters.RequestContext.Logger.Verbose("No Refresh Token was found in the cache");

                throw new MsalUiRequiredException(
                          MsalUiRequiredException.NoTokensFoundError,
                          "No Refresh Token found in the cache");
            }

            AuthenticationRequestParameters.RequestContext.Logger.Verbose("Refreshing access token...");
            await ResolveAuthorityEndpointsAsync().ConfigureAwait(false);

            var msalTokenResponse = await SendTokenRequestAsync(GetBodyParameters(msalRefreshTokenItem.Secret), cancellationToken)
                                    .ConfigureAwait(false);

            if (msalTokenResponse.RefreshToken == null)
            {
                msalTokenResponse.RefreshToken = msalRefreshTokenItem.Secret;
                AuthenticationRequestParameters.RequestContext.Logger.Info(
                    "Refresh token was missing from the token refresh response, so the refresh token in the request is returned instead");
            }

            return(CacheTokenResponseAndCreateAuthenticationResult(msalTokenResponse));
        }
Beispiel #4
0
        public MsalIdTokenCacheItem GetIdToken(MsalAccessTokenCacheItem accessTokenCacheItem)
        {
            string partitionKey = CacheKeyFactory.GetIdTokenKeyFromCachedItem(accessTokenCacheItem);

            IdTokenCacheDictionary.TryGetValue(partitionKey, out var partition);
            if (partition != null && partition.TryGetValue(accessTokenCacheItem.GetIdTokenItemKey().ToString(), out var idToken))
            {
                return(idToken);
            }

            _logger.WarningPii(
                $"Could not find an id token for the access token with key {accessTokenCacheItem.GetKey()}",
                $"Could not find an id token for the access token for realm {accessTokenCacheItem.TenantId} ");
            return(null);
        }
Beispiel #5
0
        private async Task <AuthenticationResult> CreateAuthenticationResultAsync(MsalAccessTokenCacheItem cachedAccessTokenItem)
        {
            var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(cachedAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

            var tenantProfiles = await CacheManager.GetTenantProfilesAsync(cachedAccessTokenItem.HomeAccountId).ConfigureAwait(false);

            return(new AuthenticationResult(
                       cachedAccessTokenItem,
                       msalIdTokenItem,
                       tenantProfiles?.Values,
                       AuthenticationRequestParameters.AuthenticationScheme,
                       AuthenticationRequestParameters.RequestContext.CorrelationId,
                       TokenSource.Cache,
                       AuthenticationRequestParameters.RequestContext.ApiEvent));
        }
Beispiel #6
0
        protected override async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            if (AuthenticationRequestParameters.Scope == null || AuthenticationRequestParameters.Scope.Count == 0)
            {
                throw new MsalClientException(
                          MsalError.ScopesRequired,
                          MsalErrorMessage.ScopesRequired);
            }

            await ResolveAuthorityEndpointsAsync().ConfigureAwait(false);

            // look for access token in the cache first.
            // no access token is found, then it means token does not exist
            // or new assertion has been passed. We should not use Refresh Token
            // for the user because the new incoming token may have updated claims
            // like mfa etc.
            MsalAccessTokenCacheItem msalAccessTokenItem = await CacheManager.FindAccessTokenAsync().ConfigureAwait(false);

            if (msalAccessTokenItem != null)
            {
                var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(msalAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

                AuthenticationRequestParameters.RequestContext.Logger.Info(
                    "OBO found a valid access token in the cache. ID token also found? " + (msalIdTokenItem != null));

                AuthenticationRequestParameters.RequestContext.ApiEvent.IsAccessTokenCacheHit = true;

                return(new AuthenticationResult(
                           msalAccessTokenItem,
                           msalIdTokenItem,
                           AuthenticationRequestParameters.AuthenticationScheme,
                           AuthenticationRequestParameters.RequestContext.CorrelationId,
                           TokenSource.Cache));
            }


            var msalTokenResponse = await SendTokenRequestAsync(GetBodyParameters(), cancellationToken).ConfigureAwait(false);

            return(await CacheTokenResponseAndCreateAuthenticationResultAsync(msalTokenResponse).ConfigureAwait(false));
        }
Beispiel #7
0
 public MsalIdTokenCacheItem GetIdToken(MsalAccessTokenCacheItem accessTokenCacheItem)
 {
     return(MsalIdTokenCacheItem.FromJsonString(
                _idTokenSharedPreference.GetString(accessTokenCacheItem.GetIdTokenItemKey().ToString(), null)));
 }
        protected override async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            if (AuthenticationRequestParameters.Scope == null || AuthenticationRequestParameters.Scope.Count == 0)
            {
                throw new MsalClientException(
                          MsalError.ScopesRequired,
                          MsalErrorMessage.ScopesRequired);
            }

            await ResolveAuthorityEndpointsAsync().ConfigureAwait(false);

            CacheInfoTelemetry       cacheInfoTelemetry  = CacheInfoTelemetry.None;
            MsalAccessTokenCacheItem msalAccessTokenItem = null;
            var logger = AuthenticationRequestParameters.RequestContext.Logger;

            if (!_onBehalfOfParameters.ForceRefresh)
            {
                // look for access token in the cache first.
                // no access token is found, then it means token does not exist
                // or new assertion has been passed. We should not use Refresh Token
                // for the user because the new incoming token may have updated claims
                // like MFA etc.
                msalAccessTokenItem = await CacheManager.FindAccessTokenAsync().ConfigureAwait(false);

                if (msalAccessTokenItem != null && !msalAccessTokenItem.NeedsRefresh())
                {
                    var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(msalAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

                    AuthenticationRequestParameters.RequestContext.Logger.Info(
                        "OBO found a valid access token in the cache. ID token also found? " + (msalIdTokenItem != null));

                    AuthenticationRequestParameters.RequestContext.ApiEvent.IsAccessTokenCacheHit = true;

                    return(new AuthenticationResult(
                               msalAccessTokenItem,
                               msalIdTokenItem,
                               AuthenticationRequestParameters.AuthenticationScheme,
                               AuthenticationRequestParameters.RequestContext.CorrelationId,
                               TokenSource.Cache,
                               AuthenticationRequestParameters.RequestContext.ApiEvent));
                }

                cacheInfoTelemetry = (msalAccessTokenItem == null) ? CacheInfoTelemetry.NoCachedAT : CacheInfoTelemetry.RefreshIn;
            }
            else
            {
                logger.Info("Skipped looking for an Access Token in the cache because ForceRefresh or Claims were set. ");
                cacheInfoTelemetry = CacheInfoTelemetry.ForceRefresh;
            }

            if (AuthenticationRequestParameters.RequestContext.ApiEvent.CacheInfo == (int)CacheInfoTelemetry.None)
            {
                AuthenticationRequestParameters.RequestContext.ApiEvent.CacheInfo = (int)cacheInfoTelemetry;
            }

            // No AT in the cache or AT needs to be refreshed
            try
            {
                return(await FetchNewAccessTokenAsync(cancellationToken).ConfigureAwait(false));
            }
            catch (MsalServiceException e)
            {
                return(HandleTokenRefreshError(e, msalAccessTokenItem));
            }
        }
Beispiel #9
0
        protected override async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            if (AuthenticationRequestParameters.Scope == null || AuthenticationRequestParameters.Scope.Count == 0)
            {
                throw new MsalClientException(
                          MsalError.ScopesRequired,
                          MsalErrorMessage.ScopesRequired);
            }

            await ResolveAuthorityAsync().ConfigureAwait(false);

            MsalAccessTokenCacheItem msalAccessTokenItem = null;
            var logger = AuthenticationRequestParameters.RequestContext.Logger;

            CacheInfoTelemetry cacheInfoTelemetry;

            if (!_onBehalfOfParameters.ForceRefresh && string.IsNullOrEmpty(AuthenticationRequestParameters.Claims))
            {
                // look for access token in the cache first.
                // no access token is found, then it means token does not exist
                // or new assertion has been passed.
                // Look for a refresh token, if refresh token is found perform refresh token flow.
                // If a refresh token is not found, then it means refresh token does not exist or new assertion has been passed.
                // Fetch new access token for OBO
                using (logger.LogBlockDuration("[OBO Request] Looking in the cache for an access token"))
                {
                    msalAccessTokenItem = await CacheManager.FindAccessTokenAsync().ConfigureAwait(false);
                }

                if (msalAccessTokenItem != null && !msalAccessTokenItem.NeedsRefresh())
                {
                    var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(msalAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

                    var tenantProfiles = await CacheManager.GetTenantProfilesAsync(msalAccessTokenItem.HomeAccountId).ConfigureAwait(false);

                    logger.Info(
                        "[OBO Request] Found a valid access token in the cache. ID token also found? " + (msalIdTokenItem != null));

                    AuthenticationRequestParameters.RequestContext.ApiEvent.IsAccessTokenCacheHit = true;

                    Metrics.IncrementTotalAccessTokensFromCache();
                    return(new AuthenticationResult(
                               msalAccessTokenItem,
                               msalIdTokenItem,
                               tenantProfiles?.Values,
                               AuthenticationRequestParameters.AuthenticationScheme,
                               AuthenticationRequestParameters.RequestContext.CorrelationId,
                               TokenSource.Cache,
                               AuthenticationRequestParameters.RequestContext.ApiEvent));
                }

                cacheInfoTelemetry = (msalAccessTokenItem == null) ? CacheInfoTelemetry.NoCachedAT : CacheInfoTelemetry.RefreshIn;
                logger.Verbose($"[OBO request] No valid access token found because {cacheInfoTelemetry} ");
            }
            else
            {
                logger.Info("[OBO Request] Skipped looking for an Access Token in the cache because ForceRefresh or Claims were set. ");
                cacheInfoTelemetry = CacheInfoTelemetry.ForceRefresh;
            }

            if (AuthenticationRequestParameters.RequestContext.ApiEvent.CacheInfo == (int)CacheInfoTelemetry.None)
            {
                AuthenticationRequestParameters.RequestContext.ApiEvent.CacheInfo = (int)cacheInfoTelemetry;
            }

            // No AT in the cache or AT needs to be refreshed
            try
            {
                return(await RefreshRtOrFetchNewAccessTokenAsync(cancellationToken).ConfigureAwait(false));
            }
            catch (MsalServiceException e)
            {
                return(await HandleTokenRefreshErrorAsync(e, msalAccessTokenItem).ConfigureAwait(false));
            }
        }
Beispiel #10
0
        internal override async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            if (!CacheManager.HasCache)
            {
                throw new MsalUiRequiredException(
                          MsalError.TokenCacheNullError,
                          MsalErrorMessage.NullTokenCacheForSilentError);
            }

            // Look for access token
            if (!_silentParameters.ForceRefresh)
            {
                MsalAccessTokenCacheItem msalAccessTokenItem =
                    await CacheManager.FindAccessTokenAsync().ConfigureAwait(false);

                if (msalAccessTokenItem != null)
                {
                    var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(msalAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

                    return(new AuthenticationResult(msalAccessTokenItem, msalIdTokenItem, AuthenticationRequestParameters.RequestContext.CorrelationId));
                }
            }

            // Try FOCI first
            MsalTokenResponse msalTokenResponse = await TryGetTokenUsingFociAsync(cancellationToken)
                                                  .ConfigureAwait(false);

            // Normal, non-FOCI flow
            if (msalTokenResponse == null)
            {
                // Look for a refresh token
                MsalRefreshTokenCacheItem appRefreshToken = await FindRefreshTokenOrFailAsync()
                                                            .ConfigureAwait(false);

                msalTokenResponse = await RefreshAccessTokenAsync(appRefreshToken, cancellationToken)
                                    .ConfigureAwait(false);
            }
            return(await CacheTokenResponseAndCreateAuthenticationResultAsync(msalTokenResponse).ConfigureAwait(false));
        }
        public MsalIdTokenCacheItem GetIdToken(MsalAccessTokenCacheItem accessTokenCacheItem)
        {
            var idTokenKey = accessTokenCacheItem.GetIdTokenItemKey();

            return(MsalIdTokenCacheItem.FromJsonString(GetPayload(idTokenKey)));
        }
        internal override async Task <AuthenticationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            // Look for access token
            if (!_silentParameters.ForceRefresh)
            {
                MsalAccessTokenCacheItem msalAccessTokenItem =
                    await CacheManager.FindAccessTokenAsync().ConfigureAwait(false);

                if (msalAccessTokenItem != null)
                {
                    var msalIdTokenItem = await CacheManager.GetIdTokenCacheItemAsync(msalAccessTokenItem.GetIdTokenItemKey()).ConfigureAwait(false);

                    return(new AuthenticationResult(msalAccessTokenItem, msalIdTokenItem, AuthenticationRequestParameters.RequestContext.CorrelationId));
                }
            }

            return(await RefreshRTAsync(cancellationToken).ConfigureAwait(false));
        }