public async Task StoreUserConsentAsync_should_persist_grant() { var consent1 = new Consent() { ClientId = "client", SubjectId = "123", Scopes = new string[] { "foo", "bar" } }; await _userConsent.StoreUserConsentAsync(consent1); var consent2 = await _userConsent.GetUserConsentAsync("123", "client"); consent2.ClientId.Should().Be(consent1.ClientId); consent2.SubjectId.Should().Be(consent1.SubjectId); consent2.Scopes.ShouldBeEquivalentTo(new string[] { "bar", "foo" }); }
/// <summary> /// Checks if consent is required. /// </summary> /// <param name="subject">The user.</param> /// <param name="client">The client.</param> /// <param name="scopes">The scopes.</param> /// <returns> /// Boolean if consent is required. /// </returns> /// <exception cref="System.ArgumentNullException"> /// client /// or /// subject /// </exception> public virtual async Task <bool> RequiresConsentAsync(ClaimsPrincipal subject, Client client, IEnumerable <string> scopes) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (subject == null) { throw new ArgumentNullException(nameof(subject)); } if (!client.RequireConsent) { return(false); } if (!client.AllowRememberConsent) { return(true); } if (scopes == null || !scopes.Any()) { return(false); } // we always require consent for offline access if // the client has not disabled RequireConsent if (scopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess)) { return(true); } var consent = await _userConsentStore.GetUserConsentAsync(subject.GetSubjectId(), client.ClientId); if (consent == null) { return(true); } if (consent.Expiration.HasExpired(_options.UtcNow)) { await _userConsentStore.RemoveUserConsentAsync(consent.SubjectId, consent.ClientId); return(true); } if (consent.Scopes != null) { var intersect = scopes.Intersect(consent.Scopes); return(!(scopes.Count() == intersect.Count())); } return(true); }
/// <summary> /// Checks if consent is required. /// </summary> /// <param name="subject">The user.</param> /// <param name="client">The client.</param> /// <param name="scopes">The scopes.</param> /// <returns> /// Boolean if consent is required. /// </returns> /// <exception cref="System.ArgumentNullException"> /// client /// or /// subject /// </exception> public virtual async Task <bool> RequiresConsentAsync(ClaimsPrincipal subject, Client client, IEnumerable <string> scopes) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (subject == null) { throw new ArgumentNullException(nameof(subject)); } if (!client.RequireConsent) { return(false); } if (!client.AllowRememberConsent) { return(true); } if (scopes == null || !scopes.Any()) { return(false); } var consent = await _userConsentStore.GetUserConsentAsync(subject.GetSubjectId(), client.ClientId); if (consent?.Scopes != null) { var intersect = scopes.Intersect(consent.Scopes); return(!(scopes.Count() == intersect.Count())); } return(true); }
/// <summary> /// Checks if consent is required. /// </summary> /// <param name="subject">The user.</param> /// <param name="client">The client.</param> /// <param name="parsedScopes">The parsed scopes.</param> /// <returns> /// Boolean if consent is required. /// </returns> /// <exception cref="System.ArgumentNullException"> /// client /// or /// subject /// </exception> public virtual async Task <bool> RequiresConsentAsync(ClaimsPrincipal subject, Client client, IEnumerable <ParsedScopeValue> parsedScopes) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (subject == null) { throw new ArgumentNullException(nameof(subject)); } if (!client.RequireConsent) { Logger.LogDebug("Client is configured to not require consent, no consent is required"); return(false); } if (parsedScopes == null || !parsedScopes.Any()) { Logger.LogDebug("No scopes being requested, no consent is required"); return(false); } if (!client.AllowRememberConsent) { Logger.LogDebug("Client is configured to not allow remembering consent, consent is required"); return(true); } if (parsedScopes.Any(x => x.Name != x.Value)) { Logger.LogDebug("Scopes contains parameterized values, consent is required"); return(true); } var scopes = parsedScopes.Select(x => x.Value).ToArray(); // we always require consent for offline access if // the client has not disabled RequireConsent if (scopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess)) { Logger.LogDebug("Scopes contains offline_access, consent is required"); return(true); } var consent = await UserConsentStore.GetUserConsentAsync(subject.GetSubjectId(), client.ClientId); if (consent == null) { Logger.LogDebug("Found no prior consent from consent store, consent is required"); return(true); } if (consent.Expiration.HasExpired(Clock.UtcNow.UtcDateTime)) { Logger.LogDebug("Consent found in consent store is expired, consent is required"); await UserConsentStore.RemoveUserConsentAsync(consent.SubjectId, consent.ClientId); return(true); } if (consent.Scopes != null) { var intersect = scopes.Intersect(consent.Scopes); var different = scopes.Count() != intersect.Count(); if (different) { Logger.LogDebug("Consent found in consent store is different than current request, consent is required"); } else { Logger.LogDebug("Consent found in consent store is same as current request, consent is not required"); } return(different); } Logger.LogDebug("Consent found in consent store has no scopes, consent is required"); return(true); }