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)); }
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)); }
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)); }
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); }