protected AcquireTokenHandlerBase(Authenticator authenticator, TokenCache tokenCache, string resource, ClientKey clientKey, TokenSubjectType subjectType) { this.Authenticator = authenticator; this.CallState = CreateCallState(this.Authenticator.CorrelationId); PlatformPlugin.Logger.Information(this.CallState, string.Format(CultureInfo.CurrentCulture, "=== Token Acquisition started:\n\tAuthority: {0}\n\tResource: {1}\n\tClientId: {2}\n\tCacheType: {3}\n\tAuthentication Target: {4}\n\t", authenticator.Authority, resource, clientKey.ClientId, (tokenCache != null) ? tokenCache.GetType().FullName + string.Format(CultureInfo.CurrentCulture, " ({0} items)", tokenCache.Count) : "null", subjectType)); this.tokenCache = tokenCache; if (string.IsNullOrWhiteSpace(resource)) { throw new ArgumentNullException("resource"); } this.Resource = (resource != NullResource) ? resource : null; this.ClientKey = clientKey; this.TokenSubjectType = subjectType; this.LoadFromCache = (tokenCache != null); this.StoreToCache = (tokenCache != null); this.SupportADFS = false; this.brokerParameters = new Dictionary <string, string>(); brokerParameters["authority"] = authenticator.Authority; brokerParameters["resource"] = resource; brokerParameters["client_id"] = clientKey.ClientId; brokerParameters["correlation_id"] = this.CallState.CorrelationId.ToString(); brokerParameters["client_version"] = AdalIdHelper.GetAdalVersion(); this.ResultEx = null; CacheQueryData = new CacheQueryData(); CacheQueryData.Authority = Authenticator.Authority; CacheQueryData.Resource = this.Resource; CacheQueryData.ClientId = this.ClientKey.ClientId; CacheQueryData.SubjectType = this.TokenSubjectType; CacheQueryData.UniqueId = this.UniqueId; CacheQueryData.DisplayableId = this.DisplayableId; }
private KeyValuePair <TokenCacheKey, AuthenticationResultEx>?LoadSingleItemFromCache(CacheQueryData cacheQueryData, CallState callState) { lock (cacheLock) { // First identify all potential tokens. List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > items = this.QueryCache(cacheQueryData.Authority, cacheQueryData.ClientId, cacheQueryData.SubjectType, cacheQueryData.UniqueId, cacheQueryData.DisplayableId); List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > resourceSpecificItems = items.Where(p => p.Key.ResourceEquals(cacheQueryData.Resource)).ToList(); int resourceValuesCount = resourceSpecificItems.Count(); //multiple tokens matched. scope down the results to the matching userAssertion Hash, if provided if (resourceValuesCount > 1 && cacheQueryData.AssertionHash != null) { resourceSpecificItems = resourceSpecificItems.Where(p => p.Value.UserAssertionHash.Equals(cacheQueryData.AssertionHash)) .ToList(); resourceValuesCount = resourceSpecificItems.Count(); } KeyValuePair <TokenCacheKey, AuthenticationResultEx>?returnValue = null; switch (resourceValuesCount) { case 1: PlatformPlugin.Logger.Information(callState, "An item matching the requested resource was found in the cache"); returnValue = resourceSpecificItems.First(); break; case 0: { // There are no resource specific tokens. Choose any of the MRRT tokens if there are any. List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > mrrtItems = items.Where(p => p.Value.IsMultipleResourceRefreshToken).ToList(); if (mrrtItems.Any()) { returnValue = mrrtItems.First(); PlatformPlugin.Logger.Information(callState, "A Multi Resource Refresh Token for a different resource was found which can be used"); } } break; default: throw new AdalException(AdalError.MultipleTokensMatched); } // check for tokens issued to same client_id/user_id combination, but any tenant. if (returnValue == null) { List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > itemsForAllTenants = this.QueryCache(null, cacheQueryData.ClientId, cacheQueryData.SubjectType, cacheQueryData.UniqueId, cacheQueryData.DisplayableId); if (itemsForAllTenants.Count != 0) { returnValue = itemsForAllTenants.First(); } // check if the token was issued by AAD if (returnValue != null && Authenticator.DetectAuthorityType(returnValue.Value.Key.Authority) != AuthorityType.ADFS) { //remove access token to redeem refresh token against a different tenant. returnValue.Value.Value.Result.AccessToken = null; } else { returnValue = null; } } return(returnValue); } }
internal AuthenticationResultEx LoadFromCache(CacheQueryData cacheQueryData, CallState callState) { lock (cacheLock) { PlatformPlugin.Logger.Verbose(callState, "Looking up cache for a token..."); AuthenticationResultEx resultEx = null; KeyValuePair <TokenCacheKey, AuthenticationResultEx>?kvp = this.LoadSingleItemFromCache(cacheQueryData, callState); if (kvp.HasValue) { TokenCacheKey cacheKey = kvp.Value.Key; resultEx = kvp.Value.Value; bool tokenNearExpiry = (resultEx.Result.ExpiresOn <= DateTime.UtcNow + TimeSpan.FromMinutes(ExpirationMarginInMinutes)); if (tokenNearExpiry) { resultEx.Result.AccessToken = null; PlatformPlugin.Logger.Verbose(callState, "An expired or near expiry token was found in the cache"); } else if (!cacheKey.ResourceEquals(cacheQueryData.Resource)) { PlatformPlugin.Logger.Verbose(callState, string.Format(CultureInfo.CurrentCulture, "Multi resource refresh token for resource '{0}' will be used to acquire token for '{1}'", cacheKey.Resource, cacheQueryData.Resource)); var newResultEx = new AuthenticationResultEx { Result = new AuthenticationResult(null, null, DateTimeOffset.MinValue), RefreshToken = resultEx.RefreshToken, ResourceInResponse = resultEx.ResourceInResponse }; newResultEx.Result.UpdateTenantAndUserInfo(resultEx.Result.TenantId, resultEx.Result.IdToken, resultEx.Result.UserInfo); resultEx = newResultEx; } else { PlatformPlugin.Logger.Verbose(callState, string.Format(CultureInfo.CurrentCulture, "{0} minutes left until token in cache expires", (resultEx.Result.ExpiresOn - DateTime.UtcNow).TotalMinutes)); } if (resultEx.Result.AccessToken == null && resultEx.RefreshToken == null) { this.tokenCacheDictionary.Remove(cacheKey); PlatformPlugin.Logger.Information(callState, "An old item was removed from the cache"); this.HasStateChanged = true; resultEx = null; } if (resultEx != null) { PlatformPlugin.Logger.Information(callState, "A matching item (access token or refresh token or both) was found in the cache"); } } else { PlatformPlugin.Logger.Information(callState, "No matching token was found in the cache"); } return(resultEx); } }