public void TestScopeContains()
        {
            //null scope
            TokenCacheKey key = new TokenCacheKey(TestConstants.DefaultAuthorityHomeTenant,
                                                  null, TestConstants.DefaultClientId,
                                                  TestConstants.DefaultUniqueId, TestConstants.DefaultDisplayableId, TestConstants.DefaultHomeObjectId,
                                                  TestConstants.DefaultPolicy);

            //null will contain null
            HashSet <string> otherScope = null;

            Assert.IsTrue(key.ScopeContains(otherScope));
            Assert.IsFalse(key.ScopeContains(new HashSet <string>()));

            //put scope value
            key = new TokenCacheKey(TestConstants.DefaultAuthorityHomeTenant,
                                    TestConstants.DefaultScope, TestConstants.DefaultClientId,
                                    TestConstants.DefaultUniqueId, TestConstants.DefaultDisplayableId, TestConstants.DefaultHomeObjectId,
                                    TestConstants.DefaultPolicy);
            Assert.IsTrue(key.ScopeContains(otherScope));
            Assert.IsTrue(key.ScopeContains(new HashSet <string>()));

            otherScope = new HashSet <string>(TestConstants.DefaultScope.ToArray());
            Assert.IsTrue(key.ScopeContains(otherScope));

            // other scope has more
            otherScope.Add("anotherscope");
            Assert.IsFalse(key.ScopeContains(otherScope));
        }
Example #2
0
        internal virtual AuthenticationResultEx LoadFromCache(string authority, HashSet <string> scope, string clientId, User user, string policy, CallState callState)
        {
            lock (lockObject)
            {
                PlatformPlugin.Logger.Verbose(callState, "Looking up cache for a token...");
                AuthenticationResultEx resultEx = null;

                //get either a matching token or an MRRT supported RT
                KeyValuePair <TokenCacheKey, AuthenticationResultEx>?kvp = this.LoadSingleItemFromCache(authority, scope,
                                                                                                        clientId, user, policy, callState);
                TokenCacheKey cacheKey = null;
                if (kvp.HasValue)
                {
                    cacheKey = kvp.Value.Key;
                    resultEx = kvp.Value.Value;
                    bool tokenNearExpiry = (resultEx.Result.ExpiresOn <=
                                            DateTime.UtcNow + TimeSpan.FromMinutes(Constant.ExpirationMarginInMinutes));
                    if (!cacheKey.ScopeContains(scope) ||
                        (!Authenticator.IsTenantLess(authority) && !authority.Equals(cacheKey.Authority)) ||
                        !clientId.Equals(cacheKey.ClientId))
                    {
                        //requested scope are not a subset or authority does not match (cross-tenant RT) or client id is not same (FoCI).
                        PlatformPlugin.Logger.Verbose(callState,
                                                      string.Format(CultureInfo.InvariantCulture, "Refresh token for scope '{0}' will be used to acquire token for '{1}'",
                                                                    cacheKey.Scope.AsSingleString(),
                                                                    scope.AsSingleString()));

                        resultEx = CreateResultExFromCacheResultEx(cacheKey, resultEx);
                    }
                    else if (tokenNearExpiry)
                    {
                        resultEx.Result.Token = null;
                        PlatformPlugin.Logger.Verbose(callState,
                                                      "An expired or near expiry token was found in the cache");
                    }
                    else
                    {
                        PlatformPlugin.Logger.Verbose(callState,
                                                      string.Format(CultureInfo.InvariantCulture, "{0} minutes left until token in cache expires",
                                                                    (resultEx.Result.ExpiresOn - DateTime.UtcNow).TotalMinutes));
                    }

                    // client credential tokens do not have associated refresh tokens.
                    if (resultEx.Result.Token == 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");
                    }
                }

                return(resultEx);
            }
        }