internal async Task <AuthenticationResultEx> LoadFromCacheAsync(CacheQueryData cacheQueryData, CallState callState)
        {
            AuthenticationResultEx resultEx = null;
            var aliasedHosts = await GetOrderedAliasesAsync(cacheQueryData.Authority, false, callState).ConfigureAwait(false);

            foreach (var aliasedHost in aliasedHosts)
            {
                cacheQueryData.Authority = ReplaceHost(cacheQueryData.Authority, aliasedHost);
                resultEx = LoadFromCacheCommon(cacheQueryData, callState);
                if (resultEx?.Result != null)
                {
                    break;
                }
            }

            return(resultEx);
        }
Пример #2
0
        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;
        }
Пример #3
0
        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, cacheQueryData.AssertionHash);

                List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > resourceSpecificItems =
                    items.Where(p => p.Key.ResourceEquals(cacheQueryData.Resource)).ToList();
                int 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.
                // this check only applies to user tokens. client tokens should be ignored.
                if (returnValue == null && cacheQueryData.SubjectType != TokenSubjectType.Client)
                {
                    List <KeyValuePair <TokenCacheKey, AuthenticationResultEx> > itemsForAllTenants = this.QueryCache(
                        null, cacheQueryData.ClientId, cacheQueryData.SubjectType, cacheQueryData.UniqueId,
                        cacheQueryData.DisplayableId, cacheQueryData.AssertionHash);
                    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)
                    {
                        returnValue = null;
                    }
                }

                return(returnValue);
            }
        }
Пример #4
0
        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.Clone();

                    bool tokenNearExpiry = (resultEx.Result.ExpiresOn <=
                                            DateTime.UtcNow + TimeSpan.FromMinutes(ExpirationMarginInMinutes));
                    bool tokenExtendedLifeTimeExpired = (resultEx.Result.ExtendedExpiresOn <=
                                                         DateTime.UtcNow);

                    //check for cross-tenant authority
                    if (!cacheKey.Authority.Equals(cacheQueryData.Authority))
                    {
                        // this is a cross-tenant result. use RT only
                        resultEx.Result.AccessToken = null;
                        PlatformPlugin.Logger.Information(callState,
                                                          "Cross Tenant refresh token was found in the cache");
                    }
                    else if (tokenNearExpiry && !cacheQueryData.ExtendedLifeTimeEnabled)
                    {
                        resultEx.Result.AccessToken = null;
                        PlatformPlugin.Logger.Information(callState,
                                                          "An expired or near expiry token was found in the cache");
                    }
                    else if (!cacheKey.ResourceEquals(cacheQueryData.Resource))
                    {
                        PlatformPlugin.Logger.Information(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 if (!tokenExtendedLifeTimeExpired && cacheQueryData.ExtendedLifeTimeEnabled && tokenNearExpiry)
                    {
                        resultEx.Result.ExtendedLifeTimeToken = true;
                        resultEx.Result.ExpiresOn             = resultEx.Result.ExtendedExpiresOn;
                        PlatformPlugin.Logger.Information(callState,
                                                          "The extendedLifeTime is enabled and a stale AT with extendedLifeTimeEnabled is returned.");
                    }
                    else if (tokenExtendedLifeTimeExpired)
                    {
                        resultEx.Result.AccessToken = null;
                        PlatformPlugin.Logger.Information(callState,
                                                          "The AT has expired its ExtendedLifeTime");
                    }
                    else
                    {
                        PlatformPlugin.Logger.Information(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);
            }
        }