public async Task Expired_RefreshToken() { var refreshToken = new RefreshToken { AccessToken = new Token("access_token") { Client = new Client() { ClientId = "roclient" } }, LifeTime = 10, CreationTime = DateTimeOffset.UtcNow.AddSeconds(-15) }; var handle = Guid.NewGuid().ToString(); var store = new InMemoryRefreshTokenStore(); await store.StoreAsync(handle, refreshToken); var client = await _clients.FindClientByIdAsync("roclient"); var validator = Factory.CreateTokenRequestValidator( refreshTokens: store); var parameters = new NameValueCollection(); parameters.Add(Constants.TokenRequest.GrantType, "refresh_token"); parameters.Add(Constants.TokenRequest.RefreshToken, handle); var result = await validator.ValidateRequestAsync(parameters, client); result.IsError.Should().BeTrue(); result.Error.Should().Be(Constants.TokenErrors.InvalidGrant); }
private async Task When_refreshing_onetimeonly_absolute_token_then_raise_event_with_two_different_handlers() { // Given var oldHandle = "old_handle"; var client = new Client() { RefreshTokenUsage = TokenUsage.OneTimeOnly, RefreshTokenExpiration = TokenExpiration.Absolute }; var refreshToken = new RefreshToken() { AccessToken = new Token("token_type") { Client = new Client() } }; // When await _defaultRefreshTokenService.UpdateRefreshTokenAsync(oldHandle, refreshToken, client); // Then _eventServiceMock.Verify(x => x.RaiseAsync<RefreshTokenRefreshDetails>( It.Is<Event<RefreshTokenRefreshDetails>>(p => p.Details.OldHandle == oldHandle && p.Details.NewHandle != p.Details.OldHandle)), Times.Once); }
public async Task StoreAsync(string key, RefreshToken value) { var result = await Collection.ReplaceOneAsync( Filter.ById(key), _serializer.Serialize(key, value), PerformUpsert ).ConfigureAwait(false); Log.Debug(result.ToString); }
public async Task StoreAsync(string key, RefreshToken value) { using (var s = _store.OpenAsyncSession()) using (s.Advanced.DocumentStore.AggressivelyCache()) { var toSave = Data.StoredRefreshToken.ToDbFormat(key, value); await s.StoreAsync(toSave); await s.SaveChangesAsync(); } }
public async Task<RefreshToken> Deserialize(BsonDocument doc) { var token = new RefreshToken(); BsonValue at; if (doc.TryGetValue("accessToken", out at)) { token.AccessToken = await _tokenSerializer.Deserialize(at.AsBsonDocument); } token.CreationTime = doc.GetValueOrDefault("creationTime", token.CreationTime); token.LifeTime = doc.GetValueOrDefault("lifetime", token.LifeTime); token.Version = doc.GetValueOrDefault("version", token.Version); return token; }
internal static StoredRefreshToken ToDbFormat(string key, RefreshToken refreshToken) { return new StoredRefreshToken { Id = "refreshtokens/" + key, ClientId = refreshToken.ClientId, Scopes = refreshToken.Scopes, CreationTime = refreshToken.CreationTime, LifeTime = refreshToken.LifeTime, SubjectId = refreshToken.SubjectId, Version = refreshToken.Version, Expires = refreshToken.CreationTime.AddSeconds(refreshToken.LifeTime), AccessToken = Data.StoredToken.ToDbFormat(refreshToken.AccessToken) }; }
public BsonDocument Serialize(string key, RefreshToken value) { var doc = new BsonDocument(); doc["_id"] = key; doc["_version"] = 1; doc["_expires"] = value.CreationTime.AddSeconds(value.LifeTime).ToBsonDateTime(); doc["_clientId"] = value.ClientId; doc["_subjectId"] = value.SubjectId; var accessToken = new BsonDocument(); _tokenSerializer.Serialize(accessToken ,value.AccessToken); doc["accessToken"] = accessToken; doc["creationTime"] = value.CreationTime.ToBsonDateTime(); doc["lifetime"] = value.LifeTime; doc["version"] = value.Version; return doc; }
/// <summary> /// Stores the data. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns></returns> public Task StoreAsync(string key, RefreshToken value) { _repository[key] = value; return Task.FromResult<object>(null); }
public async Task Valid_RefreshToken_Request_using_Restricted_Client() { var mock = new Mock<IUserService>(); var subjectClaim = new Claim(Constants.ClaimTypes.Subject, "foo"); var refreshToken = new RefreshToken { AccessToken = new Token("access_token") { Claims = new List<Claim> { subjectClaim }, Client = new Client { ClientId = "roclient_restricted_refresh"} }, LifeTime = 600, CreationTime = DateTimeOffset.UtcNow }; var handle = Guid.NewGuid().ToString(); var store = new InMemoryRefreshTokenStore(); await store.StoreAsync(handle, refreshToken); var client = await _clients.FindClientByIdAsync("roclient_restricted_refresh"); var validator = Factory.CreateTokenRequestValidator( refreshTokens: store, userService: mock.Object); var parameters = new NameValueCollection(); parameters.Add(Constants.TokenRequest.GrantType, "refresh_token"); parameters.Add(Constants.TokenRequest.RefreshToken, handle); var result = await validator.ValidateRequestAsync(parameters, client); result.IsError.Should().BeFalse(); }
public void ToSimpleEntity_WhenComplexEntity_ExpectCorrectMap() { // Arrange var mockPropertyMapper = new Mock<IPropertyGetSettersTyped<RefreshToken>>(); var mockClaimsPrincipalMapper = new Mock<IMapper<SimpleClaimsPrincipal, ClaimsPrincipal>>(); var mockTokenMapper = new Mock<IMapper<SimpleToken, Token>>(); mockClaimsPrincipalMapper.Setup(r => r.ToSimpleEntity(It.IsAny<ClaimsPrincipal>())) .Returns(new SimpleClaimsPrincipal()); mockTokenMapper.Setup(r => r.ToSimpleEntity(It.IsAny<Token>())).Returns(new SimpleToken()); mockPropertyMapper.Setup(r => r.GetGetters(It.IsAny<Type>())) .Returns(new Dictionary<string, Func<RefreshToken, object>>()); var refreshTokenMappers = new RefreshTokenMappers<RefreshToken>( mockPropertyMapper.Object, mockClaimsPrincipalMapper.Object, mockTokenMapper.Object); var complexEntity = new RefreshToken { Subject = new ClaimsPrincipal(), CreationTime = new DateTimeOffset(new DateTime(2016, 1, 1)), AccessToken = new Token(), LifeTime = 1, Version = 1 }; // Act var stopwatch = Stopwatch.StartNew(); var simpleRefreshToken = refreshTokenMappers.ToSimpleEntity(complexEntity); stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); Assert.That(simpleRefreshToken.Subject, Is.Not.Null); Assert.That(simpleRefreshToken.AccessToken, Is.Not.Null); Assert.That(simpleRefreshToken.CreationTime, Is.EqualTo(new DateTimeOffset(new DateTime(2016, 1, 1)))); Assert.That(simpleRefreshToken.LifeTime, Is.EqualTo(1)); Assert.That(simpleRefreshToken.Version, Is.EqualTo(1)); }
public void RefreshTokenPersists() { var subClaim = new Claim("sub", "*****@*****.**"); var emailClaim = new Claim("email", "*****@*****.**"); var token = new RefreshToken { AccessToken = new Token { CreationTime = DateTimeOffset.Now, Audience = "aud", Claims = new List<Claim> { subClaim, emailClaim}, Client = new Client { ClientId = "cid", ClientName = "cname", Enabled = true, SlidingRefreshTokenLifetime = 100, AccessTokenType = AccessTokenType.Jwt, Flow = Flows.Implicit }, Issuer = "iss", Lifetime = 1234567, Type = Constants.TokenTypes.RefreshToken, Version = 1, }, CreationTime = DateTimeOffset.Now, Version = 1, LifeTime = 1234567, Subject = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> { subClaim, emailClaim })) }; var clients = new List<Client> { new Client { ClientId = "cid", ClientName = "cname", Enabled = true, SlidingRefreshTokenLifetime = 100, AccessTokenType = AccessTokenType.Jwt, Flow = Flows.Implicit } }; var clientStore = new InMemoryClientStore(clients); var scopes = new List<Scope> { new Scope { Description = "sdescription", Name = "sname", Enabled = true, Emphasize = false, IncludeAllClaimsForUser = true, Required = false, Type = ScopeType.Identity } }; var scopeStore = new InMemoryScopeStore(scopes); var store = new RedisRefreshTokenStore(clientStore, scopeStore, RedisServer); store.StoreAsync("key2", token).Wait(); var result = store.GetAsync("key2").Result; Assert.Equal(token.SubjectId, result.SubjectId); Assert.Equal(token.ClientId, result.ClientId); }
/// <summary> /// Raises the refresh token refreshed event. /// </summary> /// <param name="oldHandle">The old handle.</param> /// <param name="newHandle">The new handle.</param> /// <param name="token">The token.</param> protected async Task RaiseRefreshTokenRefreshedEventAsync(string oldHandle, string newHandle, RefreshToken token) { await _events.RaiseSuccessfulRefreshTokenRefreshEventAsync(oldHandle, newHandle, token); }
/// <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.Debug("Creating refresh token"); int lifetime; if (client.RefreshTokenExpiration == TokenExpiration.Absolute) { Logger.Debug("Setting an absolute lifetime: " + client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } else { Logger.Debug("Setting a sliding lifetime: " + client.SlidingRefreshTokenLifetime); lifetime = client.SlidingRefreshTokenLifetime; } var handle = CryptoRandom.CreateUniqueId(); var refreshToken = new RefreshToken { CreationTime = DateTimeOffsetHelper.UtcNow, LifeTime = lifetime, AccessToken = accessToken, Subject = subject }; await _store.StoreAsync(handle, refreshToken); await RaiseRefreshTokenIssuedEventAsync(handle, refreshToken); return handle; }
public async Task Client_has_no_Resource_Scope_anymore_at_RefreshToken_Request() { var subjectClaim = new Claim(Constants.ClaimTypes.Subject, "foo"); var resourceScope = new Claim("scope", "resource"); var offlineAccessScope = new Claim("scope", "offline_access"); var refreshToken = new RefreshToken { AccessToken = new Token("access_token") { Claims = new List<Claim> { subjectClaim, resourceScope, offlineAccessScope }, Client = new Client { ClientId = "roclient_offline_only", }, }, LifeTime = 600, CreationTime = DateTimeOffset.UtcNow }; var handle = Guid.NewGuid().ToString(); var store = new InMemoryRefreshTokenStore(); await store.StoreAsync(handle, refreshToken); var client = await _clients.FindClientByIdAsync("roclient_offline_only"); var validator = Factory.CreateTokenRequestValidator( refreshTokens: store); var parameters = new NameValueCollection(); parameters.Add(Constants.TokenRequest.GrantType, "refresh_token"); parameters.Add(Constants.TokenRequest.RefreshToken, handle); var result = await validator.ValidateRequestAsync(parameters, client); result.IsError.Should().BeTrue(); result.Error.Should().Be(Constants.TokenErrors.InvalidGrant); }
/// <summary> /// Raises the refresh token issued event. /// </summary> /// <param name="handle">The handle.</param> /// <param name="token">The token.</param> protected async Task RaiseRefreshTokenIssuedEventAsync(string handle, RefreshToken token) { await _events.RaiseRefreshTokenIssuedEventAsync(handle, token); }
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); }
public async Task RefreshToken_Request_with_disabled_User() { var mock = new Mock<IUserService>(); mock.Setup(u => u.IsActiveAsync(It.IsAny<IsActiveContext>())).Callback<IsActiveContext>(ctx => { ctx.IsActive = false; }).Returns(Task.FromResult(0)); var subjectClaim = new Claim(Constants.ClaimTypes.Subject, "foo"); var refreshToken = new RefreshToken { AccessToken = new Token("access_token") { Claims = new List<Claim> { subjectClaim }, Client = new Client() { ClientId = "roclient" } }, LifeTime = 600, CreationTime = DateTimeOffset.UtcNow }; var handle = Guid.NewGuid().ToString(); var store = new InMemoryRefreshTokenStore(); await store.StoreAsync(handle, refreshToken); var client = await _clients.FindClientByIdAsync("roclient"); var validator = Factory.CreateTokenRequestValidator( refreshTokens: store, userService: mock.Object); var parameters = new NameValueCollection(); parameters.Add(Constants.TokenRequest.GrantType, "refresh_token"); parameters.Add(Constants.TokenRequest.RefreshToken, handle); var result = await validator.ValidateRequestAsync(parameters, client); result.IsError.Should().BeTrue(); }
public void TestFixtureSetup() { var database = RedisHelpers.ConnectionMultiplexer.GetDatabase(); 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, Subject = new ClaimsPrincipal() }; var settings = new JsonSettingsFactory(new CustomMappersConfiguration()).Create(); var serialized = JsonConvert.SerializeObject(refreshToken, settings); database.StringSet("DEFAULT_RTS_Existing", serialized); database.StringSet("DEFAULT_RTS_Delete", serialized); }
/// <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.Debug("Updating refresh token"); bool needsUpdate = false; string newHandle = handle; if (client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.Debug("Token usage is one-time only. Generating new handle"); // delete old one await _store.RemoveAsync(handle); // create new one newHandle = CryptoRandom.CreateUniqueId(); needsUpdate = true; } if (client.RefreshTokenExpiration == TokenExpiration.Sliding) { Logger.Debug("Refresh token expiration is sliding - extending lifetime"); // make sure we don't exceed absolute exp // cap it at absolute exp var currentLifetime = refreshToken.CreationTime.GetLifetimeInSeconds(); Logger.Debug("Current lifetime: " + currentLifetime.ToString()); var newLifetime = currentLifetime + client.SlidingRefreshTokenLifetime; Logger.Debug("New lifetime: " + newLifetime.ToString()); if (newLifetime > client.AbsoluteRefreshTokenLifetime) { newLifetime = client.AbsoluteRefreshTokenLifetime; Logger.Debug("New lifetime exceeds absolute lifetime, capping it to " + newLifetime.ToString()); } refreshToken.LifeTime = newLifetime; needsUpdate = true; } if (needsUpdate) { await _store.StoreAsync(newHandle, refreshToken); Logger.Debug("Updated refresh token in store"); } else { Logger.Debug("No updates to refresh token done"); } await RaiseRefreshTokenRefreshedEventAsync(handle, newHandle, refreshToken); Logger.Debug("No updates to refresh token done"); return handle; }