public async Task StoreRefreshTokenAsync_should_update_entity() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); var token = new RefreshToken { AccessToken = new Token { ClientId = "test" } }; using var s1 = store.OpenAsyncSession(); await s1.StoreAsync(new Entity.RefreshToken { Id = "test", ClientId = "test", Data = serializer.Serialize(token) }, $"{nameof(Entity.RefreshToken)}/test"); await s1.SaveChangesAsync(); using var session = store.OpenAsyncSession(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(session), serializer, loggerMock.Object); var code = await sut.StoreRefreshTokenAsync(token); Assert.Equal("test", code); }
public async Task RevokeAsync() { //Arrange var sut = new RefreshTokenStore(NhibernateSession, ScopeStoreMock.Object, ClientStoreMock.Object); var subjectIdToRevoke = Guid.NewGuid().ToString(); var clientIdToRevoke = Guid.NewGuid().ToString(); var testKey = Guid.NewGuid().ToString(); var testCode = ObjectCreator.GetRefreshToken(); var tokenHandle = new Token { Key = testKey, SubjectId = testCode.SubjectId, ClientId = testCode.ClientId, JsonCode = ConvertToJson(testCode), Expiry = testCode.CreationTime.UtcDateTime.AddSeconds(testCode.LifeTime), TokenType = TokenType.RefreshToken }; var testKeyToRevoke = Guid.NewGuid().ToString(); var testCodeToRevoke = ObjectCreator.GetRefreshToken(subjectIdToRevoke, clientIdToRevoke); var tokenHandleToRevoke = new Token { Key = testKeyToRevoke, SubjectId = testCodeToRevoke.SubjectId, ClientId = testCodeToRevoke.ClientId, JsonCode = ConvertToJson(testCodeToRevoke), Expiry = testCodeToRevoke.CreationTime.UtcDateTime.AddSeconds(testCodeToRevoke.LifeTime), TokenType = TokenType.RefreshToken }; ExecuteInTransaction(session => { session.Save(tokenHandle); session.Save(tokenHandleToRevoke); }); //Act await sut.RevokeAsync(subjectIdToRevoke, clientIdToRevoke); ExecuteInTransaction(session => { //Assert var tokenRevoked = session.Query <Token>() .SingleOrDefault(t => t.TokenType == TokenType.RefreshToken && t.Key == testKeyToRevoke); var tokenNotRevoked = session.Query <Token>() .SingleOrDefault(t => t.TokenType == TokenType.RefreshToken && t.Key == testKey); Assert.Null(tokenRevoked); Assert.NotNull(tokenNotRevoked); //CleanUp session.Delete(tokenNotRevoked); }); }
public void GetAsync_WhenCalled_ExpectResponse() { // Arrange var mockCacheManager = new Mock<ICacheManager<RefreshToken>>(); var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns(new RedisCacheConfigurationEntity { CacheDuration = 1 }); var keyCallback = default(string); mockCacheManager.Setup(r => r.GetAsync(It.IsAny<string>())) .Callback((string s) => keyCallback = s) .ReturnsAsync(new RefreshToken()); var refreshTokenStore = new RefreshTokenStore( mockCacheManager.Object, mockCacheConfiguration.Object); // Act var stopwatch = Stopwatch.StartNew(); var authorizationCode = refreshTokenStore.GetAsync("string").Result; stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); Assert.That(authorizationCode, Is.Not.Null); Assert.That(keyCallback, Is.EqualTo("RTS_string")); }
public async Task GetRefreshTokenAsync_should_return_grant_by_hamlder() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); using var s1 = store.OpenAsyncSession(); await s1.StoreAsync(new Entity.RefreshToken { Id = "test", ClientId = "test", Data = serializer.Serialize(new Token { ClientId = "test" }) }, $"{nameof(Entity.RefreshToken)}/test"); await s1.SaveChangesAsync(); using var session = store.OpenAsyncSession(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(session), serializer, loggerMock.Object); var result = await sut.GetRefreshTokenAsync("test"); Assert.NotNull(result); }
public async Task RemoveRefreshTokenAsync_by_subjectId_clientId_should_delete_entity() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); using var s1 = store.OpenAsyncSession(); await s1.StoreAsync(new Entity.RefreshToken { Id = "test", ClientId = "test", UserId = "test", Data = serializer.Serialize(new Token { ClientId = "test" }) }, $"{nameof(Entity.RefreshToken)}/test"); await s1.SaveChangesAsync(); using var session = store.OpenAsyncSession(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(session), serializer, loggerMock.Object); await sut.RemoveRefreshTokensAsync("test", "test"); using var s2 = store.OpenAsyncSession(); var result = await s2.LoadAsync <Entity.RefreshToken>($"{nameof(Entity.RefreshToken)}/test"); Assert.Null(result); }
/// <summary> /// Creates the refresh token. /// </summary> /// <param name="subject">The subject.</param> /// <param name="accessToken">The access token.</param> /// <param name="client">The client.</param> /// <returns> /// The refresh token handle /// </returns> public virtual async Task <string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client) { _logger.LogDebug("Creating refresh token"); int lifetime; if (client.RefreshTokenExpiration == TokenExpiration.Absolute) { _logger.LogDebug("Setting an absolute lifetime: {absoluteLifetime}", client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } else { lifetime = client.SlidingRefreshTokenLifetime; if (client.AbsoluteRefreshTokenLifetime > 0 && lifetime > client.AbsoluteRefreshTokenLifetime) { _logger.LogWarning("Client {clientId}'s configured " + nameof(client.SlidingRefreshTokenLifetime) + " of {slidingLifetime} exceeds its " + nameof(client.AbsoluteRefreshTokenLifetime) + " of {absoluteLifetime}. The refresh_token's sliding lifetime will be capped to the absolute lifetime", client.ClientId, lifetime, client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } _logger.LogDebug("Setting a sliding lifetime: {slidingLifetime}", lifetime); } var refreshToken = new RefreshToken { CreationTime = Clock.UtcNow.UtcDateTime, Lifetime = lifetime, AccessToken = accessToken }; var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken); return(handle); }
public void Setup() { base.Setup(); _clientStore = new ClientStore(StoreSettings.UsingFolder(TargetFolder)); _tokenHandleStore = new TokenHandleStore(StoreSettings.UsingFolder(TargetFolder)); _refreshTokenHandleStore = new RefreshTokenStore(StoreSettings.UsingFolder(TargetFolder)); _scopeStore = new ScopeStore(StoreSettings.UsingFolder(TargetFolder)); }
private static void CreateSut(out Mock <IAdminStore <RefreshToken> > storeMock, out RefreshTokenStore sut) { storeMock = new Mock <IAdminStore <RefreshToken> >(); var serializerMock = new Mock <IPersistentGrantSerializer>(); sut = new RefreshTokenStore(storeMock.Object, serializerMock.Object); }
public async Task UpdateByUserCodeAsync_should_throw_when_handle_not_found() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(store.OpenAsyncSession()), serializer, loggerMock.Object); await Assert.ThrowsAsync <InvalidOperationException>(() => sut.UpdateRefreshTokenAsync("handle", new RefreshToken())); }
public override async Task <string> CreateRefreshTokenAsync(RefreshTokenCreationRequest request) { Logger.LogDebug("Creating refresh token"); int lifetime; if (request.Client.RefreshTokenExpiration == TokenExpiration.Absolute) { Logger.LogDebug("Setting an absolute lifetime: {absoluteLifetime}", request.Client.AbsoluteRefreshTokenLifetime); lifetime = request.Client.AbsoluteRefreshTokenLifetime; } else { lifetime = request.Client.SlidingRefreshTokenLifetime; if (request.Client.AbsoluteRefreshTokenLifetime > 0 && lifetime > request.Client.AbsoluteRefreshTokenLifetime) { Logger.LogWarning( "Client {clientId}'s configured " + nameof(request.Client.SlidingRefreshTokenLifetime) + " of {slidingLifetime} exceeds its " + nameof(request.Client.AbsoluteRefreshTokenLifetime) + " of {absoluteLifetime}. The refresh_token's sliding lifetime will be capped to the absolute lifetime", request.Client.ClientId, lifetime, request.Client.AbsoluteRefreshTokenLifetime); lifetime = request.Client.AbsoluteRefreshTokenLifetime; } Logger.LogDebug("Setting a sliding lifetime: {slidingLifetime}", lifetime); } var formCollection = await _scopedHttpContextRequestForm.GetFormCollectionAsync(); var originGrantType = formCollection["grant_type"]; var refreshToken = new RefreshTokenExtra() { Subject = request.Subject, ClientId = request.Client.ClientId, Description = request.Description, AuthorizedScopes = request.AuthorizedScopes, AuthorizedResourceIndicators = request.AuthorizedResourceIndicators, CreationTime = Clock.UtcNow.UtcDateTime, Lifetime = lifetime, OriginGrantType = originGrantType }; refreshToken.SetAccessToken(request.AccessToken, request.RequestedResourceIndicator); var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken); return(handle); }
/// <summary> /// Creates the refresh token. /// </summary> /// <returns> /// The refresh token handle /// </returns> public virtual async Task <string> CreateRefreshTokenAsync(RefreshTokenCreationRequest request) { using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultRefreshTokenService.CreateRefreshToken"); Logger.LogDebug("Creating refresh token"); int lifetime; if (request.Client.RefreshTokenExpiration == TokenExpiration.Absolute) { Logger.LogDebug("Setting an absolute lifetime: {absoluteLifetime}", request.Client.AbsoluteRefreshTokenLifetime); lifetime = request.Client.AbsoluteRefreshTokenLifetime; } else { lifetime = request.Client.SlidingRefreshTokenLifetime; if (request.Client.AbsoluteRefreshTokenLifetime > 0 && lifetime > request.Client.AbsoluteRefreshTokenLifetime) { Logger.LogWarning( "Client {clientId}'s configured " + nameof(request.Client.SlidingRefreshTokenLifetime) + " of {slidingLifetime} exceeds its " + nameof(request.Client.AbsoluteRefreshTokenLifetime) + " of {absoluteLifetime}. The refresh_token's sliding lifetime will be capped to the absolute lifetime", request.Client.ClientId, lifetime, request.Client.AbsoluteRefreshTokenLifetime); lifetime = request.Client.AbsoluteRefreshTokenLifetime; } Logger.LogDebug("Setting a sliding lifetime: {slidingLifetime}", lifetime); } var refreshToken = new RefreshToken { Subject = request.Subject, SessionId = request.AccessToken.SessionId, ClientId = request.Client.ClientId, Description = request.Description, AuthorizedScopes = request.AuthorizedScopes, AuthorizedResourceIndicators = request.AuthorizedResourceIndicators, CreationTime = Clock.UtcNow.UtcDateTime, Lifetime = lifetime, }; refreshToken.SetAccessToken(request.AccessToken, request.RequestedResourceIndicator); var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken); return(handle); }
public async Task RemoveRefreshTokenAsync_should_not_throw_when_entity_not_exist() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); using var session = store.OpenAsyncSession(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(session), serializer, loggerMock.Object); await sut.RemoveRefreshTokenAsync("test"); using var s2 = store.OpenAsyncSession(); var result = await s2.LoadAsync <Entity.RefreshToken>($"{nameof(Entity.RefreshToken)}/test"); Assert.Null(result); }
public async Task <string> CreateRefreshTokenAsync( ClaimsPrincipal subject, Token accessToken, Client client) { Logger.LogDebug("Creating refresh token"); int lifetime; if (client.RefreshTokenExpiration == TokenExpiration.Absolute) { Logger.LogDebug("Setting an absolute lifetime: {absoluteLifetime}", client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } else { lifetime = client.SlidingRefreshTokenLifetime; if (client.AbsoluteRefreshTokenLifetime > 0 && lifetime > client.AbsoluteRefreshTokenLifetime) { Logger.LogWarning( "Client {clientId}'s configured " + nameof(client.SlidingRefreshTokenLifetime) + " of {slidingLifetime} exceeds its " + nameof(client.AbsoluteRefreshTokenLifetime) + " of {absoluteLifetime}. The refresh_token's sliding lifetime will be capped to the absolute lifetime", client.ClientId, lifetime, client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } Logger.LogDebug("Setting a sliding lifetime: {slidingLifetime}", lifetime); } var formCollection = await _scopedHttpContextRequestForm.GetFormCollectionAsync(); var originGrantType = formCollection["grant_type"]; var refreshToken = new RefreshTokenExtra { CreationTime = Clock.UtcNow.UtcDateTime, Lifetime = lifetime, AccessToken = accessToken, OriginGrantType = originGrantType }; var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken); return(handle); }
public async Task UpdateByUserCodeAsync_should_update_token() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); var token = new RefreshToken { AccessToken = new Token { ClientId = "test" } }; using var s1 = store.OpenAsyncSession(); await s1.StoreAsync(new Entity.RefreshToken { Id = "test", ClientId = "test", Data = serializer.Serialize(token) }, $"{nameof(Entity.RefreshToken)}/test"); await s1.SaveChangesAsync(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(store.OpenAsyncSession()), serializer, loggerMock.Object); await sut.UpdateRefreshTokenAsync("test", new RefreshToken { AccessToken = new Token { ClientId = "test", Description = "test" } }); using var s2 = store.OpenAsyncSession(); var updated = await s2.LoadAsync <Entity.RefreshToken>($"{nameof(Entity.RefreshToken)}/test"); var data = serializer.Deserialize <RefreshToken>(updated.Data); Assert.Equal("test", data.AccessToken.Description); }
public void GetAllAsync_WhenCalled_ExpectThrows() { // Arrange var mockCacheManager = new Mock<ICacheManager<RefreshToken>>(); var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns(new RedisCacheConfigurationEntity { CacheDuration = 1 }); var refreshTokenStore = new RefreshTokenStore( mockCacheManager.Object, mockCacheConfiguration.Object); // Act and Assert var stopwatch = Stopwatch.StartNew(); Assert.Throws<NotImplementedException>( () => refreshTokenStore.GetAllAsync("string").GetAwaiter().GetResult()); stopwatch.Stop(); this.WriteTimeElapsed(stopwatch); }
public void GetAsync_WhenCalled_ExpectResponse() { // Arrange var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns( new RedisCacheConfigurationEntity { CacheDuration = 10, RedisCacheDefaultPrefix = "DEFAULT", UseObjectCompression = false }); var jsonSettingsFactory = new JsonSettingsFactory(new CustomMappersConfiguration()); var cacheManager = new RedisCacheManager<RefreshToken>( RedisHelpers.ConnectionMultiplexer, mockCacheConfiguration.Object, jsonSettingsFactory.Create()); var refreshTokenStore = new RefreshTokenStore( cacheManager, mockCacheConfiguration.Object); // Act var stopwatch = Stopwatch.StartNew(); var refreshToken = refreshTokenStore.GetAsync("Existing").Result; stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); Assert.That(refreshToken, Is.Not.Null); Assert.That(refreshToken.Subject, Is.Not.Null); Assert.That(refreshToken.AccessToken, Is.Not.Null); Assert.That(refreshToken.CreationTime, Is.EqualTo(new DateTimeOffset(new DateTime(2016, 1, 1)))); Assert.That(refreshToken.LifeTime, Is.EqualTo(1600)); Assert.That(refreshToken.Scopes, Is.Not.Null); Assert.That(refreshToken.Version, Is.EqualTo(1)); }
public async Task StoreRefreshTokenAsync_should_create_entity() { using var store = new RavenDbTestDriverWrapper().GetDocumentStore(); var serializer = new PersistentGrantSerializer(); var loggerMock = new Mock <ILogger <RefreshTokenStore> >(); using var session = store.OpenAsyncSession(); var sut = new RefreshTokenStore(new ScopedAsynDocumentcSession(session), serializer, loggerMock.Object); var code = await sut.StoreRefreshTokenAsync(new RefreshToken { AccessToken = new Token { ClientId = "test" } }); using var s2 = store.OpenAsyncSession(); var result = await s2.LoadAsync <Entity.RefreshToken>($"{nameof(Entity.RefreshToken)}/{code}"); Assert.NotNull(result); }
// revoke refresh token only if it belongs to client doing the request private async Task <bool> RevokeRefreshTokenAsync(TokenRevocationRequestValidationResult validationResult) { var token = await RefreshTokenStore.GetRefreshTokenAsync(validationResult.Token); if (token != null) { if (token.ClientId == validationResult.Client.ClientId) { Logger.LogDebug("Refresh token revoked"); await RefreshTokenStore.RemoveRefreshTokensAsync(token.SubjectId, token.ClientId); await ReferenceTokenStore.RemoveReferenceTokensAsync(token.SubjectId, token.ClientId); } else { Logger.LogWarning("Client {clientId} tried to revoke a refresh token belonging to a different client: {clientId}", validationResult.Client.ClientId, token.ClientId); } return(true); } return(false); }
public override async Task <TokenValidationResult> ValidateRefreshTokenAsync( string tokenHandle, Client client) { ////////////////////////////////////////////////// // Calling the base ValidateRefreshTokenAsync // this covers the obvious failures like Lifetime checks. ////////////////////////////////////////////////// var baseResult = await base.ValidateRefreshTokenAsync(tokenHandle, client); if (baseResult.IsError) { // await RefreshTokenStore.RemoveRefreshTokenAsync(tokenHandle); return(baseResult); } var invalidGrant = new TokenValidationResult { IsError = true, Error = OidcConstants.TokenErrors.InvalidGrant }; ///////////////////////////////////////////// // check if refresh token has been consumed ///////////////////////////////////////////// if (baseResult.RefreshToken.ConsumedTime.HasValue) { if (await AcceptConsumedTokenAsync(baseResult.RefreshToken, client) == false) { Logger.LogWarning("Rejecting refresh token because it has been consumed already."); await RefreshTokenStore.RemoveRefreshTokenAsync(tokenHandle); return(invalidGrant); } } baseResult.Client = client; return(baseResult); }
public async Task GetAsync() { //Arrange var sut = new RefreshTokenStore(NhibernateSession, ScopeStoreMock.Object, ClientStoreMock.Object); var testKey = Guid.NewGuid().ToString(); var testCode = ObjectCreator.GetRefreshToken(); var tokenHandle = new Token { Key = testKey, SubjectId = testCode.SubjectId, ClientId = testCode.ClientId, JsonCode = ConvertToJson(testCode), Expiry = testCode.CreationTime.UtcDateTime.AddSeconds(30), TokenType = TokenType.RefreshToken }; SetupScopeStoreMock(); ExecuteInTransaction(session => { session.SaveOrUpdate(tokenHandle); }); //Act var resultToken = await sut.GetAsync(testKey); //Assert Assert.NotNull(resultToken); //CleanUp ExecuteInTransaction(session => { session.Delete(tokenHandle); }); }
public async Task StoreAsync() { //Arrange var sut = new RefreshTokenStore(NhibernateSession, ScopeStoreMock.Object, ClientStoreMock.Object); var testKey = Guid.NewGuid().ToString(); var testCode = ObjectCreator.GetRefreshToken(); //Act await sut.StoreAsync(testKey, testCode); ExecuteInTransaction(session => { //Assert var token = session.Query <Token>() .SingleOrDefault(t => t.TokenType == TokenType.RefreshToken && t.Key == testKey); Assert.NotNull(token); //CleanUp session.Delete(token); }); }
/// <inheritdoc/> public virtual Task <RefreshToken> GetRefreshTokenAsync(string refreshTokenHandle) => RefreshTokenStore.GetRefreshTokenAsync(refreshTokenHandle);
public void RemoveAsync_WhenCalled_ExpectAction() { // Arrange var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns( new RedisCacheConfigurationEntity { CacheDuration = 10, RedisCacheDefaultPrefix = "DEFAULT", UseObjectCompression = false }); var jsonSettingsFactory = new JsonSettingsFactory(new CustomMappersConfiguration()); var cacheManager = new RedisCacheManager<RefreshToken>( RedisHelpers.ConnectionMultiplexer, mockCacheConfiguration.Object, jsonSettingsFactory.Create()); var refreshTokenStore = new RefreshTokenStore( cacheManager, mockCacheConfiguration.Object); // Act var stopwatch = Stopwatch.StartNew(); refreshTokenStore.RemoveAsync("Delete").Wait(); stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); var redisValue = RedisHelpers.ConnectionMultiplexer.GetDatabase().StringGet("DEFAULT_RTS_Delete"); Assert.That(redisValue.HasValue, Is.False); }
public void StoreAsync_WhenCalled_ExpectAction() { // Arrange var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns( new RedisCacheConfigurationEntity { CacheDuration = 10, RedisCacheDefaultPrefix = "DEFAULT", UseObjectCompression = false }); var jsonSettingsFactory = new JsonSettingsFactory(new CustomMappersConfiguration()); var cacheManager = new RedisCacheManager<RefreshToken>( RedisHelpers.ConnectionMultiplexer, mockCacheConfiguration.Object, jsonSettingsFactory.Create()); var refreshTokenStore = new RefreshTokenStore( cacheManager, mockCacheConfiguration.Object); var refreshToken = new RefreshToken { AccessToken = new Token { Client = new Client { ClientId = "cid", }, Claims = new List<Claim> { new Claim("SubjectId", "sid") } }, CreationTime = new DateTimeOffset(new DateTime(2016, 1, 1)), LifeTime = 1600, Version = 1, }; // Act var stopwatch = Stopwatch.StartNew(); refreshTokenStore.StoreAsync("KeyToStore", refreshToken).Wait(); stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); var redisValue = RedisHelpers.ConnectionMultiplexer.GetDatabase().StringGet("DEFAULT_RTS_KeyToStore"); Assert.That(redisValue.HasValue, Is.True); Console.WriteLine(redisValue); }
/// <summary> /// Updates the refresh token. /// </summary> /// <param name="handle">The handle.</param> /// <param name="refreshToken">The refresh token.</param> /// <param name="client">The client.</param> /// <returns> /// The refresh token handle /// </returns> public virtual async Task <string> UpdateRefreshTokenAsync(string handle, RefreshToken refreshToken, Client client) { _logger.LogDebug("Updating refresh token"); bool needsCreate = false; bool needsUpdate = false; if (client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { _logger.LogDebug("Token usage is one-time only. Generating new handle"); // delete old one await RefreshTokenStore.RemoveRefreshTokenAsync(handle); // create new one needsCreate = true; } if (client.RefreshTokenExpiration == TokenExpiration.Sliding) { _logger.LogDebug("Refresh token expiration is sliding - extending lifetime"); // if absolute exp > 0, make sure we don't exceed absolute exp // if absolute exp = 0, allow indefinite slide var currentLifetime = refreshToken.CreationTime.GetLifetimeInSeconds(Clock.UtcNow.UtcDateTime); _logger.LogDebug("Current lifetime: {currentLifetime}", currentLifetime.ToString()); var newLifetime = currentLifetime + client.SlidingRefreshTokenLifetime; _logger.LogDebug("New lifetime: {slidingLifetime}", newLifetime.ToString()); // zero absolute refresh token lifetime represents unbounded absolute lifetime // if absolute lifetime > 0, cap at absolute lifetime if (client.AbsoluteRefreshTokenLifetime > 0 && newLifetime > client.AbsoluteRefreshTokenLifetime) { newLifetime = client.AbsoluteRefreshTokenLifetime; _logger.LogDebug("New lifetime exceeds absolute lifetime, capping it to {newLifetime}", newLifetime.ToString()); } refreshToken.Lifetime = newLifetime; needsUpdate = true; } if (needsCreate) { handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken); _logger.LogDebug("Created refresh token in store"); } else if (needsUpdate) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, refreshToken); _logger.LogDebug("Updated refresh token in store"); } else { _logger.LogDebug("No updates to refresh token done"); } return(handle); }
public async Task GetAllAsync() { //Arrange var sut = new RefreshTokenStore(NhibernateSession, ScopeStoreMock.Object, ClientStoreMock.Object); var subjectId1 = Guid.NewGuid().ToString(); var subjectId2 = Guid.NewGuid().ToString(); var testKey1 = Guid.NewGuid().ToString(); var testCode1 = ObjectCreator.GetRefreshToken(subjectId1); var tokenHandle1 = new Token { Key = testKey1, SubjectId = testCode1.SubjectId, ClientId = testCode1.ClientId, JsonCode = ConvertToJson(testCode1), Expiry = testCode1.CreationTime.UtcDateTime.AddSeconds(testCode1.LifeTime), TokenType = TokenType.RefreshToken }; var testKey2 = Guid.NewGuid().ToString(); var testCode2 = ObjectCreator.GetRefreshToken(subjectId1); var tokenHandle2 = new Token { Key = testKey2, SubjectId = testCode2.SubjectId, ClientId = testCode2.ClientId, JsonCode = ConvertToJson(testCode2), Expiry = testCode2.CreationTime.UtcDateTime.AddSeconds(testCode2.LifeTime), TokenType = TokenType.RefreshToken }; var testKey3 = Guid.NewGuid().ToString(); var testCode3 = ObjectCreator.GetRefreshToken(subjectId2); var tokenHandle3 = new Token { Key = testKey3, SubjectId = testCode3.SubjectId, ClientId = testCode3.ClientId, JsonCode = ConvertToJson(testCode3), Expiry = testCode3.CreationTime.UtcDateTime.AddSeconds(testCode3.LifeTime), TokenType = TokenType.RefreshToken }; var testKey4 = Guid.NewGuid().ToString(); var testCode4 = ObjectCreator.GetRefreshToken(subjectId2); var tokenHandle4 = new Token { Key = testKey4, SubjectId = testCode4.SubjectId, ClientId = testCode4.ClientId, JsonCode = ConvertToJson(testCode4), Expiry = testCode4.CreationTime.UtcDateTime.AddSeconds(testCode4.LifeTime), TokenType = TokenType.RefreshToken }; SetupScopeStoreMock(); ExecuteInTransaction(session => { session.SaveOrUpdate(tokenHandle1); session.SaveOrUpdate(tokenHandle2); session.SaveOrUpdate(tokenHandle3); session.SaveOrUpdate(tokenHandle4); }); //Act var tokens = (await sut.GetAllAsync(subjectId1)).ToList(); //Assert Assert.True(tokens.Count == 2); Assert.True(tokens.All(t => t.SubjectId == subjectId1)); //CleanUp ExecuteInTransaction(session => { session.Delete(tokenHandle1); session.Delete(tokenHandle2); session.Delete(tokenHandle3); session.Delete(tokenHandle4); }); }
public void RemoveAsync_WhenCalled_ExpectAction() { // Arrange var mockCacheManager = new Mock<ICacheManager<RefreshToken>>(); var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns(new RedisCacheConfigurationEntity { CacheDuration = 1 }); var keyCallback = default(string); mockCacheManager.Setup(r => r.DeleteAsync(It.IsAny<string>())) .Callback((string s) => keyCallback = s) .Returns(Task.FromResult(0)); var refreshTokenStore = new RefreshTokenStore( mockCacheManager.Object, mockCacheConfiguration.Object); // Act var stopwatch = Stopwatch.StartNew(); refreshTokenStore.RemoveAsync("string").Wait(); stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); Assert.That(keyCallback, Is.EqualTo("RTS_string")); mockCacheManager.Verify(r => r.DeleteAsync(It.IsAny<string>()), Times.Once()); }
public async Task <string> UpdateRefreshTokenAsync( string handle, RefreshToken refreshToken, Client client) { Logger.LogDebug("Updating refresh token"); var refreshTokenExtra = refreshToken as RefreshTokenExtra; var clientExtra = client as ClientExtra; bool needsCreate = false; bool needsUpdate = false; if (client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.LogDebug("Token usage is one-time only. Setting current handle as consumed, and generating new handle"); // flag as consumed if (!refreshTokenExtra.ConsumedTime.HasValue) { // only track the initial consumed time. refreshTokenExtra.ConsumedTime = Clock.UtcNow.DateTime; } // increment the attempts used refreshTokenExtra.ConsumedAttempts += 1; if (!clientExtra.RefreshTokenGraceEnabled) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, refreshTokenExtra); } // create new one needsCreate = true; } if (client.RefreshTokenExpiration == TokenExpiration.Sliding) { Logger.LogDebug("Refresh token expiration is sliding - extending lifetime"); // if absolute exp > 0, make sure we don't exceed absolute exp // if absolute exp = 0, allow indefinite slide var currentLifetime = refreshTokenExtra.CreationTime.GetLifetimeInSeconds(Clock.UtcNow.UtcDateTime); Logger.LogDebug("Current lifetime: {currentLifetime}", currentLifetime.ToString()); var newLifetime = currentLifetime + client.SlidingRefreshTokenLifetime; Logger.LogDebug("New lifetime: {slidingLifetime}", newLifetime.ToString()); // zero absolute refresh token lifetime represents unbounded absolute lifetime // if absolute lifetime > 0, cap at absolute lifetime if (client.AbsoluteRefreshTokenLifetime > 0 && newLifetime > client.AbsoluteRefreshTokenLifetime) { newLifetime = client.AbsoluteRefreshTokenLifetime; Logger.LogDebug("New lifetime exceeds absolute lifetime, capping it to {newLifetime}", newLifetime.ToString()); } refreshTokenExtra.Lifetime = newLifetime; needsUpdate = true; } if (needsCreate) { var oldChild = refreshTokenExtra.RefeshTokenChild; var oldParent = refreshTokenExtra.RefeshTokenParent; var savedConsumedTime = refreshTokenExtra.ConsumedTime; // set it to null so that we save non-consumed token refreshTokenExtra.ConsumedTime = null; refreshTokenExtra.RefeshTokenChild = null; // carry forward the parent. refreshTokenExtra.RefeshTokenParent = handle; var newHandle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshTokenExtra); refreshTokenExtra.ConsumedTime = savedConsumedTime; refreshTokenExtra.RefeshTokenParent = null; if (client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.LogDebug("Token usage is one-time only. Setting current handle as consumed, and generating new handle"); if (clientExtra.RefreshTokenGraceEnabled) { refreshTokenExtra.RefeshTokenChild = newHandle; } await RefreshTokenStore.UpdateRefreshTokenAsync( handle, refreshTokenExtra); if (clientExtra.RefreshTokenGraceEnabled) { if (!string.IsNullOrWhiteSpace(oldChild)) { await RefreshTokenStore.RemoveRefreshTokenAsync(oldChild); } if (!string.IsNullOrWhiteSpace(oldParent)) { await RefreshTokenStore.RemoveRefreshTokenAsync(oldParent); } } } handle = newHandle; Logger.LogDebug("Created refresh token in store"); } else if (needsUpdate) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, refreshTokenExtra); Logger.LogDebug("Updated refresh token in store"); } else { Logger.LogDebug("No updates to refresh token done"); } return(handle); }
/// <summary> /// Updates the refresh token. /// </summary> /// <returns> /// The refresh token handle /// </returns> public virtual async Task <string> UpdateRefreshTokenAsync(RefreshTokenUpdateRequest request) { Logger.LogDebug("Updating refresh token"); var handle = request.Handle; bool needsCreate = false; bool needsUpdate = request.MustUpdate; if (request.Client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.LogDebug("Token usage is one-time only. Setting current handle as consumed, and generating new handle"); // flag as consumed if (request.RefreshToken.ConsumedTime == null) { request.RefreshToken.ConsumedTime = Clock.UtcNow.UtcDateTime; await RefreshTokenStore.UpdateRefreshTokenAsync(handle, request.RefreshToken); } // create new one needsCreate = true; } if (request.Client.RefreshTokenExpiration == TokenExpiration.Sliding) { Logger.LogDebug("Refresh token expiration is sliding - extending lifetime"); // if absolute exp > 0, make sure we don't exceed absolute exp // if absolute exp = 0, allow indefinite slide var currentLifetime = request.RefreshToken.CreationTime.GetLifetimeInSeconds(Clock.UtcNow.UtcDateTime); Logger.LogDebug("Current lifetime: {currentLifetime}", currentLifetime.ToString()); var newLifetime = currentLifetime + request.Client.SlidingRefreshTokenLifetime; Logger.LogDebug("New lifetime: {slidingLifetime}", newLifetime.ToString()); // zero absolute refresh token lifetime represents unbounded absolute lifetime // if absolute lifetime > 0, cap at absolute lifetime if (request.Client.AbsoluteRefreshTokenLifetime > 0 && newLifetime > request.Client.AbsoluteRefreshTokenLifetime) { newLifetime = request.Client.AbsoluteRefreshTokenLifetime; Logger.LogDebug("New lifetime exceeds absolute lifetime, capping it to {newLifetime}", newLifetime.ToString()); } request.RefreshToken.Lifetime = newLifetime; needsUpdate = true; } if (needsCreate) { // set it to null so that we save non-consumed token request.RefreshToken.ConsumedTime = null; handle = await RefreshTokenStore.StoreRefreshTokenAsync(request.RefreshToken); Logger.LogDebug("Created refresh token in store"); } else if (needsUpdate) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, request.RefreshToken); Logger.LogDebug("Updated refresh token in store"); } else { Logger.LogDebug("No updates to refresh token done"); } return(handle); }
/// <inheritdoc/> public Task RemoveRefreshTokenAsync(string refreshTokenHandle) => RefreshTokenStore.RemoveRefreshTokenAsync(refreshTokenHandle);
/// <summary> /// Validates a refresh token /// </summary> /// <param name="tokenHandle">The token handle.</param> /// <param name="client">The client.</param> /// <returns></returns> public virtual async Task <TokenValidationResult> ValidateRefreshTokenAsync(string tokenHandle, Client client) { var invalidGrant = new TokenValidationResult { IsError = true, Error = OidcConstants.TokenErrors.InvalidGrant }; Logger.LogTrace("Start refresh token validation"); ///////////////////////////////////////////// // check if refresh token is valid ///////////////////////////////////////////// var refreshToken = await RefreshTokenStore.GetRefreshTokenAsync(tokenHandle); if (refreshToken == null) { Logger.LogWarning("Invalid refresh token"); return(invalidGrant); } ///////////////////////////////////////////// // check if refresh token has expired ///////////////////////////////////////////// if (refreshToken.CreationTime.HasExceeded(refreshToken.Lifetime, Clock.UtcNow.DateTime)) { Logger.LogWarning("Refresh token has expired."); return(invalidGrant); } ///////////////////////////////////////////// // check if client belongs to requested refresh token ///////////////////////////////////////////// if (client.ClientId != refreshToken.ClientId) { Logger.LogError("{0} tries to refresh token belonging to {1}", client.ClientId, refreshToken.ClientId); return(invalidGrant); } ///////////////////////////////////////////// // check if client still has offline_access scope ///////////////////////////////////////////// if (!client.AllowOfflineAccess) { Logger.LogError("{clientId} does not have access to offline_access scope anymore", client.ClientId); return(invalidGrant); } ///////////////////////////////////////////// // check if refresh token has been consumed ///////////////////////////////////////////// if (refreshToken.ConsumedTime.HasValue && !await AcceptConsumedTokenAsync(refreshToken)) { Logger.LogWarning("Rejecting refresh token because it has been consumed already."); return(invalidGrant); } ///////////////////////////////////////////// // make sure user is enabled ///////////////////////////////////////////// var isActiveCtx = new IsActiveContext( refreshToken.Subject, client, IdentityServerConstants.ProfileIsActiveCallers.RefreshTokenValidation); await Profile.IsActiveAsync(isActiveCtx); if (!isActiveCtx.IsActive) { Logger.LogError("{subjectId} has been disabled", refreshToken.Subject.GetSubjectId()); return(invalidGrant); } return(new TokenValidationResult { IsError = false, RefreshToken = refreshToken, RefreshTokenHandle = tokenHandle, Client = client }); }
public void StoreAsync_WhenCalled_ExpectAction() { // Arrange var mockCacheManager = new Mock<ICacheManager<RefreshToken>>(); var mockCacheConfiguration = new Mock<IConfiguration<RedisCacheConfigurationEntity>>(); mockCacheConfiguration.Setup(r => r.Get).Returns(new RedisCacheConfigurationEntity { CacheDuration = 1 }); var keyCallback = default(string); var timespanCallback = default(TimeSpan); mockCacheManager.Setup(r => r.SetAsync(It.IsAny<string>(), It.IsAny<RefreshToken>(), It.IsAny<TimeSpan>())) .Callback((string s, RefreshToken a, TimeSpan t) => { keyCallback = s; timespanCallback = t; }) .Returns(Task.FromResult(0)); var refreshTokenStore = new RefreshTokenStore( mockCacheManager.Object, mockCacheConfiguration.Object); // Act var stopwatch = Stopwatch.StartNew(); refreshTokenStore.StoreAsync("string", new RefreshToken { LifeTime = 100 }).Wait(); stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); Assert.That(keyCallback, Is.EqualTo("RTS_string")); Assert.That(timespanCallback, Is.EqualTo(TimeSpan.FromSeconds(95))); mockCacheManager.Verify(r => r.SetAsync(It.IsAny<string>(), It.IsAny<RefreshToken>(), It.IsAny<TimeSpan>()), Times.Once()); }
public static List <RefreshTokenHandleRecord> InsertTestData(ClientStore clientStore, ScopeStore scopeStore, TokenHandleStore ths, RefreshTokenStore store, int count = 1) { List <RefreshTokenHandleRecord> result = new List <RefreshTokenHandleRecord>(); var insert = TokenHandleStoreTest.InsertTestData(clientStore, scopeStore, ths, count); var subjectSeed = Guid.NewGuid().ToString(); var clientId = insert[0].Record.ClientId; foreach (var item in insert) { RefreshTokenHandle tokenHandle = new RefreshTokenHandle { ClientId = clientId, AccessToken = item.Record, CreationTime = DateTimeOffset.UtcNow, Key = Guid.NewGuid().ToString(), Expires = DateTimeOffset.UtcNow.AddMinutes(5), LifeTime = 5, SubjectId = item.Record.SubjectId, Version = 1 }; var tokenHandleRecord = new RefreshTokenHandleRecord(tokenHandle); store.CreateAsync(tokenHandleRecord.Record); result.Add(tokenHandleRecord); } return(result); }
/// <summary> /// Initializes this instance. /// </summary> /// <returns>The <see cref="Caches"/></returns> private static Entities.Caches Initialize() { var jsonSettingsFactory = new JsonSettingsFactory(incomingMappers); var settings = jsonSettingsFactory.Create(); var authorizationCacheManager = new RedisCacheManager<AuthorizationCode>( ConnectionMultiplexer, Configuration, settings); var authorizationCodeStore = new AuthorizationCodeStore( authorizationCacheManager, Configuration); var clientCacheManager = new RedisCacheManager<Client>( ConnectionMultiplexer, Configuration, settings); var clientCache = new ClientStoreCache( clientCacheManager, Configuration); var refreshTokenCacheManager = new RedisCacheManager<RefreshToken>( ConnectionMultiplexer, Configuration, settings); var refreshTokenStore = new RefreshTokenStore( refreshTokenCacheManager, Configuration); var scopeCacheManager = new RedisCacheManager<IEnumerable<Scope>>( ConnectionMultiplexer, Configuration, settings); var scopesCache = new ScopeStoreCache( scopeCacheManager, Configuration); var redisHandleCacheManager = new RedisCacheManager<Token>( ConnectionMultiplexer, Configuration, settings); var tokenHandleStore = new TokenHandleStore( redisHandleCacheManager, Configuration); var userServiceCacheManager = new RedisCacheManager<IEnumerable<Claim>>( ConnectionMultiplexer, Configuration, settings); var userServiceCache = new UserServiceCache( userServiceCacheManager, Configuration); var caches = new Entities.Caches { AuthorizationCodeStore = authorizationCodeStore, ClientCache = clientCache, RefreshTokenStore = refreshTokenStore, ScopesCache = scopesCache, TokenHandleStore = tokenHandleStore, UserServiceCache = userServiceCache }; return caches; }