public async Task <Models.DeviceCode> FindByDeviceCodeAsync(string deviceCode) { using (var connection = new SqlConnection(_dapperStoreOptions.DbConnectionString)) { var sql = $@" SELECT DeviceCode, UserCode, SubjectId, ClientId, CreationTime, Expiration, Data FROM DeviceFlowCodes WHERE DeviceCode = @deviceCode; "; var deviceFlowCode = await connection.QueryFirstOrDefaultAsync <Entities.DeviceFlowCodes>(sql, new { deviceCode }); var deviceFlowCodeData = deviceFlowCode?.Data; if (deviceFlowCodeData == null) { return(null); } return(_persistentGrantSerializer.Deserialize <Models.DeviceCode>(deviceFlowCodeData)); } }
/// <summary> /// Gets all grants for a given subject ID. /// </summary> /// <param name="subjectId">The subject identifier.</param> /// <returns></returns> public async Task <IEnumerable <Consent> > GetAllGrantsAsync(string subjectId) { var grants = (await _store.GetAllAsync(subjectId)).ToArray(); try { var consents = grants.Where(x => x.Type == Constants.PersistedGrantTypes.UserConsent) .Select(x => _serializer.Deserialize <Consent>(x.Data)); var codes = grants.Where(x => x.Type == Constants.PersistedGrantTypes.AuthorizationCode) .Select(x => _serializer.Deserialize <AuthorizationCode>(x.Data)) .Select(x => new Consent { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.RequestedScopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); var refresh = grants.Where(x => x.Type == Constants.PersistedGrantTypes.RefreshToken) .Select(x => _serializer.Deserialize <RefreshToken>(x.Data)) .Select(x => new Consent { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); var access = grants.Where(x => x.Type == Constants.PersistedGrantTypes.ReferenceToken) .Select(x => _serializer.Deserialize <Token>(x.Data)) .Select(x => new Consent { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); consents = Join(consents, codes); consents = Join(consents, refresh); consents = Join(consents, access); return(consents.ToArray()); } catch (Exception ex) { _logger.LogError("Failed processing results from grant store. Exception: {0}", ex.Message); } return(Enumerable.Empty <Consent>()); }
/// <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)); }
/// <inheritdoc/> public async Task RemoveAllGrantsAsync(string subjectId, string clientId = null, string sessionId = null) { var removedGrants = await _persistedGrantDbContext.PersistedGrants.Where(x => x.SubjectId == subjectId && x.ClientId == clientId).ToListAsync(); await _inner.RemoveAllGrantsAsync(subjectId, clientId); var consents = removedGrants.Where(x => x.Type == IdentityServerConstants.PersistedGrantTypes.UserConsent); var scopeValues = new List <string>(); foreach (var consent in consents) { var consentData = _serializer.Deserialize <Consent>(consent.Data); if (consentData?.Scopes != null && consentData.Scopes.Any()) { scopeValues.AddRange(consentData.Scopes); } } var parsedScopesResult = _scopeParser.ParseScopeValues(scopeValues); if (!parsedScopesResult.Succeeded) { return; } await _parsedScopeNotificationService.Notify(clientId, parsedScopesResult.ParsedScopes, ParsedScopeNotificationType.GrantsRevoked); }
public async Task UpdateByUserCodeAsync_WhenDeviceCodeAuthorized_ExpectSubjectAndDataUpdated() { var testDeviceCode = $"device_{Guid.NewGuid().ToString()}"; var testUserCode = $"user_{Guid.NewGuid().ToString()}"; var expectedSubject = $"sub_{Guid.NewGuid().ToString()}"; var unauthorizedDeviceCode = new DeviceCode { ClientId = "device_flow", RequestedScopes = new[] { "openid", "api1" }, CreationTime = new DateTime(2018, 10, 19, 16, 14, 29), Lifetime = 300, IsOpenId = true }; var repo = g.operationalDb.GetRepository <Storage.Entities.DeviceFlowCodes>(); var entity = new Storage.Entities.DeviceFlowCodes { DeviceCode = testDeviceCode, UserCode = testUserCode, ClientId = unauthorizedDeviceCode.ClientId, CreationTime = unauthorizedDeviceCode.CreationTime, Expiration = unauthorizedDeviceCode.CreationTime.AddSeconds(unauthorizedDeviceCode.Lifetime), Data = serializer.Serialize(unauthorizedDeviceCode) }; repo.Insert(entity); var authorizedDeviceCode = new DeviceCode { ClientId = unauthorizedDeviceCode.ClientId, RequestedScopes = unauthorizedDeviceCode.RequestedScopes, AuthorizedScopes = unauthorizedDeviceCode.RequestedScopes, Subject = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> { new Claim(JwtClaimTypes.Subject, expectedSubject) })), IsAuthorized = true, IsOpenId = true, CreationTime = new DateTime(2018, 10, 19, 16, 14, 29), Lifetime = 300 }; var store = new DeviceFlowStore(g.operationalDb, new PersistentGrantSerializer(), FakeLogger <DeviceFlowStore> .Create()); await store.UpdateByUserCodeAsync(testUserCode, authorizedDeviceCode); Storage.Entities.DeviceFlowCodes updatedCodes; updatedCodes = repo.Where(x => x.UserCode == testUserCode).First(); // should be unchanged updatedCodes.DeviceCode.Should().Be(testDeviceCode); updatedCodes.ClientId.Should().Be(unauthorizedDeviceCode.ClientId); updatedCodes.CreationTime.Should().Be(unauthorizedDeviceCode.CreationTime); updatedCodes.Expiration.Should().Be(unauthorizedDeviceCode.CreationTime.AddSeconds(authorizedDeviceCode.Lifetime)); // should be changed var parsedCode = serializer.Deserialize <DeviceCode>(updatedCodes.Data); parsedCode.Should().BeEquivalentTo(authorizedDeviceCode, assertionOptions => assertionOptions.Excluding(x => x.Subject)); parsedCode.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).Should().NotBeNull(); }
public async Task <IEnumerable <Consent> > GetAllGrantsAsync(string subjectId) { var grants = await _store.GetAllAsync(subjectId); var consents = grants.Where(x => x.Type == Constants.PersistedGrantTypes.UserConsent) .Select(x => _serializer.Deserialize <Consent>(x.Data)); var codes = grants.Where(x => x.Type == Constants.PersistedGrantTypes.AuthorizationCode) .Select(x => _serializer.Deserialize <AuthorizationCode>(x.Data)) .Select(x => new Consent { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.RequestedScopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); var refresh = grants.Where(x => x.Type == Constants.PersistedGrantTypes.RefreshToken) .Select(x => _serializer.Deserialize <RefreshToken>(x.Data)) .Select(x => new Consent { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); var access = grants.Where(x => x.Type == Constants.PersistedGrantTypes.ReferenceToken) .Select(x => _serializer.Deserialize <Token>(x.Data)) .Select(x => new Consent { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); consents = Join(consents, codes); consents = Join(consents, refresh); consents = Join(consents, access); return(consents.ToArray()); }
public async Task <T> GetAsync(string key) { try { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } var cacheKey = GetKey(key); string json = await _getFallBack .ExecuteAsync(async() => await Task.Run( () => _handle.cache.Get <string>(cacheKey)) .ConfigureAwait(false) ) .ConfigureAwait(false); if (string.IsNullOrWhiteSpace(json)) { if (_debugLoggingEnabled) { _logger.LogDebug( "Cache Miss: No item with key {key} in NCache", key); } return(null); } else if (json.Equals(CacheHandle.CACHE_PROBLEMS)) { if (_errorLoggingEnabled) { _logger.LogError( $"Cache problems when accessing {key}"); } return(null); } else { if (_debugLoggingEnabled) { _logger.LogDebug( "Cache Hit: Item with key {key} found in NCache", key); } return(_serializer.Deserialize <T>(json)); } } catch (Exception ex) { if (_errorLoggingEnabled) { _logger.LogError( ex, $"Something wrong with GetAsync for key {key}"); } throw; } }
public async Task <IEnumerable <Consent> > GetAllUserConsent(string subjectId) { return(await _context.UserConstents .AsNoTracking() .Where(c => c.UserId == subjectId) .Select(c => _serializer.Deserialize <Consent>(c.Data)) .ToListAsync() .ConfigureAwait(false)); }
private DeviceCode ToModel(string entity) { if (entity == null) { return(null); } return(_serializer.Deserialize <DeviceCode>(entity)); }
public static DeviceCode ToModel(this DeviceFlowCodes deviceFlowCode) { if (deviceFlowCode == null || string.IsNullOrWhiteSpace(deviceFlowCode.Data)) { return(null); } return(_serializer.Deserialize <DeviceCode>(deviceFlowCode.Data)); }
/// <summary> /// Converts a serialized DeviceCode to a model. /// </summary> /// <param name="entity"></param> /// <returns></returns> protected DeviceCode ToModel(string entity) { if (entity == null) { return(null); } return(Serializer.Deserialize <DeviceCode>(entity)); }
public async Task <IEnumerable <Consent> > GetAllUserConsent(string subjectId) { return((await _store.GetAsync(new PageRequest { Filter = $"{nameof(UserConsent.UserId)} eq '{subjectId}'", Select = nameof(UserConsent.Data) }).ConfigureAwait(false)).Items .Select(c => _serializer.Deserialize <Consent>(c.Data))); }
private Models.DeviceCode ToModel(DeviceCode entity) { if (entity != null) { return(_serializer.Deserialize <Models.DeviceCode>(entity.Data)); } return(null); }
public async Task <AuthorizationCode> GetAuthorizationCodeAsync(string code) { var entity = await _context.AuthorizationCodes.FindAsync(code); if (entity != null) { return(_serializer.Deserialize <AuthorizationCode>(entity.Data)); } return(null); }
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()) { return(_serializer.Deserialize <T>(grant.Data)); } return(default(T)); }
public async Task <AuthorizationCode> GetAuthorizationCodeAsync(string code) { code = code ?? throw new ArgumentNullException(nameof(code)); var response = await _store.GetAsync(new PageRequest { Filter = $"{nameof(Entity.AuthorizationCode.Id)} eq '{code}'", Select = nameof(Entity.AuthorizationCode.Data) }).ConfigureAwait(false); if (response.Count == 1) { return(_serializer.Deserialize <AuthorizationCode>(response.Items.First().Data)); } return(null); }
/// <summary> /// Removes all grants for a given subject id and client id combination. /// </summary> /// <param name="subjectId">The subject identifier.</param> /// <param name="clientId">The client identifier.</param> public async Task RemoveAllGrantsAsync(string subjectId, string clientId) { var grants = await _persistedGrantDbContext.PersistedGrants.Where(x => x.SubjectId == subjectId && x.ClientId == clientId).ToListAsync(); await _inner.RemoveAllGrantsAsync(subjectId, clientId); var consents = grants.Where(x => x.Type == IdentityServerConstants.PersistedGrantTypes.UserConsent); var scopes = new List <string>(); foreach (var consent in consents) { var consentData = _serializer.Deserialize <Consent>(consent.Data); if (consentData?.Scopes != null && consentData.Scopes.Any()) { scopes.AddRange(consentData.Scopes); } } await _dynamicScopeNotificationService.Notify(clientId, scopes, DynamicScopeNotificationType.GrantsRevoked); }
/// <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)); }
private Grant TryDeserialize <TToken>(Entity.IGrant grant, Func <TToken, Grant> createGrant) { try { return(createGrant(_serializer.Deserialize <TToken>(grant.Data))); } catch (CryptographicException ex) { _logger.LogError(ex, "{Message}", ex.Message); return(new Grant { ClientId = grant.ClientId, CreationTime = grant.CreatedAt, Expiration = grant.Expiration, Description = _localizer["Cannot get the description of an internal error."], SubjectId = grant.UserId, Scopes = Array.Empty <string>() }); } }
/// <summary> /// Converts a serialized DeviceCode to a model. /// </summary> /// <param name="entity"></param> /// <returns></returns> protected DeviceCode ToModel(string entity) => entity == null ? null : Serializer.Deserialize <DeviceCode>(entity);
/// <summary> /// Gets all grants for a given subject ID. /// </summary> /// <param name="subjectId">The subject identifier.</param> /// <returns></returns> public async Task <IEnumerable <Grant> > GetAllGrantsAsync(string subjectId) { var request = new PageRequest { Take = null, Filter = $"{nameof(Entity.IGrant.UserId)} eq '{subjectId}'" }; var consentList = (await _userConsentStore.GetAsync(request).ConfigureAwait(false)).Items .Select(c => _serializer.Deserialize <Consent>(c.Data)) .Select(c => new Grant { ClientId = c.ClientId, CreationTime = c.CreationTime, Expiration = c.Expiration, Scopes = c.Scopes, SubjectId = subjectId }); var codeList = (await _authorizationCodeStore.GetAsync(request).ConfigureAwait(false)).Items .Select(c => _serializer.Deserialize <AuthorizationCode>(c.Data)) .Select(c => new Grant { ClientId = c.ClientId, CreationTime = c.CreationTime, Description = c.Description, Expiration = c.CreationTime.AddSeconds(c.Lifetime), Scopes = c.RequestedScopes, SubjectId = subjectId }); var refreshTokenList = (await _refreshTokenStore.GetAsync(request).ConfigureAwait(false)).Items .Select(t => _serializer.Deserialize <RefreshToken>(t.Data)) .Select(t => new Grant { ClientId = t.ClientId, CreationTime = t.CreationTime, Description = t.Description, Expiration = t.CreationTime.AddSeconds(t.Lifetime), Scopes = t.Scopes, SubjectId = subjectId }); var referenceTokenList = (await _referenceTokenStore.GetAsync(request).ConfigureAwait(false)).Items .Select(t => _serializer.Deserialize <Token>(t.Data)) .Select(t => new Grant { ClientId = t.ClientId, CreationTime = t.CreationTime, Description = t.Description, Expiration = t.CreationTime.AddSeconds(t.Lifetime), Scopes = t.Scopes, SubjectId = subjectId }); consentList = Join(consentList, codeList); consentList = Join(consentList, refreshTokenList); consentList = Join(consentList, referenceTokenList); return(consentList); }
private async Task <IEnumerable <UserConsentInfo> > GetPersistedGrantsAsync(string subjectId, string clientId, string consentType) { if (string.IsNullOrWhiteSpace(subjectId)) { throw new ArgumentNullException(nameof(subjectId)); } var grants = (await _persistedGrantStore.GetAllAsync(new PersistedGrantFilter { SubjectId = subjectId, ClientId = clientId, Type = consentType })) .ToArray(); try { var consents = grants .Where(x => x.Type == PersistedGrantTypes.UserConsent) .Select(x => _serializer.Deserialize <Consent>(x.Data)) .Select(x => new UserConsentInfo { ClientId = x.ClientId, Scopes = x.Scopes, CreatedAt = x.CreationTime, ExpiresAt = x.Expiration, Type = PersistedGrantTypes.UserConsent }); var codes = grants .Where(x => x.Type == PersistedGrantTypes.AuthorizationCode) .Select(x => _serializer.Deserialize <AuthorizationCode>(x.Data)) .Select(x => new UserConsentInfo { ClientId = x.ClientId, Scopes = x.RequestedScopes, CreatedAt = x.CreationTime, ExpiresAt = x.CreationTime.AddSeconds(x.Lifetime), Type = PersistedGrantTypes.AuthorizationCode }); var refresh = grants .Where(x => x.Type == PersistedGrantTypes.RefreshToken) .Select(x => _serializer.Deserialize <RefreshToken>(x.Data)) .Select(x => new UserConsentInfo { ClientId = x.ClientId, Scopes = x.Scopes, Claims = x.AccessToken?.Claims?.Select(x => new BasicClaimInfo { Type = x.Type, Value = x.Value }), CreatedAt = x.CreationTime, ExpiresAt = x.CreationTime.AddSeconds(x.Lifetime), Type = PersistedGrantTypes.RefreshToken }); var access = grants .Where(x => x.Type == PersistedGrantTypes.ReferenceToken) .Select(x => _serializer.Deserialize <Token>(x.Data)) .Select(x => new UserConsentInfo { ClientId = x.ClientId, Scopes = x.Scopes, Claims = x.Claims.Select(x => new BasicClaimInfo { Type = x.Type, Value = x.Value }), CreatedAt = x.CreationTime, ExpiresAt = x.CreationTime.AddSeconds(x.Lifetime), Type = PersistedGrantTypes.ReferenceToken }); consents = Join(consents, codes); consents = Join(consents, refresh); consents = Join(consents, access); return(consents.ToArray()); } catch (Exception) { } return(Enumerable.Empty <UserConsentInfo>()); }
public async Task UpdateByUserCodeAsync_WhenDeviceCodeAuthorized_ExpectSubjectAndDataUpdated() { var storeHolder = GetOperationalDocumentStoreHolder(); var testDeviceCode = $"device_{Guid.NewGuid().ToString()}"; var testUserCode = $"user_{Guid.NewGuid().ToString()}"; var expectedSubject = $"sub_{Guid.NewGuid().ToString()}"; var unauthorizedDeviceCode = new DeviceCode { ClientId = "device_flow", RequestedScopes = new[] { "openid", "api1" }, CreationTime = new DateTime(2018, 10, 19, 16, 14, 29), Lifetime = 300, IsOpenId = true }; using (var session = storeHolder.OpenAsyncSession()) { await session.StoreAsync(new DeviceFlowCode { DeviceCode = testDeviceCode, UserCode = testUserCode, ClientId = unauthorizedDeviceCode.ClientId, CreationTime = unauthorizedDeviceCode.CreationTime, Expiration = unauthorizedDeviceCode.CreationTime.AddSeconds(unauthorizedDeviceCode.Lifetime), Data = _serializer.Serialize(unauthorizedDeviceCode) }); await session.SaveChangesAsync(); } WaitForIndexing(storeHolder.IntegrationTest_GetDocumentStore()); var authorizedDeviceCode = new DeviceCode { ClientId = unauthorizedDeviceCode.ClientId, RequestedScopes = unauthorizedDeviceCode.RequestedScopes, AuthorizedScopes = unauthorizedDeviceCode.RequestedScopes, Subject = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> { new Claim(JwtClaimTypes.Subject, expectedSubject) })), IsAuthorized = true, IsOpenId = true, CreationTime = new DateTime(2018, 10, 19, 16, 14, 29), Lifetime = 300 }; var store = new DeviceFlowStore(storeHolder, new PersistentGrantSerializer(), FakeLogger <DeviceFlowStore> .Create()); await store.UpdateByUserCodeAsync(testUserCode, authorizedDeviceCode); WaitForIndexing(storeHolder.IntegrationTest_GetDocumentStore()); using (var session = storeHolder.OpenAsyncSession()) { var updatedCodes = await session.Query <DeviceFlowCode>().SingleAsync(x => x.UserCode == testUserCode); // should be unchanged updatedCodes.DeviceCode.Should().Be(testDeviceCode); updatedCodes.ClientId.Should().Be(unauthorizedDeviceCode.ClientId); updatedCodes.CreationTime.Should().Be(unauthorizedDeviceCode.CreationTime); updatedCodes.Expiration.Should() .Be(unauthorizedDeviceCode.CreationTime.AddSeconds(authorizedDeviceCode.Lifetime)); // should be changed var parsedCode = _serializer.Deserialize <DeviceCode>(updatedCodes.Data); parsedCode.Should().BeEquivalentTo(authorizedDeviceCode, assertionOptions => assertionOptions.Excluding(x => x.Subject)); parsedCode.Subject.Claims .FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).Should() .NotBeNull(); } }
protected DeviceCode ToModel(string entity) { return(entity == null ? null : _serializer.Deserialize <DeviceCode>(entity)); }
/// <inheritdoc/> public async Task <IEnumerable <Grant> > GetAllGrantsAsync(string subjectId) { if (String.IsNullOrWhiteSpace(subjectId)) { throw new ArgumentNullException(nameof(subjectId)); } var grants = (await _store.GetAllAsync(new PersistedGrantFilter { SubjectId = subjectId })).ToArray(); try { var consents = grants.Where(x => x.Type == IdentityServerConstants.PersistedGrantTypes.UserConsent) .Select(x => _serializer.Deserialize <Consent>(x.Data)) .Select(x => new Grant { ClientId = x.ClientId, SubjectId = subjectId, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.Expiration }); var codes = grants.Where(x => x.Type == IdentityServerConstants.PersistedGrantTypes.AuthorizationCode) .Select(x => _serializer.Deserialize <AuthorizationCode>(x.Data)) .Select(x => new Grant { ClientId = x.ClientId, SubjectId = subjectId, Description = x.Description, Scopes = x.RequestedScopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); var refresh = grants.Where(x => x.Type == IdentityServerConstants.PersistedGrantTypes.RefreshToken) .Select(x => _serializer.Deserialize <RefreshToken>(x.Data)) .Select(x => new Grant { ClientId = x.ClientId, SubjectId = subjectId, Description = x.Description, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); var access = grants.Where(x => x.Type == IdentityServerConstants.PersistedGrantTypes.ReferenceToken) .Select(x => _serializer.Deserialize <Token>(x.Data)) .Select(x => new Grant { ClientId = x.ClientId, SubjectId = subjectId, Description = x.Description, Scopes = x.Scopes, CreationTime = x.CreationTime, Expiration = x.CreationTime.AddSeconds(x.Lifetime) }); consents = Join(consents, codes); consents = Join(consents, refresh); consents = Join(consents, access); return(consents.ToArray()); } catch (Exception ex) { _logger.LogError(ex, "Failed processing results from grant store."); } return(Enumerable.Empty <Grant>()); }
public async Task UpdateByUserCodeAsync_WhenDeviceCodeAuthorized_ExpectSubjectAndDataUpdated(DbContextOptions <PersistedGrantDbContext> options) { var testDeviceCode = $"device_{Guid.NewGuid().ToString()}"; var testUserCode = $"user_{Guid.NewGuid().ToString()}"; var expectedSubject = $"sub_{Guid.NewGuid().ToString()}"; var unauthorizedDeviceCode = new DeviceCode { ClientId = "device_flow", RequestedScopes = new[] { "openid", "api1" }, CreationTime = new DateTime(2018, 10, 19, 16, 14, 29), Lifetime = 300, IsOpenId = true }; using (var context = new PersistedGrantDbContext(options)) { context.DeviceFlowCodes.Add(new DeviceFlowCodes { DeviceCode = testDeviceCode, UserCode = testUserCode, ClientId = unauthorizedDeviceCode.ClientId, CreationTime = unauthorizedDeviceCode.CreationTime, Expiration = unauthorizedDeviceCode.CreationTime.AddSeconds(unauthorizedDeviceCode.Lifetime), Data = serializer.Serialize(unauthorizedDeviceCode) }); context.SaveChanges(); } var authorizedDeviceCode = new DeviceCode { ClientId = unauthorizedDeviceCode.ClientId, RequestedScopes = unauthorizedDeviceCode.RequestedScopes, AuthorizedScopes = unauthorizedDeviceCode.RequestedScopes, Subject = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> { new Claim(JwtClaimTypes.Subject, expectedSubject) })), IsAuthorized = true, IsOpenId = true, CreationTime = new DateTime(2018, 10, 19, 16, 14, 29), Lifetime = 300 }; using (var context = new PersistedGrantDbContext(options)) { var store = new DeviceFlowStore(context, new PersistentGrantSerializer(), FakeLogger <DeviceFlowStore> .Create(), new NoneCancellationTokenProvider()); await store.UpdateByUserCodeAsync(testUserCode, authorizedDeviceCode); } DeviceFlowCodes updatedCodes; using (var context = new PersistedGrantDbContext(options)) { updatedCodes = context.DeviceFlowCodes.Single(x => x.UserCode == testUserCode); } // should be unchanged updatedCodes.DeviceCode.Should().Be(testDeviceCode); updatedCodes.ClientId.Should().Be(unauthorizedDeviceCode.ClientId); updatedCodes.CreationTime.Should().Be(unauthorizedDeviceCode.CreationTime); updatedCodes.Expiration.Should().Be(unauthorizedDeviceCode.CreationTime.AddSeconds(authorizedDeviceCode.Lifetime)); // should be changed var parsedCode = serializer.Deserialize <DeviceCode>(updatedCodes.Data); parsedCode.Should().BeEquivalentTo(authorizedDeviceCode, assertionOptions => assertionOptions.Excluding(x => x.Subject)); parsedCode.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject && x.Value == expectedSubject).Should().NotBeNull(); }