private async Task <AuthenticationResult> RefreshRtOrFetchNewAccessTokenAsync(CancellationToken cancellationToken)
        {
            var logger = AuthenticationRequestParameters.RequestContext.Logger;

            if (IsLongRunningObo())
            {
                AuthenticationRequestParameters.RequestContext.Logger.Info("[OBO request] Long-running OBO flow, trying to refresh using an refresh token flow.");

                // Look for a refresh token
                MsalRefreshTokenCacheItem cachedRefreshToken = await CacheManager.FindRefreshTokenAsync().ConfigureAwait(false);

                // If a refresh token is not found, fetch a new access token
                if (cachedRefreshToken != null)
                {
                    logger.Info("[OBO request] Found a refresh token");
                    if (!string.IsNullOrEmpty(cachedRefreshToken.RawClientInfo))
                    {
                        var clientInfo = ClientInfo.CreateFromJson(cachedRefreshToken.RawClientInfo);

                        _ccsRoutingHint = CoreHelpers.GetCcsClientInfoHint(
                            clientInfo.UniqueObjectIdentifier,
                            clientInfo.UniqueTenantIdentifier);
                    }
                    else
                    {
                        logger.Info("[OBO request] No client info associated with RT. This is OBO for a Service Principal.");
                    }

                    var msalTokenResponse = await SilentRequestHelper.RefreshAccessTokenAsync(cachedRefreshToken, this, AuthenticationRequestParameters, cancellationToken)
                                            .ConfigureAwait(false);

                    return(await CacheTokenResponseAndCreateAuthenticationResultAsync(msalTokenResponse).ConfigureAwait(false));
                }

                if (AcquireTokenInLongRunningOboWasCalled())
                {
                    AuthenticationRequestParameters.RequestContext.Logger.Error("[OBO request] AcquireTokenInLongRunningProcess was called and no access or refresh tokens were found in the cache.");
                    throw new MsalClientException(MsalError.OboCacheKeyNotInCacheError, MsalErrorMessage.OboCacheKeyNotInCache);
                }

                AuthenticationRequestParameters.RequestContext.Logger.Info("[OBO request] No Refresh Token was found in the cache. Fetching OBO token from ESTS");
            }
            else
            {
                logger.Info("[OBO request] Normal OBO flow, skipping to fetching access token via OBO flow.");
            }

            return(await FetchNewAccessTokenAsync(cancellationToken).ConfigureAwait(false));
        }
Exemplo n.º 2
0
        private async Task <AuthenticationResult> RefreshRtOrFailAsync(CancellationToken cancellationToken)
        {
            // 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 SilentRequestHelper.RefreshAccessTokenAsync(appRefreshToken, _silentRequest, AuthenticationRequestParameters, cancellationToken)
                                    .ConfigureAwait(false);
            }
            return(await _silentRequest.CacheTokenResponseAndCreateAuthenticationResultAsync(msalTokenResponse).ConfigureAwait(false));
        }
Exemplo n.º 3
0
        private async Task <AuthenticationResult> RefreshRtOrFetchNewAccessTokenAsync(CancellationToken cancellationToken)
        {
            // Look for a refresh token
            MsalRefreshTokenCacheItem appRefreshToken = await CacheManager.FindRefreshTokenAsync().ConfigureAwait(false);

            // If a refresh token is not found, fetch a new access token
            if (appRefreshToken != null)
            {
                var clientInfo = ClientInfo.CreateFromJson(appRefreshToken.RawClientInfo);
                _ccsRoutingHint = CoreHelpers.GetCcsClientInfoHint(clientInfo.UniqueObjectIdentifier,
                                                                   clientInfo.UniqueTenantIdentifier);

                var msalTokenResponse = await SilentRequestHelper.RefreshAccessTokenAsync(appRefreshToken, this, AuthenticationRequestParameters, cancellationToken)
                                        .ConfigureAwait(false);

                return(await CacheTokenResponseAndCreateAuthenticationResultAsync(msalTokenResponse).ConfigureAwait(false));
            }

            AuthenticationRequestParameters.RequestContext.Logger.Info("[OBO request] No Refresh Token was found in the cache. Fetching OBO token from ESTS");

            return(await FetchNewAccessTokenAsync(cancellationToken).ConfigureAwait(false));
        }
Exemplo n.º 4
0
        private async Task <MsalTokenResponse> TryGetTokenUsingFociAsync(CancellationToken cancellationToken)
        {
            if (!ServiceBundle.PlatformProxy.GetFeatureFlags().IsFociEnabled)
            {
                return(null);
            }

            var logger = AuthenticationRequestParameters.RequestContext.Logger;

            // If the app was just added to the family, the app metadata will reflect this
            // after the first RT exchanged.
            bool?isFamilyMember = await CacheManager.IsAppFociMemberAsync(TheOnlyFamilyId).ConfigureAwait(false);

            if (isFamilyMember.HasValue && !isFamilyMember.Value)
            {
                AuthenticationRequestParameters.RequestContext.Logger.Verbose(
                    "[FOCI] App is not part of the family, skipping FOCI. ");

                return(null);
            }

            logger.Verbose("[FOCI] App is part of the family or unknown, looking for FRT. ");
            var familyRefreshToken = await CacheManager.FindFamilyRefreshTokenAsync(TheOnlyFamilyId).ConfigureAwait(false);

            logger.Verbose("[FOCI] FRT found? " + (familyRefreshToken != null));

            if (familyRefreshToken != null)
            {
                try
                {
                    MsalTokenResponse frtTokenResponse = await SilentRequestHelper.RefreshAccessTokenAsync(familyRefreshToken, _silentRequest, AuthenticationRequestParameters, cancellationToken)
                                                         .ConfigureAwait(false);

                    logger.Verbose("[FOCI] FRT refresh succeeded. ");
                    return(frtTokenResponse);
                }
                catch (MsalServiceException ex)
                {
                    // Hack: STS does not yet send back the suberror on these platforms because they are not in an allowed list,
                    // so the best thing we can do is to consider all errors as client_mismatch.
#if NETSTANDARD || WINDOWS_APP || MAC
                    ex?.GetType();  // avoid the "variable 'ex' is declared but never used" in this code path.
                    return(null);
#else
                    if (MsalError.InvalidGrantError.Equals(ex?.ErrorCode, StringComparison.OrdinalIgnoreCase) &&
                        MsalError.ClientMismatch.Equals(ex?.SubError, StringComparison.OrdinalIgnoreCase))
                    {
                        logger.Error("[FOCI] FRT refresh failed - client mismatch. ");
                        return(null);
                    }

                    // Rethrow failures to refresh the FRT, other than client_mismatch, because
                    // apps need to handle them in the same way they handle exceptions from refreshing the RT.
                    // For example, some apps have special handling for MFA errors.
                    logger.Error("[FOCI] FRT refresh failed - other error. ");
                    throw;
#endif
                }
            }

            return(null);
        }