public void GetAccessTokenExpiryInRangeTest() { cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem atItem = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, ScopeSet = TestConstants.Scope, RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId), TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromMinutes(4)) }; atItem.AccessToken = atItem.GetAccessTokenItemKey().ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[atItem.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(atItem); Assert.IsNull(cache.FindAccessToken(new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = TestConstants.Scope, User = new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier } })); }
/// <summary> /// Only used by dev test apps /// </summary> /// <param name="accessTokenCacheItem"></param> internal void SaveAccesTokenCacheItem(AccessTokenCacheItem accessTokenCacheItem) { lock (LockObject) { TokenCacheNotificationArgs args = new TokenCacheNotificationArgs { TokenCache = this, ClientId = ClientId, User = accessTokenCacheItem.User }; try { HasStateChanged = true; OnBeforeAccess(args); OnBeforeWrite(args); TokenCacheAccessor.SaveAccessToken(accessTokenCacheItem.GetAccessTokenItemKey().ToString(), JsonHelper.SerializeToJson(accessTokenCacheItem)); } finally { OnAfterAccess(args); HasStateChanged = false; } } }
internal MsalUserAccessTokenControl(TokenCache cache, AccessTokenCacheItem item) : this() { _cache = cache; _item = item; accessTokenAuthorityLabel.Text = _item.Authority; accessTokenScopesLabel.Text = _item.Scope; expiresOnLabel.Text = _item.ExpiresOn.ToString(); }
internal void AddAccessTokenCacheItem(AccessTokenCacheItem accessTokenCacheItem) { // this method is called by serialize and does not require // delegates because serialize itself is called from delegates lock (LockObject) { TokenCacheAccessor.SaveAccessToken(accessTokenCacheItem.GetAccessTokenItemKey().ToString(), JsonHelper.SerializeToJson(accessTokenCacheItem)); } }
protected virtual AuthenticationResult PostTokenRequest() { //save to cache if no access token item found //this means that no cached item was found if (AccessTokenItem == null) { AccessTokenItem = SaveTokenResponseToCache(); } return(new AuthenticationResult(AccessTokenItem)); }
public void DeserializeCacheItemWithDifferentVersion() { string differentVersionEntry = "{\"client_id\":\"client_id\",\"client_info\":\"eyJ1aWQiOiJteS1VSUQiLCJ1dGlkIjoibXktVVRJRCJ9\",\"ver\":5,\"access_token\":\"access-token\",\"authority\":\"https:\\\\/\\\\/login.microsoftonline.com\\\\/home\\\\/\",\"expires_on\":1494025355,\"id_token\":\"someheader.eyJhdWQiOiAiZTg1NGE0YTctNmMzNC00NDljLWIyMzctZmM3YTI4MDkzZDg0IiwiaXNzIjogImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbS82YzNkNTFkZC1mMGU1LTQ5NTktYjRlYS1hODBjNGUzNmZlNWUvdjIuMC8iLCJpYXQiOiAxNDU1ODMzODI4LCJuYmYiOiAxNDU1ODMzODI4LCJleHAiOiAxNDU1ODM3NzI4LCJpcGFkZHIiOiAiMTMxLjEwNy4xNTkuMTE3IiwibmFtZSI6ICJNYXJycnJyaW8gQm9zc3kiLCJvaWQiOiAidW5pcXVlX2lkIiwicHJlZmVycmVkX3VzZXJuYW1lIjogImRpc3BsYXlhYmxlQGlkLmNvbSIsInN1YiI6ICJLNF9TR0d4S3FXMVN4VUFtaGc2QzFGNlZQaUZ6Y3gtUWQ4MGVoSUVkRnVzIiwidGlkIjogIm15LWlkcCIsInZlciI6ICIyLjAifQ.somesignature\",\"scope\":\"r1\\\\/scope1 r1\\\\/scope2\",\"token_type\":\"Bearer\",\"user_assertion_hash\":null}"; TokenCache cache = new TokenCache() { ClientId = TestConstants.ClientId }; cache.AddAccessTokenCacheItem(JsonHelper.DeserializeFromJson <AccessTokenCacheItem>(differentVersionEntry)); ICollection <AccessTokenCacheItem> items = cache.GetAllAccessTokensForClient(new RequestContext(Guid.Empty, null)); Assert.AreEqual(1, items.Count); AccessTokenCacheItem item = items.First(); Assert.AreEqual(5, item.Version); }
internal ICollection <AccessTokenCacheItem> GetAllAccessTokensForClient(RequestContext requestContext) { lock (LockObject) { ICollection <AccessTokenCacheItem> allAccessTokens = new List <AccessTokenCacheItem>(); foreach (var accessTokenString in TokenCacheAccessor.GetAllAccessTokensAsString()) { AccessTokenCacheItem accessTokenCacheItem = JsonHelper.DeserializeFromJson <AccessTokenCacheItem>(accessTokenString); if (accessTokenCacheItem.ClientId.Equals(ClientId)) { allAccessTokens.Add(accessTokenCacheItem); } } return(allAccessTokens); } }
public void GetIntersectedScopesMatchedAccessTokenTest() { TokenCache cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem atItem = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ScopeSet = TestConstants.Scope, ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromHours(1)), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId) }; // create key out of access token cache item and then // set it as the value of the access token. AccessTokenCacheKey atKey = atItem.GetAccessTokenItemKey(); atItem.AccessToken = atKey.ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[atKey.ToString()] = JsonHelper.SerializeToJson(atItem); var param = new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = new SortedSet <string>(), User = new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier } }; param.Scope.Add(TestConstants.Scope.First()); param.Scope.Add("non-existant-scopes"); AccessTokenCacheItem item = cache.FindAccessToken(param); //intersected scopes are not returned. Assert.IsNull(item); }
public void GetSubsetScopesMatchedAccessTokenTest() { TokenCache cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem atItem = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ScopeSet = TestConstants.Scope, Scope = TestConstants.Scope.AsSingleString(), ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromHours(1)), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId), RawClientInfo = MockHelpers.CreateClientInfo(), }; atItem.IdToken = IdToken.Parse(atItem.RawIdToken); atItem.ClientInfo = ClientInfo.CreateFromJson(atItem.RawClientInfo); // create key out of access token cache item and then // set it as the value of the access token. AccessTokenCacheKey atKey = atItem.GetAccessTokenItemKey(); atItem.AccessToken = atKey.ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[atKey.ToString()] = JsonHelper.SerializeToJson(atItem); var param = new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = new SortedSet <string>(), User = TestConstants.User }; param.Scope.Add("r1/scope1"); AccessTokenCacheItem item = cache.FindAccessToken(param); Assert.IsNotNull(item); Assert.AreEqual(atKey.ToString(), item.AccessToken); }
internal AccessTokenCacheItemDetails(AccessTokenCacheItem accessTokenCacheItem) { InitializeComponent(); authorityLabel.Text = accessTokenCacheItem.Authority; clientIdLabel.Text = accessTokenCacheItem.ClientId; userDisplayableIdLabel.Text = accessTokenCacheItem.User.DisplayableId; userNameLabel.Text = accessTokenCacheItem.User.Name; userIdentityProviderLabel.Text = accessTokenCacheItem.User.IdentityProvider; expiresOnLabel.Text = accessTokenCacheItem.ExpiresOn.ToString(); scopesLabel.Text = accessTokenCacheItem.Scope; clientInfoUniqueIdentifierLabel.Text = accessTokenCacheItem.ClientInfo.UniqueIdentifier; clientInfoUniqueTenantIdentifierLabel.Text = accessTokenCacheItem.ClientInfo.UniqueTenantIdentifier; accessTokenLabel.Text = StringShortenerConverter.GetShortStr(accessTokenCacheItem.AccessToken, 100); }
public void GetExpiredAccessTokenTest() { cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem item = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId), RawClientInfo = MockHelpers.CreateClientInfo(), ScopeSet = TestConstants.Scope }; item.IdToken = IdToken.Parse(item.RawIdToken); item.ClientInfo = ClientInfo.CreateFromJson(item.RawClientInfo); item.AccessToken = item.GetAccessTokenItemKey().ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[item.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(item); cache.TokenCacheAccessor.AccessTokenCacheDictionary[item.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(item); Assert.IsNull(cache.FindAccessToken(new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = TestConstants.Scope, User = new User() { DisplayableId = TestConstants.DisplayableId, Identifier = TestConstants.UserIdentifier } })); }
public void GetAccessTokenMatchedUserAssertionInCacheTest() { TokenCache cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem atItem = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ScopeSet = TestConstants.Scope, Scope = TestConstants.Scope.AsSingleString(), ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromHours(1)), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId) }; // create key out of access token cache item and then // set it as the value of the access token. AccessTokenCacheKey atKey = atItem.GetAccessTokenItemKey(); atItem.AccessToken = atKey.ToString(); atItem.UserAssertionHash = CryptographyHelper.CreateBase64UrlEncodedSha256Hash(atKey.ToString()); cache.TokenCacheAccessor.AccessTokenCacheDictionary[atKey.ToString()] = JsonHelper.SerializeToJson(atItem); var param = new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = TestConstants.Scope, UserAssertion = new UserAssertion(atKey.ToString()) }; cache.AfterAccess = AfterAccessNoChangeNotification; AccessTokenCacheItem item = cache.FindAccessToken(param); Assert.IsNotNull(item); Assert.AreEqual(atKey.ToString(), item.AccessToken); }
public static void PopulateCache(TokenCacheAccessor accessor) { AccessTokenCacheItem item = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(new DateTimeOffset(DateTime.UtcNow + TimeSpan.FromSeconds(ValidExpiresIn))), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId), RawClientInfo = MockHelpers.CreateClientInfo(), Scope = TestConstants.Scope.AsSingleString(), ScopeSet = TestConstants.Scope }; item.IdToken = IdToken.Parse(item.RawIdToken); item.ClientInfo = ClientInfo.CreateFromJson(item.RawClientInfo); item.AccessToken = item.GetAccessTokenItemKey().ToString(); //add access token accessor.AccessTokenCacheDictionary[item.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(item); item = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityGuestTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(new DateTimeOffset(DateTime.UtcNow + TimeSpan.FromSeconds(ValidExpiresIn))), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId + "more", TestConstants.DisplayableId), RawClientInfo = MockHelpers.CreateClientInfo(), Scope = TestConstants.ScopeForAnotherResource.AsSingleString(), ScopeSet = TestConstants.ScopeForAnotherResource }; item.IdToken = IdToken.Parse(item.RawIdToken); item.ClientInfo = ClientInfo.CreateFromJson(item.RawClientInfo); item.AccessToken = item.GetAccessTokenItemKey().ToString(); //add another access token accessor.AccessTokenCacheDictionary[item.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(item); AddRefreshTokenToCache(accessor, TestConstants.Uid, TestConstants.Utid, TestConstants.Name); }
public void GetAccessTokenUserAssertionMismatchInCacheTest() { TokenCache cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem atItem = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ScopeSet = TestConstants.Scope, ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromHours(1)), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId) }; // create key out of access token cache item and then // set it as the value of the access token. AccessTokenCacheKey atKey = atItem.GetAccessTokenItemKey(); atItem.AccessToken = atKey.ToString(); atItem.UserAssertionHash = CryptographyHelper.CreateBase64UrlEncodedSha256Hash(atKey.ToString()); cache.TokenCacheAccessor.AccessTokenCacheDictionary[atKey.ToString()] = JsonHelper.SerializeToJson(atItem); var param = new AuthenticationRequestParameters() { RequestContext = new RequestContext(Guid.Empty, null), ClientId = TestConstants.ClientId, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), Scope = TestConstants.Scope, UserAssertion = new UserAssertion(atItem.UserAssertionHash + "-random") }; AccessTokenCacheItem item = cache.FindAccessToken(param); // cache lookup should fail because there was userassertion hash did not match the one // stored in token cache item. Assert.IsNull(item); }
public void GetAppTokenFromCacheTest() { cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem item = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromSeconds(ValidExpiresIn)), RawIdToken = null, RawClientInfo = null, User = null, Scope = TestConstants.Scope.AsSingleString(), ScopeSet = TestConstants.Scope }; item.AccessToken = item.GetAccessTokenItemKey().ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[item.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(item); AccessTokenCacheItem cacheItem = cache.FindAccessToken(new AuthenticationRequestParameters() { IsClientCredentialRequest = true, RequestContext = new RequestContext(Guid.Empty, null), Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), ClientId = TestConstants.ClientId, ClientCredential = TestConstants.CredentialWithSecret, Scope = TestConstants.Scope }); Assert.IsNotNull(cacheItem); Assert.AreEqual(item.GetAccessTokenItemKey().ToString(), cacheItem.GetAccessTokenItemKey().ToString()); }
internal void DeleteAccessToken(AccessTokenCacheItem accessTokenCacheItem) { lock (LockObject) { try { TokenCacheNotificationArgs args = new TokenCacheNotificationArgs { TokenCache = this, ClientId = ClientId, User = accessTokenCacheItem.User }; OnBeforeAccess(args); OnBeforeWrite(args); TokenCacheAccessor.DeleteAccessToken(accessTokenCacheItem.GetAccessTokenItemKey().ToString()); OnAfterAccess(args); } finally { HasStateChanged = false; } } }
public void NoCacheLookup() { Authority authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false); cache = new TokenCache() { ClientId = TestConstants.ClientId }; AccessTokenCacheItem atItem = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId), RawClientInfo = MockHelpers.CreateClientInfo(), TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow + TimeSpan.FromSeconds(3599)), ScopeSet = TestConstants.Scope }; atItem.IdToken = IdToken.Parse(atItem.RawIdToken); atItem.ClientInfo = ClientInfo.CreateFromJson(atItem.RawClientInfo); AccessTokenCacheKey atKey = atItem.GetAccessTokenItemKey(); atItem.AccessToken = atKey.ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[atKey.ToString()] = JsonHelper.SerializeToJson(atItem); MockWebUI ui = new MockWebUI() { MockResult = new AuthorizationResult(AuthorizationStatus.Success, TestConstants.AuthorityHomeTenant + "?code=some-code") }; //add mock response for tenant endpoint discovery HttpMessageHandlerFactory.AddMockHandler(new MockHttpMessageHandler { Method = HttpMethod.Get, ResponseMessage = MockHelpers.CreateOpenIdConfigurationResponse(TestConstants.AuthorityHomeTenant) }); MockHttpMessageHandler mockHandler = new MockHttpMessageHandler(); mockHandler.Method = HttpMethod.Post; mockHandler.ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage(); HttpMessageHandlerFactory.AddMockHandler(mockHandler); AuthenticationRequestParameters parameters = new AuthenticationRequestParameters() { Authority = authority, ClientId = TestConstants.ClientId, Scope = TestConstants.Scope, TokenCache = cache, RequestContext = new RequestContext(Guid.Empty, null) }; parameters.RedirectUri = new Uri("some://uri"); parameters.ExtraQueryParameters = "extra=qp"; InteractiveRequest request = new InteractiveRequest(parameters, TestConstants.ScopeForAnotherResource.ToArray(), TestConstants.DisplayableId, UIBehavior.SelectAccount, ui); Task <AuthenticationResult> task = request.RunAsync(); task.Wait(); AuthenticationResult result = task.Result; Assert.IsNotNull(result); Assert.AreEqual(1, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); Assert.AreEqual(2, cache.TokenCacheAccessor.AccessTokenCacheDictionary.Count); Assert.AreEqual(result.AccessToken, "some-access-token"); Assert.IsTrue(HttpMessageHandlerFactory.IsMocksQueueEmpty, "All mocks should have been consumed"); Assert.IsNotNull(_myReceiver.EventsReceived.Find(anEvent => // Expect finding such an event anEvent[EventBase.EventNameKey].EndsWith("ui_event") && anEvent[UiEvent.UserCancelledKey] == "false")); Assert.IsNotNull(_myReceiver.EventsReceived.Find(anEvent => // Expect finding such an event anEvent[EventBase.EventNameKey].EndsWith("api_event") && anEvent[ApiEvent.UiBehaviorKey] == "select_account")); }
private AccessTokenCacheItem FindAccessTokenCommon(AuthenticationRequestParameters requestParams) { lock (LockObject) { requestParams.RequestContext.Logger.Info("Looking up access token in the cache.."); AccessTokenCacheItem accessTokenCacheItem = null; TokenCacheNotificationArgs args = new TokenCacheNotificationArgs { TokenCache = this, ClientId = ClientId, User = requestParams.User }; OnBeforeAccess(args); //filtered by client id. ICollection <AccessTokenCacheItem> tokenCacheItems = GetAllAccessTokensForClient(requestParams.RequestContext); OnAfterAccess(args); // this is OBO flow. match the cache entry with assertion hash, // Authority, ScopeSet and client Id. if (requestParams.UserAssertion != null) { requestParams.RequestContext.Logger.Info("Filtering by user assertion..."); tokenCacheItems = tokenCacheItems.Where( item => !string.IsNullOrEmpty(item.UserAssertionHash) && item.UserAssertionHash.Equals(requestParams.UserAssertion.AssertionHash)) .ToList(); } else { if (!requestParams.IsClientCredentialRequest) { requestParams.RequestContext.Logger.Info("Filtering by user identifier..."); //filter by identifier of the user instead tokenCacheItems = tokenCacheItems .Where(item => item.GetUserIdentifier().Equals(requestParams.User?.Identifier)) .ToList(); } } //no match found after initial filtering if (!tokenCacheItems.Any()) { requestParams.RequestContext.Logger.Info("No matching entry found for user or assertion"); return(null); } requestParams.RequestContext.Logger.Info("Matching entry count - " + tokenCacheItems.Count); IEnumerable <AccessTokenCacheItem> filteredItems = tokenCacheItems.Where( item => item.ScopeSet.ScopeContains(requestParams.Scope)) .ToList(); requestParams.RequestContext.Logger.Info("Matching entry count after filtering by scopes - " + filteredItems.Count()); //no authority passed if (requestParams.Authority == null) { requestParams.RequestContext.Logger.Info("No authority provided.."); //if only one cached token found if (filteredItems.Count() == 1) { accessTokenCacheItem = filteredItems.First(); requestParams.Authority = Authority.CreateAuthority(accessTokenCacheItem.Authority, requestParams.ValidateAuthority); requestParams.RequestContext.Logger.Info("1 matching entry found. Authority may be used for refreshing access token."); } else if (filteredItems.Count() > 1) { requestParams.RequestContext.Logger.Error( "Multiple authorities found for same client_id, user and scopes"); requestParams.RequestContext.Logger.ErrorPii( "Multiple authorities found for same client_id, user and scopes :- " + filteredItems .Select(tci => tci.Authority) .AsSingleString()); throw new MsalClientException(MsalClientException.MultipleTokensMatchedError, MsalErrorMessage.MultipleTokensMatched); } else { requestParams.RequestContext.Logger.Info("No tokens found for matching client_id, user and scopes."); requestParams.RequestContext.Logger.Info("Check if the tokens are for the same authority for given client_id and user."); //no match found. check if there was a single authority used IEnumerable <string> authorityList = tokenCacheItems.Select(tci => tci.Authority).Distinct(); if (authorityList.Count() > 1) { requestParams.RequestContext.Logger.Error( "Multiple authorities found for same client_id and user."); requestParams.RequestContext.Logger.ErrorPii( "MMultiple authorities found for same client_id and user. :- " + authorityList .AsSingleString()); throw new MsalClientException(MsalClientException.MultipleTokensMatchedError, "Multiple authorities found in the cache. Pass in authority in the API overload."); } requestParams.RequestContext.Logger.Info("Distinct Authority found. Use it for refresh token grant call"); requestParams.Authority = Authority.CreateAuthority(authorityList.First(), requestParams.ValidateAuthority); } } else { requestParams.RequestContext.Logger.Info("Authority provided.."); //authority was passed in the API filteredItems = filteredItems.Where( item => item.Authority.Equals(requestParams.Authority.CanonicalAuthority)) .ToList(); //no match if (!filteredItems.Any()) { requestParams.RequestContext.Logger.Info("No tokens found for matching authority, client_id, user and scopes."); return(null); } //if only one cached token found if (filteredItems.Count() == 1) { accessTokenCacheItem = filteredItems.First(); } else { requestParams.RequestContext.Logger.Error( "Multiple tokens found for matching authority, client_id, user and scopes."); throw new MsalClientException(MsalClientException.MultipleTokensMatchedError, MsalErrorMessage.MultipleTokensMatched); } } if (accessTokenCacheItem != null && accessTokenCacheItem.ExpiresOn > DateTime.UtcNow + TimeSpan.FromMinutes(DefaultExpirationBufferInMinutes)) { requestParams.RequestContext.Logger.Info("Access token is not expired. Returning the found cache entry.."); return(accessTokenCacheItem); } if (accessTokenCacheItem != null) { requestParams.RequestContext.Logger.Info( "Access token has expired or about to expire. Current time (" + DateTime.UtcNow + ") - Expiration Time (" + accessTokenCacheItem.ExpiresOn + ")"); } return(null); } }
internal AccessTokenCacheItem SaveAccessAndRefreshToken(AuthenticationRequestParameters requestParams, TokenResponse response) { lock (LockObject) { try { // create the access token cache item AccessTokenCacheItem accessTokenCacheItem = new AccessTokenCacheItem(requestParams.TenantUpdatedCanonicalAuthority, requestParams.ClientId, response) { UserAssertionHash = requestParams.UserAssertion?.AssertionHash }; TokenCacheNotificationArgs args = new TokenCacheNotificationArgs { TokenCache = this, ClientId = ClientId, User = accessTokenCacheItem.User }; HasStateChanged = true; OnBeforeAccess(args); OnBeforeWrite(args); //delete all cache entries with intersecting scopes. //this should not happen but we have this as a safe guard //against multiple matches. requestParams.RequestContext.Logger.Info( "Looking for scopes for the authority in the cache which intersect with " + requestParams.Scope.AsSingleString()); IList <AccessTokenCacheItem> accessTokenItemList = new List <AccessTokenCacheItem>(); foreach (var accessTokenString in TokenCacheAccessor.GetAllAccessTokensAsString()) { AccessTokenCacheItem accessTokenItem = JsonHelper.DeserializeFromJson <AccessTokenCacheItem>(accessTokenString); if (accessTokenItem.ClientId.Equals(ClientId) && accessTokenItem.Authority.Equals(requestParams.TenantUpdatedCanonicalAuthority) && accessTokenItem.ScopeSet.ScopeIntersects(accessTokenCacheItem.ScopeSet)) { requestParams.RequestContext.Logger.Verbose( "Intersecting scopes found - " + accessTokenItem.Scope); accessTokenItemList.Add(accessTokenItem); } } requestParams.RequestContext.Logger.Info( "Intersecting scope entries count - " + accessTokenItemList.Count); if (!requestParams.IsClientCredentialRequest) { //filter by identifer of the user instead accessTokenItemList = accessTokenItemList.Where( item => item.GetUserIdentifier().Equals(accessTokenCacheItem.GetUserIdentifier())) .ToList(); requestParams.RequestContext.Logger.Info( "Matching entries after filtering by user - " + accessTokenItemList.Count); } foreach (var cacheItem in accessTokenItemList) { TokenCacheAccessor.DeleteAccessToken(cacheItem.GetAccessTokenItemKey().ToString(), requestParams.RequestContext); } TokenCacheAccessor.SaveAccessToken(accessTokenCacheItem.GetAccessTokenItemKey().ToString(), JsonHelper.SerializeToJson(accessTokenCacheItem), requestParams.RequestContext); // if server returns the refresh token back, save it in the cache. if (response.RefreshToken != null) { // create the refresh token cache item RefreshTokenCacheItem refreshTokenCacheItem = new RefreshTokenCacheItem( requestParams.Authority.Host, requestParams.ClientId, response); requestParams.RequestContext.Logger.Info("Saving RT in cache..."); TokenCacheAccessor.SaveRefreshToken(refreshTokenCacheItem.GetRefreshTokenItemKey().ToString(), JsonHelper.SerializeToJson(refreshTokenCacheItem), requestParams.RequestContext); } OnAfterAccess(args); return(accessTokenCacheItem); } finally { HasStateChanged = false; } } }
public void GetUsersTest() { PublicClientApplication app = new PublicClientApplication(TestConstants.ClientId); IEnumerable <IUser> users = app.Users; Assert.IsNotNull(users); Assert.IsFalse(users.Any()); cache = new TokenCache() { ClientId = TestConstants.ClientId }; app.UserTokenCache = cache; TokenCacheHelper.PopulateCache(cache.TokenCacheAccessor); users = app.Users; Assert.IsNotNull(users); Assert.AreEqual(1, users.Count()); AccessTokenCacheItem item = new AccessTokenCacheItem() { Authority = TestConstants.AuthorityHomeTenant, ClientId = TestConstants.ClientId, TokenType = "Bearer", ExpiresOnUnixTimestamp = MsalHelpers.DateTimeToUnixTimestamp((DateTime.UtcNow + TimeSpan.FromSeconds(3600))), RawIdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId), RawClientInfo = MockHelpers.CreateClientInfo(), ScopeSet = TestConstants.Scope }; item.IdToken = IdToken.Parse(item.RawIdToken); item.ClientInfo = ClientInfo.CreateFromJson(item.RawClientInfo); item.AccessToken = item.GetAccessTokenItemKey().ToString(); cache.TokenCacheAccessor.AccessTokenCacheDictionary[item.GetAccessTokenItemKey().ToString()] = JsonHelper.SerializeToJson(item); // another cache entry for different uid. user count should be 2. RefreshTokenCacheItem rtItem = new RefreshTokenCacheItem() { Environment = TestConstants.ProductionEnvironment, ClientId = TestConstants.ClientId, RefreshToken = "someRT", RawClientInfo = MockHelpers.CreateClientInfo(TestConstants.Uid + "more", TestConstants.Utid), DisplayableId = TestConstants.DisplayableId, IdentityProvider = TestConstants.IdentityProvider, Name = TestConstants.Name }; rtItem.ClientInfo = ClientInfo.CreateFromJson(rtItem.RawClientInfo); cache.TokenCacheAccessor.RefreshTokenCacheDictionary[rtItem.GetRefreshTokenItemKey().ToString()] = JsonHelper.SerializeToJson(rtItem); Assert.AreEqual(2, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); users = app.Users; Assert.IsNotNull(users); Assert.AreEqual(2, users.Count()); // another cache entry for different environment. user count should still be 2. Sovereign cloud user must not be returned rtItem = new RefreshTokenCacheItem() { Environment = TestConstants.SovereignEnvironment, ClientId = TestConstants.ClientId, RefreshToken = "someRT", RawClientInfo = MockHelpers.CreateClientInfo(TestConstants.Uid + "more1", TestConstants.Utid), DisplayableId = TestConstants.DisplayableId, IdentityProvider = TestConstants.IdentityProvider, Name = TestConstants.Name }; rtItem.ClientInfo = ClientInfo.CreateFromJson(rtItem.RawClientInfo); cache.TokenCacheAccessor.RefreshTokenCacheDictionary[rtItem.GetRefreshTokenItemKey().ToString()] = JsonHelper.SerializeToJson(rtItem); Assert.AreEqual(3, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); users = app.Users; Assert.IsNotNull(users); Assert.AreEqual(2, users.Count()); }
internal AuthenticationResult(AccessTokenCacheItem accessTokenCacheItem) { _accessTokenCacheItem = accessTokenCacheItem; }
public void SerializeDeserializeCacheTest() { TokenCache cache = new TokenCache() { ClientId = TestConstants.ClientId }; TokenResponse response = new TokenResponse(); response.IdToken = MockHelpers.CreateIdToken(TestConstants.UniqueId, TestConstants.DisplayableId); response.ClientInfo = MockHelpers.CreateClientInfo(); response.AccessToken = "access-token"; response.ExpiresIn = 3599; response.CorrelationId = "correlation-id"; response.RefreshToken = "refresh-token"; response.Scope = TestConstants.Scope.AsSingleString(); response.TokenType = "Bearer"; RequestContext requestContext = new RequestContext(Guid.NewGuid(), null); AuthenticationRequestParameters requestParams = new AuthenticationRequestParameters() { RequestContext = requestContext, Authority = Authority.CreateAuthority(TestConstants.AuthorityHomeTenant, false), ClientId = TestConstants.ClientId, TenantUpdatedCanonicalAuthority = TestConstants.AuthorityHomeTenant }; cache.SaveAccessAndRefreshToken(requestParams, response); byte[] serializedCache = cache.Serialize(); cache.TokenCacheAccessor.AccessTokenCacheDictionary.Clear(); cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Clear(); Assert.AreEqual(0, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); Assert.AreEqual(0, cache.TokenCacheAccessor.AccessTokenCacheDictionary.Count); cache.Deserialize(serializedCache); Assert.AreEqual(1, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); Assert.AreEqual(1, cache.TokenCacheAccessor.AccessTokenCacheDictionary.Count); serializedCache = cache.Serialize(); cache.Deserialize(serializedCache); //item count should not change because old cache entries should have //been overriden Assert.AreEqual(1, cache.TokenCacheAccessor.RefreshTokenCacheDictionary.Count); Assert.AreEqual(1, cache.TokenCacheAccessor.AccessTokenCacheDictionary.Count); AccessTokenCacheItem atItem = cache.GetAllAccessTokensForClient(requestContext).First(); Assert.AreEqual(response.AccessToken, atItem.AccessToken); Assert.AreEqual(TestConstants.AuthorityHomeTenant, atItem.Authority); Assert.AreEqual(TestConstants.ClientId, atItem.ClientId); Assert.AreEqual(response.TokenType, atItem.TokenType); Assert.AreEqual(response.Scope, atItem.ScopeSet.AsSingleString()); Assert.AreEqual(response.IdToken, atItem.RawIdToken); RefreshTokenCacheItem rtItem = cache.GetAllRefreshTokensForClient(requestContext).First(); Assert.AreEqual(response.RefreshToken, rtItem.RefreshToken); Assert.AreEqual(TestConstants.ClientId, rtItem.ClientId); Assert.AreEqual(TestConstants.UserIdentifier, rtItem.GetUserIdentifier()); Assert.AreEqual(TestConstants.ProductionEnvironment, rtItem.Environment); }