public async Task Store_Grant_And_Retrieve_It() { var key = Guid.NewGuid().ToString("N"); var grant = new IdentityServer4.Models.PersistedGrant { Key = key, Expiration = DateTime.UtcNow.AddDays(1), Type = "test", ClientId = "client1", SubjectId = "sub1", SessionId = "session1", CreationTime = DateTime.UtcNow, Description = "des", Data = "bla bla", ConsumedTime = DateTime.UtcNow }; await persistedGrantStore.StoreAsync(grant); var item = await persistedGrantStore.GetAsync(key); item.Should().NotBeNull(); item.Key.Should().Be(key); item.Type.Should().Be(grant.Type); item.ClientId.Should().Be(grant.ClientId); item.SubjectId.Should().Be(grant.SubjectId); item.Data.Should().Be(grant.Data); item.Description.Should().Be(grant.Description); item.SessionId.Should().Be(grant.SessionId); item.CreationTime.Should().NotBe(new DateTime()); item.Expiration.Should().NotBeNull(); item.ConsumedTime.Should().NotBeNull(); }
public void CanCreateAndUpdateAndDeletePersistedGrant() { IPersistedGrantStore store = Fixture.GetService <IPersistedGrantStore>(); Client client = CreateClient(); Provider.AddClientAsync(client).Wait(); PersistedGrant grant = CreateGrant(client.ClientId); PersistedGrant result = store.GetAsync(grant.Key).Result; Assert.Null(result); Provider.AddPersistedGrantAsync(grant).Wait(); result = store.GetAsync(grant.Key).Result; Assert.NotNull(result); Assert.NotEqual("test", result.Data); result.Data = "test"; Provider.UpdatePersistedGrantAsync(result).Wait(); result = store.GetAsync(grant.Key).Result; Assert.NotNull(result); Assert.Equal("test", result.Data); Provider.RemovePersistedGrantAsync(result).Wait(); result = store.GetAsync(grant.Key).Result; Assert.Null(result); }
public async Task CopyAsync(string sourceKey, string destinationKey) { var source = await _innerPersistedGrantStore.GetAsync(sourceKey); if (source != null) { source.Key = destinationKey; await StoreAsync(source); } }
/// <summary> /// Gets the item. /// </summary> /// <param name="key">The key.</param> /// <returns></returns> protected async Task <T> GetItemAsync(string key) { var hashedKey = GetHashedKey(key); var grant = await _store.GetAsync(hashedKey); if (grant != null && grant.Type == _grantType) { if (!grant.Expiration.HasExpired()) { try { return(_serializer.Deserialize <T>(grant.Data)); } catch (Exception ex) { _logger.LogError("Failed to deserailize JSON from grant store. Exception: {0}", ex.Message); } } else { _logger.LogDebug("{grantType} grant with value: {key} found in store, but has expired.", _grantType, key); } } else { _logger.LogDebug("{grantType} grant with value: {key} not found in store.", _grantType, key); } return(default(T)); }
public async Task StoreAsync_WhenPersistedGrantStored_ExpectSuccess() { // Arrange var persistedGrant = UniquePersistedGrant; // Act await _persistedGrantStore.StoreAsync(persistedGrant); // Assert var foundPersistedGrant = await _persistedGrantStore.GetAsync(persistedGrant.Key); // Assert Assert.IsNotNull(foundPersistedGrant); }
public void PersistedGrantStore() { IPersistedGrantStore store = Fixture.GetService <IPersistedGrantStore>(); Client client = CreateClient(); Provider.AddClientAsync(client).Wait(); PersistedGrant grant1 = CreateGrant(client.ClientId, "aaa", "t1"); PersistedGrant grant2 = CreateGrant(client.ClientId, "aaa"); PersistedGrant grant3 = CreateGrant(client.ClientId, "aaa"); PersistedGrant grant4 = CreateGrant(client.ClientId); PersistedGrant grant5 = CreateGrant(client.ClientId); store.StoreAsync(grant1).Wait(); store.StoreAsync(grant2).Wait(); store.StoreAsync(grant3).Wait(); store.StoreAsync(grant4).Wait(); store.StoreAsync(grant5).Wait(); List <PersistedGrant> results = store.GetAllAsync("aaa").Result?.ToList(); Assert.Equal(3, results.Count); store.RemoveAllAsync("aaa", grant1.ClientId, "t1").Wait(); results = store.GetAllAsync("aaa").Result?.ToList(); Assert.Equal(2, results.Count); store.RemoveAllAsync("aaa", grant1.ClientId).Wait(); results = store.GetAllAsync("aaa").Result?.ToList(); Assert.Empty(results); PersistedGrant result = store.GetAsync(grant5.Key).Result; Assert.NotNull(result); store.RemoveAsync(grant5.Key); result = store.GetAsync(grant5.Key).Result; Assert.Null(result); }
async Task <T> GetItem <T>(string key, string type) { key = HashKey(key, type); var grant = await _store.GetAsync(key); if (grant != null && grant.Type == type) { return(_serializer.Deserialize <T>(grant.Data)); } return(default(T)); }
protected async Task <T> GetItemAsync(string key) { key = GetHashedKey(key); var grant = await _store.GetAsync(key); if (grant != null && grant.Type == _grantType) { return(_serializer.Deserialize <T>(grant.Data)); } return(default(T)); }
/// <summary> /// Gets the item. /// </summary> /// <param name="key">The key.</param> /// <returns></returns> protected async Task <T> GetItemAsync(string key) { key = GetHashedKey(key); var grant = await _store.GetAsync(key); if (grant != null && grant.Type == _grantType && !grant.Expiration.HasExpired()) { try { return(_serializer.Deserialize <T>(grant.Data)); } catch (Exception ex) { _logger.LogError("Failed to deserailize JSON from grant store. Exception: {0}", ex.Message); } } return(default(T)); }
public async Task Persist_Grant_Get() { var persistedGrant = await _persistedGrantStore.GetAsync(_currentId); persistedGrant.Should().NotBeNull(); persistedGrant.ClientId.Should().Be(_currentPersistedGrant.ClientId); persistedGrant.CreationTime.Should().Be(_currentPersistedGrant.CreationTime); persistedGrant.Data.Should().Be(_currentPersistedGrant.Data); persistedGrant.Expiration.Should().Be(_currentPersistedGrant.Expiration); persistedGrant.Key.Should().Be(_currentPersistedGrant.Key); persistedGrant.SubjectId.Should().Be(_currentPersistedGrant.SubjectId); persistedGrant.Type.Should().Be(_currentPersistedGrant.Type); Thread.Sleep(5000); persistedGrant = await _persistedGrantStore.GetAsync(_currentId); persistedGrant.Should().BeNull(); }
public async Task FindClientByIdAsync_Should_Return_Null_If_Not_Found() { var persistentGrant = await _persistedGrantStore.GetAsync("not-existing-id"); persistentGrant.ShouldBeNull(); }
async Task <PersistedGrant> GetAsync(string key) { var actual = await _persistedGrantStore.GetAsync(key); return(actual); }
public Task <PersistedGrant> GetAsync(string key) { return(_inMemoryPersistedGrantStore.GetAsync(key)); }
public Task <PersistedGrant> GetAsync(string key) { return(_persistedGrantStoreImplementation.GetAsync(key)); }
public async Task <Models.PersistedGrant> GetAsync(string key) { try { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException( "key cant be null or white space", nameof(key)); } var cacheKey = Utilities.CreateCachedPersistedGrantStoreKey(key); var cachedPersistedGrant = await _getPersistedGrantPolicy .ExecuteAsync(async() => { return(await Task.Run(() => _handle.cache.Get <PersistedGrant>(cacheKey) ).ConfigureAwait(false)); }).ConfigureAwait(false); Models.PersistedGrant persistedGrant = null; if (cachedPersistedGrant == null) { persistedGrant = await _inner.GetAsync(key); if (persistedGrant != null) { if (_debugLoggingEnabled) { _logger.LogDebug( $"Cache Miss: Persisted grant {key}" + $"acquired from IPersistedGrantStore"); } var item = new CacheItem(persistedGrant.ToEntity()) { Tags = Utilities.CreateCachePersistedGrantStoreTags( persistedGrant), Expiration = Utilities.DetermineCachePersistedGrantStoreExpiration ( persistedGrant, _handle.options) }; bool result = await _setFallBackPolicy .ExecuteAsync(async() => { await _handle.cache.InsertAsync(cacheKey, item) .ConfigureAwait(false); return(true); }).ConfigureAwait(false); if (_errorLoggingEnabled && !result) { _logger.LogError( $"Caching problems with persistant store cache"); } } else { if (_debugLoggingEnabled) { _logger.LogDebug( $"Persisted grant {key} not found"); } } } else { persistedGrant = cachedPersistedGrant.ToModel(); if (_debugLoggingEnabled) { _logger.LogDebug( $"Cache Hit: Persisted grant {key}" + $"acquired from NCache"); } } return(persistedGrant); } catch (Exception ex) { if (_errorLoggingEnabled) { _logger.LogError( ex, $"something went wrong with GetAsync for {key}"); } throw; } }
public async Task ValidateAsync(ExtensionGrantValidationContext context) { var client = context.Request.Client as ClientExtra; _scopedTenantRequestContext.Context.Client = client; _scopedOverrideRawScopeValues.IsOverride = true; var externalServices = await _externalServicesStore.GetExternalServicesAsync(); var form = context.Request.Raw; var error = false; var los = new List <string>(); // make sure nothing is malformed bool err = false; // optional stuff; var accessTokenLifetimeOverride = form.Get(Constants.AccessTokenLifetime); if (!string.IsNullOrWhiteSpace(accessTokenLifetimeOverride)) { int accessTokenLifetime = 0; if (int.TryParse(accessTokenLifetimeOverride, out accessTokenLifetime)) { if (accessTokenLifetime > 0 && accessTokenLifetime <= client.AccessTokenLifetime) { context.Request.AccessTokenLifetime = accessTokenLifetime; } else { los.Add($"{Constants.AccessTokenLifetime}:{accessTokenLifetimeOverride} is out of range."); err = true; } } } error = error || err; err = false; // MUST have subject // ------------------------------------------------------------------- var subjectToken = form.Get(FluffyBunny4.Constants.TokenExchangeTypes.SubjectToken); if (string.IsNullOrWhiteSpace(subjectToken)) { err = true; los.Add($"{FluffyBunny4.Constants.TokenExchangeTypes.SubjectToken} is required"); } error = error || err; err = false; // MUST have SubjectTokenType // ------------------------------------------------------------------- var subjectTokenType = form.Get(FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType); if (string.IsNullOrWhiteSpace(subjectTokenType)) { err = true; los.Add($"{FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType} is required"); } error = error || err; err = false; if (error) { context.Result.IsError = true; context.Result.Error = string.Join <string>(" | ", los); _logger.LogError($"context.Result.Error"); return; } DateTime tokenIssuedAtTime; List <Claim> claims; var subject = ""; switch (subjectTokenType) { case FluffyBunny4.Constants.TokenExchangeTypes.AccessToken: if (subjectToken.Contains('.')) { err = true; los.Add($"failed to validate, not a reference_token: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.AccessToken}={subjectToken}"); } var validatedResultAccessToken = await _tokenValidator.ValidateAccessTokenAsync(subjectToken); if (validatedResultAccessToken.IsError) { err = true; los.Add($"failed to validate: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.AccessToken}={subjectToken}"); } subject = validatedResultAccessToken.Claims .Where(item => item.Type == JwtClaimTypes.Subject) .Select(item => item.Value) .FirstOrDefault(); if (string.IsNullOrWhiteSpace(subject)) { err = true; los.Add($"subject does not exist: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.SubjectToken}={subjectToken}"); } claims = validatedResultAccessToken.Claims.ToList(); var amr = claims.FirstOrDefault(claim => claim.Type == JwtClaimTypes.AuthenticationMethod && claim.Value == Constants.GrantType.TokenExchange); if (amr == null) { err = true; los.Add($"failed to validate, missing amr={Constants.GrantType.TokenExchange}: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.AccessToken}={subjectToken}"); } var issuedAt = claims.FirstOrDefault(claim => claim.Type == JwtClaimTypes.IssuedAt); if (issuedAt == null) { err = true; los.Add( $"failed to validate, {JwtClaimTypes.IssuedAt} is missing: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.AccessToken}={subjectToken}"); } var unixSeconds = Convert.ToInt64(issuedAt.Value); DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixSeconds); tokenIssuedAtTime = dateTimeOffset.UtcDateTime; var referenceTokenStoreGrantStoreHashAccessor = _referenceTokenStore as IGrantStoreHashAccessor; var fixedSubjectToken = subjectToken.Substring(2); var hashKey = referenceTokenStoreGrantStoreHashAccessor.GetHashedKey(fixedSubjectToken); var accessTokenPersitedGrant = await _persistedGrantStore.GetAsync(hashKey); if (accessTokenPersitedGrant == null) { err = true; los.Add($"failed to validate, accessTokenPersitedGrant is missing: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.AccessToken}={subjectToken}"); } var accessTokenPersitedGrantExtra = accessTokenPersitedGrant as PersistedGrantExtra; _scopedStorage.AddOrUpdate(Constants.ScopedRequestType.SubjectToken, subjectToken); _scopedStorage.AddOrUpdate(Constants.ScopedRequestType.PersistedGrantExtra, accessTokenPersitedGrantExtra); var requestedScopes = context.Request.RequestedScopes.ToList(); if (!string.IsNullOrWhiteSpace(accessTokenPersitedGrantExtra.RefreshTokenKey)) { _scopedOverrideRawScopeValues.Scopes.Add(IdentityServerConstants.StandardScopes.OfflineAccess); _scopedOptionalClaims.Claims.Add(new Claim(JwtClaimTypes.Scope, IdentityServerConstants.StandardScopes.OfflineAccess)); if (!requestedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess)) { requestedScopes.Add(IdentityServerConstants.StandardScopes.OfflineAccess); } } else { if (requestedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess)) { requestedScopes.Remove(IdentityServerConstants.StandardScopes.OfflineAccess); } } context.Request.RequestedScopes = requestedScopes; break; default: throw new Exception($"not supported: {FluffyBunny4.Constants.TokenExchangeTypes.SubjectTokenType}={subjectTokenType},{FluffyBunny4.Constants.TokenExchangeTypes.SubjectToken}={subjectToken}"); break; } error = error || err; err = false; if (error) { context.Result.IsError = true; context.Result.Error = string.Join <string>(" | ", los); _logger.LogError($"context.Result.Error"); return; } var finalCustomPayload = new Dictionary <string, object>(); var requestedScopesRaw = form[Constants.Scope].Split(' ').ToList(); var consentAuthorizeResponseTasks = new List <Task <ConsentAuthorizeResponseContainer <PostContext> > >(); var requestedServiceScopes = GetServiceToScopesFromRequest(requestedScopesRaw); foreach (var serviceScopeSet in requestedServiceScopes) { var externalService = await _externalServicesStore.GetExternalServiceByNameAsync(serviceScopeSet.Key); if (externalService == null) { _logger.LogError($"external service: {serviceScopeSet.Key} does not exist"); continue; } var discoCache = await _consentDiscoveryCacheAccessor.GetConsentDiscoveryCacheAsync(serviceScopeSet.Key); var doco = await discoCache.GetAsync(); if (doco.IsError) { // OPINION: If I have a lot of external services it it probably better to let this continue even it if // results in an access_token that is missing this bad service's scopes. _logger.LogError(doco.Error); continue; } List <string> scopes = null; switch (doco.AuthorizationType) { case Constants.AuthorizationTypes.Implicit: scopes = null; break; case Constants.AuthorizationTypes.SubjectAndScopes: scopes = serviceScopeSet.Value; break; } if (doco.AuthorizationType == Constants.AuthorizationTypes.Implicit) { _scopedOverrideRawScopeValues.Scopes.AddRange(serviceScopeSet.Value); } else { var request = new ConsentAuthorizeRequest { AuthorizeType = doco.AuthorizationType, Scopes = scopes, Subject = subject, Requester = new ConsentAuthorizeRequest.ClientRequester() { ClientDescription = client.Description, ClientId = client.ClientId, ClientName = client.ClientName, Namespace = client.Namespace, Tenant = client.TenantName } }; // How to send many requests in parallel in ASP.Net Core // https://www.michalbialecki.com/2018/04/19/how-to-send-many-requests-in-parallel-in-asp-net-core/ var task = _consentExternalService.PostAuthorizationRequestAsync(doco, request, new PostContext() { ServiceScopeSet = serviceScopeSet, DiscoveryDocument = doco }); consentAuthorizeResponseTasks.Add(task); } } var consentAuthorizeResponses = await Task.WhenAll(consentAuthorizeResponseTasks); foreach (var consentAuthorizeResponse in consentAuthorizeResponses) { var response = consentAuthorizeResponse.Response; var serviceScopeSet = consentAuthorizeResponse.Context.ServiceScopeSet; var doco = consentAuthorizeResponse.Context.DiscoveryDocument; if (response.Error != null) { _logger.LogError($"ExternalService:{serviceScopeSet.Key},Error:{response.Error.Message}"); } else if (response.Authorized) { switch (doco.AuthorizationType) { case Constants.AuthorizationTypes.SubjectAndScopes: // make sure no funny business is coming in from the auth call. var serviceRoot = $"{_tokenExchangeOptions.BaseScope}{serviceScopeSet.Key}"; var query = (from item in response.Scopes where item.StartsWith(serviceRoot) select item); _scopedOverrideRawScopeValues.Scopes.AddRange(query); if (response.Claims != null && response.Claims.Any()) { foreach (var cac in response.Claims) { // namespace the claims. _scopedOptionalClaims.Claims.Add(new Claim($"{serviceScopeSet.Key}.{cac.Type}", cac.Value)); } } if (response.CustomPayload != null) { finalCustomPayload.Add(serviceScopeSet.Key, response.CustomPayload); } break; } } _logger.LogInformation($"ExternalService:{serviceScopeSet.Key},Authorized:{response.Authorized}"); } if (finalCustomPayload.Any()) { _scopedOptionalClaims.Claims.Add(new Claim( Constants.CustomPayload, _serializer.Serialize(finalCustomPayload), IdentityServerConstants.ClaimValueTypes.Json)); } claims = new List <Claim> { // in this case we want to preserve that the original came from Constants.GrantType.TokenExchange new Claim(JwtClaimTypes.AuthenticationMethod, Constants.GrantType.TokenExchange) }; context.Result = new GrantValidationResult(subject, GrantType, tokenIssuedAtTime, claims); _scopedStorage.AddOrUpdate(Constants.ScopedRequestType.ExtensionGrantValidationContext, context); _scopedStorage.AddOrUpdate(Constants.ScopedRequestType.OverrideTokenIssuedAtTime, tokenIssuedAtTime); return; }