diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
index 9c5f849e..ce3e2bec 100644
--- a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
+++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
@@ -29,7 +29,7 @@ namespace OpenIddict.Abstractions
/// Extracts the authentication context class values from an .
///
/// The instance.
- public static ImmutableHashSet GetAcrValues([NotNull] this OpenIddictRequest request)
+ public static ImmutableArray GetAcrValues([NotNull] this OpenIddictRequest request)
{
if (request == null)
{
@@ -38,17 +38,17 @@ namespace OpenIddict.Abstractions
if (string.IsNullOrEmpty(request.AcrValues))
{
- return ImmutableHashSet.Create(StringComparer.Ordinal);
+ return ImmutableArray.Create();
}
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, GetValues(request.AcrValues, Separators.Space));
+ return GetValues(request.AcrValues, Separators.Space).Distinct(StringComparer.Ordinal).ToImmutableArray();
}
///
/// Extracts the response types from an .
///
/// The instance.
- public static ImmutableHashSet GetResponseTypes([NotNull] this OpenIddictRequest request)
+ public static ImmutableArray GetResponseTypes([NotNull] this OpenIddictRequest request)
{
if (request == null)
{
@@ -57,17 +57,17 @@ namespace OpenIddict.Abstractions
if (string.IsNullOrEmpty(request.ResponseType))
{
- return ImmutableHashSet.Create(StringComparer.Ordinal);
+ return ImmutableArray.Create();
}
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, GetValues(request.ResponseType, Separators.Space));
+ return GetValues(request.ResponseType, Separators.Space).Distinct(StringComparer.Ordinal).ToImmutableArray();
}
///
/// Extracts the scopes from an .
///
/// The instance.
- public static ImmutableHashSet GetScopes([NotNull] this OpenIddictRequest request)
+ public static ImmutableArray GetScopes([NotNull] this OpenIddictRequest request)
{
if (request == null)
{
@@ -76,10 +76,10 @@ namespace OpenIddict.Abstractions
if (string.IsNullOrEmpty(request.Scope))
{
- return ImmutableHashSet.Create(StringComparer.Ordinal);
+ return ImmutableArray.Create();
}
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, GetValues(request.Scope, Separators.Space));
+ return GetValues(request.Scope, Separators.Space).Distinct(StringComparer.Ordinal).ToImmutableArray();
}
///
@@ -524,7 +524,7 @@ namespace OpenIddict.Abstractions
///
/// The instance.
/// The destinations associated with the claim.
- public static ImmutableHashSet GetDestinations([NotNull] this Claim claim)
+ public static ImmutableArray GetDestinations([NotNull] this Claim claim)
{
if (claim == null)
{
@@ -535,10 +535,10 @@ namespace OpenIddict.Abstractions
if (string.IsNullOrEmpty(destinations))
{
- return ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase);
+ return ImmutableArray.Create();
}
- return ImmutableHashSet.CreateRange(StringComparer.OrdinalIgnoreCase, JArray.Parse(destinations).Values());
+ return JArray.Parse(destinations).Values().Distinct(StringComparer.OrdinalIgnoreCase).ToImmutableArray();
}
///
@@ -558,7 +558,14 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The destination cannot be null or empty.", nameof(destination));
}
- return GetDestinations(claim).Contains(destination, StringComparer.OrdinalIgnoreCase);
+ claim.Properties.TryGetValue(Properties.Destinations, out string destinations);
+
+ if (string.IsNullOrEmpty(destinations))
+ {
+ return false;
+ }
+
+ return JArray.Parse(destinations).Values().Contains(destination, StringComparer.OrdinalIgnoreCase);
}
///
@@ -566,14 +573,14 @@ namespace OpenIddict.Abstractions
///
/// The instance.
/// The destinations.
- public static Claim SetDestinations([NotNull] this Claim claim, IEnumerable destinations)
+ public static Claim SetDestinations([NotNull] this Claim claim, ImmutableArray destinations)
{
if (claim == null)
{
throw new ArgumentNullException(nameof(claim));
}
- if (destinations == null || !destinations.Any())
+ if (destinations.IsDefaultOrEmpty)
{
claim.Properties.Remove(Properties.Destinations);
@@ -596,10 +603,16 @@ namespace OpenIddict.Abstractions
///
/// The instance.
/// The destinations.
- public static Claim SetDestinations([NotNull] this Claim claim, params string[] destinations)
- // Note: guarding the destinations parameter against null values
- // is not necessary as AsEnumerable() doesn't throw on null values.
- => claim.SetDestinations(destinations.AsEnumerable());
+ public static Claim SetDestinations([NotNull] this Claim claim, [CanBeNull] IEnumerable destinations)
+ => claim.SetDestinations(destinations?.ToImmutableArray() ?? ImmutableArray.Create());
+
+ ///
+ /// Adds specific destinations to a claim.
+ ///
+ /// The instance.
+ /// The destinations.
+ public static Claim SetDestinations([NotNull] this Claim claim, [CanBeNull] params string[] destinations)
+ => claim.SetDestinations(destinations?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Clones an identity by filtering its claims and the claims of its actor, recursively.
@@ -714,7 +727,7 @@ namespace OpenIddict.Abstractions
public static ClaimsIdentity AddClaim(
[NotNull] this ClaimsIdentity identity,
[NotNull] string type, [NotNull] string value,
- [NotNull] IEnumerable destinations)
+ [NotNull] ImmutableArray destinations)
{
if (identity == null)
{
@@ -751,9 +764,7 @@ namespace OpenIddict.Abstractions
[NotNull] this ClaimsIdentity identity,
[NotNull] string type, [NotNull] string value,
[NotNull] params string[] destinations)
- // Note: guarding the destinations parameter against null values
- // is not necessary as AsEnumerable() doesn't throw on null values.
- => identity.AddClaim(type, value, destinations.AsEnumerable());
+ => identity.AddClaim(type, value, destinations?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Gets the claim value corresponding to the given type.
@@ -803,7 +814,7 @@ namespace OpenIddict.Abstractions
/// The identity.
/// The type associated with the claims.
/// The claim values.
- public static ImmutableHashSet GetClaims([NotNull] this ClaimsIdentity identity, [NotNull] string type)
+ public static ImmutableArray GetClaims([NotNull] this ClaimsIdentity identity, [NotNull] string type)
{
if (identity == null)
{
@@ -815,7 +826,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The claim type cannot be null or empty.", nameof(type));
}
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, identity.FindAll(type).Select(claim => claim.Value));
+ return identity.FindAll(type).Select(claim => claim.Value).Distinct(StringComparer.Ordinal).ToImmutableArray();
}
///
@@ -824,7 +835,7 @@ namespace OpenIddict.Abstractions
/// The principal.
/// The type associated with the claims.
/// The claim values.
- public static ImmutableHashSet GetClaims([NotNull] this ClaimsPrincipal principal, [NotNull] string type)
+ public static ImmutableArray GetClaims([NotNull] this ClaimsPrincipal principal, [NotNull] string type)
{
if (principal == null)
{
@@ -836,7 +847,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The claim type cannot be null or empty.", nameof(type));
}
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, principal.FindAll(type).Select(claim => claim.Value));
+ return principal.FindAll(type).Select(claim => claim.Value).Distinct(StringComparer.Ordinal).ToImmutableArray();
}
///
@@ -964,7 +975,7 @@ namespace OpenIddict.Abstractions
/// The claim values.
/// The claims identity.
public static ClaimsIdentity SetClaims([NotNull] this ClaimsIdentity identity,
- [NotNull] string type, [NotNull] IEnumerable values)
+ [NotNull] string type, [NotNull] ImmutableArray values)
{
if (identity == null)
{
@@ -978,7 +989,7 @@ namespace OpenIddict.Abstractions
identity.RemoveClaims(type);
- foreach (var value in values)
+ foreach (var value in values.Distinct(StringComparer.Ordinal))
{
identity.AddClaim(type, value);
}
@@ -994,7 +1005,7 @@ namespace OpenIddict.Abstractions
/// The claim values.
/// The claims identity.
public static ClaimsPrincipal SetClaims([NotNull] this ClaimsPrincipal principal,
- [NotNull] string type, [NotNull] IEnumerable values)
+ [NotNull] string type, [NotNull] ImmutableArray values)
{
if (principal == null)
{
@@ -1008,7 +1019,7 @@ namespace OpenIddict.Abstractions
principal.RemoveClaims(type);
- foreach (var value in values)
+ foreach (var value in values.Distinct(StringComparer.Ordinal))
{
((ClaimsIdentity) principal.Identity).AddClaim(type, value);
}
@@ -1073,60 +1084,32 @@ namespace OpenIddict.Abstractions
///
/// The claims principal.
/// The audiences list or an empty set if the claims cannot be found.
- public static ImmutableHashSet GetAudiences([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, principal.GetClaims(Claims.Audience));
- }
+ public static ImmutableArray GetAudiences([NotNull] this ClaimsPrincipal principal)
+ => principal.GetClaims(Claims.Audience);
///
/// Gets the presenters list stored in the claims principal.
///
/// The claims principal.
/// The presenters list or an empty set if the claims cannot be found.
- public static ImmutableHashSet GetPresenters([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, principal.GetClaims(Claims.Private.Presenters));
- }
+ public static ImmutableArray GetPresenters([NotNull] this ClaimsPrincipal principal)
+ => principal.GetClaims(Claims.Private.Presenters);
///
/// Gets the resources list stored in the claims principal.
///
/// The claims principal.
/// The resources list or an empty set if the claims cannot be found.
- public static ImmutableHashSet GetResources([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, principal.GetClaims(Claims.Private.Resources));
- }
+ public static ImmutableArray GetResources([NotNull] this ClaimsPrincipal principal)
+ => principal.GetClaims(Claims.Private.Resources);
///
/// Gets the scopes list stored in the claims principal.
///
/// The claims principal.
/// The scopes list or an empty set if the claim cannot be found.
- public static ImmutableHashSet GetScopes([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return ImmutableHashSet.CreateRange(StringComparer.Ordinal, principal.GetClaims(Claims.Private.Scopes));
- }
+ public static ImmutableArray GetScopes([NotNull] this ClaimsPrincipal principal)
+ => principal.GetClaims(Claims.Private.Scopes);
///
/// Gets the access token lifetime associated with the claims principal.
@@ -1296,14 +1279,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
/// The unique identifier or null if the claim cannot be found.
public static string GetInternalAuthorizationId([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.GetClaim(Claims.Private.AuthorizationId);
- }
+ => principal.GetClaim(Claims.Private.AuthorizationId);
///
/// Gets the internal token identifier associated with the claims principal.
@@ -1311,14 +1287,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
/// The unique identifier or null if the claim cannot be found.
public static string GetInternalTokenId([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.GetClaim(Claims.Private.TokenId);
- }
+ => principal.GetClaim(Claims.Private.TokenId);
///
/// Gets the token usage associated with the claims principal.
@@ -1326,14 +1295,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
/// The token usage or null if the claim cannot be found.
public static string GetTokenUsage([NotNull] this ClaimsPrincipal principal)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.GetClaim(Claims.Private.TokenUsage);
- }
+ => principal.GetClaim(Claims.Private.TokenUsage);
///
/// Gets a boolean value indicating whether the
@@ -1432,7 +1394,15 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The audience cannot be null or empty.", nameof(audience));
}
- return principal.GetAudiences().Contains(audience);
+ foreach (var claim in principal.FindAll(Claims.Audience))
+ {
+ if (string.Equals(claim.Value, audience, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
///
@@ -1468,7 +1438,15 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The presenter cannot be null or empty.", nameof(presenter));
}
- return principal.GetPresenters().Contains(presenter);
+ foreach (var claim in principal.FindAll(Claims.Private.Presenters))
+ {
+ if (string.Equals(claim.Value, presenter, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
///
@@ -1504,7 +1482,15 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The resource cannot be null or empty.", nameof(resource));
}
- return principal.GetResources().Contains(resource);
+ foreach (var claim in principal.FindAll(Claims.Private.Resources))
+ {
+ if (string.Equals(claim.Value, resource, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
///
@@ -1540,7 +1526,15 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The scope cannot be null or empty.", nameof(scope));
}
- return principal.GetScopes().Contains(scope);
+ foreach (var claim in principal.FindAll(Claims.Private.Scopes))
+ {
+ if (string.Equals(claim.Value, scope, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
///
@@ -1601,16 +1595,19 @@ namespace OpenIddict.Abstractions
/// The audiences to store.
/// The claims principal.
public static ClaimsPrincipal SetAudiences(
- [NotNull] this ClaimsPrincipal principal,
- [CanBeNull] IEnumerable audiences)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] ImmutableArray audiences)
+ => principal.SetClaims(Claims.Audience, audiences);
- return principal.SetClaims(Claims.Audience, audiences.Distinct(StringComparer.Ordinal));
- }
+ ///
+ /// Sets the audiences list in the claims principal.
+ /// Note: this method automatically excludes duplicate audiences.
+ ///
+ /// The claims principal.
+ /// The audiences to store.
+ /// The claims principal.
+ public static ClaimsPrincipal SetAudiences(
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] IEnumerable audiences)
+ => principal.SetAudiences(audiences?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the audiences list in the claims principal.
@@ -1621,9 +1618,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
public static ClaimsPrincipal SetAudiences(
[NotNull] this ClaimsPrincipal principal, [CanBeNull] params string[] audiences)
- // Note: guarding the audiences parameter against null values
- // is not necessary as AsEnumerable() doesn't throw on null values.
- => principal.SetAudiences(audiences.AsEnumerable());
+ => principal.SetAudiences(audiences?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the presenters list in the claims principal.
@@ -1633,16 +1628,19 @@ namespace OpenIddict.Abstractions
/// The presenters to store.
/// The claims principal.
public static ClaimsPrincipal SetPresenters(
- [NotNull] this ClaimsPrincipal principal,
- [CanBeNull] IEnumerable presenters)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] ImmutableArray presenters)
+ => principal.SetClaims(Claims.Private.Presenters, presenters);
- return principal.SetClaims(Claims.Private.Presenters, presenters.Distinct(StringComparer.Ordinal));
- }
+ ///
+ /// Sets the presenters list in the claims principal.
+ /// Note: this method automatically excludes duplicate presenters.
+ ///
+ /// The claims principal.
+ /// The presenters to store.
+ /// The claims principal.
+ public static ClaimsPrincipal SetPresenters(
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] IEnumerable presenters)
+ => principal.SetPresenters(presenters?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the presenters list in the claims principal.
@@ -1653,9 +1651,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
public static ClaimsPrincipal SetPresenters(
[NotNull] this ClaimsPrincipal principal, [CanBeNull] params string[] presenters)
- // Note: guarding the presenters parameter against null values
- // is not necessary as AsEnumerable() doesn't throw on null values.
- => principal.SetPresenters(presenters.AsEnumerable());
+ => principal.SetPresenters(presenters?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the resources list in the claims principal.
@@ -1665,16 +1661,19 @@ namespace OpenIddict.Abstractions
/// The resources to store.
/// The claims principal.
public static ClaimsPrincipal SetResources(
- [NotNull] this ClaimsPrincipal principal,
- [CanBeNull] IEnumerable resources)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] ImmutableArray resources)
+ => principal.SetClaims(Claims.Private.Resources, resources);
- return principal.SetClaims(Claims.Private.Resources, resources.Distinct(StringComparer.Ordinal));
- }
+ ///
+ /// Sets the resources list in the claims principal.
+ /// Note: this method automatically excludes duplicate resources.
+ ///
+ /// The claims principal.
+ /// The resources to store.
+ /// The claims principal.
+ public static ClaimsPrincipal SetResources(
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] IEnumerable resources)
+ => principal.SetResources(resources?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the resources list in the claims principal.
@@ -1685,9 +1684,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
public static ClaimsPrincipal SetResources(
[NotNull] this ClaimsPrincipal principal, [CanBeNull] params string[] resources)
- // Note: guarding the resources parameter against null values
- // is not necessary as AsEnumerable() doesn't throw on null values.
- => principal.SetResources(resources.AsEnumerable());
+ => principal.SetResources(resources?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the scopes list in the claims principal.
@@ -1697,15 +1694,19 @@ namespace OpenIddict.Abstractions
/// The scopes to store.
/// The claims principal.
public static ClaimsPrincipal SetScopes(
- [NotNull] this ClaimsPrincipal principal, [CanBeNull] IEnumerable scopes)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] ImmutableArray scopes)
+ => principal.SetClaims(Claims.Private.Scopes, scopes);
- return principal.SetClaims(Claims.Private.Scopes, scopes.Distinct(StringComparer.Ordinal));
- }
+ ///
+ /// Sets the scopes list in the claims principal.
+ /// Note: this method automatically excludes duplicate scopes.
+ ///
+ /// The claims principal.
+ /// The scopes to store.
+ /// The claims principal.
+ public static ClaimsPrincipal SetScopes(
+ [NotNull] this ClaimsPrincipal principal, [CanBeNull] IEnumerable scopes)
+ => principal.SetScopes(scopes?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the scopes list in the claims principal.
@@ -1716,9 +1717,7 @@ namespace OpenIddict.Abstractions
/// The claims principal.
public static ClaimsPrincipal SetScopes(
[NotNull] this ClaimsPrincipal principal, [CanBeNull] params string[] scopes)
- // Note: guarding the scopes parameter against null values
- // is not necessary as AsEnumerable() doesn't throw on null values.
- => principal.SetScopes(scopes.AsEnumerable());
+ => principal.SetScopes(scopes?.ToImmutableArray() ?? ImmutableArray.Create());
///
/// Sets the access token lifetime associated with the claims principal.
@@ -1727,14 +1726,7 @@ namespace OpenIddict.Abstractions
/// The access token lifetime to store.
/// The claims principal.
public static ClaimsPrincipal SetAccessTokenLifetime([NotNull] this ClaimsPrincipal principal, TimeSpan? lifetime)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.AccessTokenLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
- }
+ => principal.SetClaim(Claims.Private.AccessTokenLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
///
/// Sets the authorization code lifetime associated with the claims principal.
@@ -1743,14 +1735,7 @@ namespace OpenIddict.Abstractions
/// The authorization code lifetime to store.
/// The claims principal.
public static ClaimsPrincipal SetAuthorizationCodeLifetime([NotNull] this ClaimsPrincipal principal, TimeSpan? lifetime)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.AuthorizationCodeLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
- }
+ => principal.SetClaim(Claims.Private.AuthorizationCodeLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
///
/// Sets the device code lifetime associated with the claims principal.
@@ -1759,14 +1744,7 @@ namespace OpenIddict.Abstractions
/// The device code lifetime to store.
/// The claims principal.
public static ClaimsPrincipal SetDeviceCodeLifetime([NotNull] this ClaimsPrincipal principal, TimeSpan? lifetime)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.DeviceCodeLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
- }
+ => principal.SetClaim(Claims.Private.DeviceCodeLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
///
/// Sets the identity token lifetime associated with the claims principal.
@@ -1775,14 +1753,7 @@ namespace OpenIddict.Abstractions
/// The identity token lifetime to store.
/// The claims principal.
public static ClaimsPrincipal SetIdentityTokenLifetime([NotNull] this ClaimsPrincipal principal, TimeSpan? lifetime)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.IdentityTokenLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
- }
+ => principal.SetClaim(Claims.Private.IdentityTokenLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
///
/// Sets the refresh token lifetime associated with the claims principal.
@@ -1791,14 +1762,7 @@ namespace OpenIddict.Abstractions
/// The refresh token lifetime to store.
/// The claims principal.
public static ClaimsPrincipal SetRefreshTokenLifetime([NotNull] this ClaimsPrincipal principal, TimeSpan? lifetime)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.RefreshTokenLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
- }
+ => principal.SetClaim(Claims.Private.RefreshTokenLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
///
/// Sets the user code lifetime associated with the claims principal.
@@ -1807,14 +1771,7 @@ namespace OpenIddict.Abstractions
/// The user code lifetime to store.
/// The claims principal.
public static ClaimsPrincipal SetUserCodeLifetime([NotNull] this ClaimsPrincipal principal, TimeSpan? lifetime)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.UserCodeLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
- }
+ => principal.SetClaim(Claims.Private.UserCodeLifetime, lifetime?.TotalSeconds.ToString(CultureInfo.InvariantCulture));
///
/// Sets the internal authorization identifier associated with the claims principal.
@@ -1823,14 +1780,7 @@ namespace OpenIddict.Abstractions
/// The unique identifier to store.
/// The claims principal.
public static ClaimsPrincipal SetInternalAuthorizationId([NotNull] this ClaimsPrincipal principal, string identifier)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.AuthorizationId, identifier);
- }
+ => principal.SetClaim(Claims.Private.AuthorizationId, identifier);
///
/// Sets the internal token identifier associated with the claims principal.
@@ -1839,14 +1789,7 @@ namespace OpenIddict.Abstractions
/// The unique identifier to store.
/// The claims principal.
public static ClaimsPrincipal SetInternalTokenId([NotNull] this ClaimsPrincipal principal, string identifier)
- {
- if (principal == null)
- {
- throw new ArgumentNullException(nameof(principal));
- }
-
- return principal.SetClaim(Claims.Private.TokenId, identifier);
- }
+ => principal.SetClaim(Claims.Private.TokenId, identifier);
private static IEnumerable GetValues(string source, char[] separators)
{
diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
index eb6c2c16..5db97b2d 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
@@ -696,9 +696,8 @@ namespace OpenIddict.Core
throw new ArgumentNullException(nameof(authorization));
}
- return (await Store.GetScopesAsync(authorization, cancellationToken))
- .ToImmutableHashSet(StringComparer.Ordinal)
- .IsSupersetOf(scopes);
+ return new HashSet(await Store.GetScopesAsync(
+ authorization, cancellationToken), StringComparer.Ordinal).IsSupersetOf(scopes);
}
///
diff --git a/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs b/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs
index bca01712..837f35e0 100644
--- a/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs
+++ b/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs
@@ -173,8 +173,9 @@ namespace OpenIddict.Server.DataProtection
static string GetProperty(IReadOnlyDictionary properties, string name)
=> properties.TryGetValue(name, out var value) ? value : null;
- static IEnumerable GetArrayProperty(IReadOnlyDictionary properties, string name)
- => properties.TryGetValue(name, out var value) ? JArray.Parse(value).Values() : Enumerable.Empty();
+ static ImmutableArray GetArrayProperty(IReadOnlyDictionary properties, string name)
+ => properties.TryGetValue(name, out var value) ?
+ JArray.Parse(value).Values().ToImmutableArray() : ImmutableArray.Create();
static DateTimeOffset? GetDateProperty(IReadOnlyDictionary properties, string name)
=> properties.TryGetValue(name, out var value) ? (DateTimeOffset?)
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
index f8a7373e..6de87249 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
@@ -5,9 +5,9 @@
*/
using System;
+using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
-using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -16,7 +16,6 @@ using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlerFilters;
-using Properties = OpenIddict.Server.OpenIddictServerConstants.Properties;
namespace OpenIddict.Server
{
@@ -637,7 +636,7 @@ namespace OpenIddict.Server
}
// Reject requests that specify an unsupported response_type.
- var types = context.Request.GetResponseTypes();
+ var types = new HashSet(context.Request.GetResponseTypes(), StringComparer.Ordinal);
if (!context.Options.ResponseTypes.Any(type =>
types.SetEquals(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))))
{
@@ -1245,12 +1244,14 @@ namespace OpenIddict.Server
}
// If all the specified scopes are registered in the options, avoid making a database lookup.
- var scopes = context.Request.GetScopes().Except(context.Options.Scopes);
+ var scopes = new HashSet(context.Request.GetScopes(), StringComparer.Ordinal);
+ scopes.ExceptWith(context.Options.Scopes);
+
if (scopes.Count != 0)
{
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{
- scopes = scopes.Remove(await _scopeManager.GetNameAsync(scope));
+ scopes.Remove(await _scopeManager.GetNameAsync(scope));
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
index 20fedf5a..c8e043e5 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
@@ -5,6 +5,7 @@
*/
using System;
+using System.Collections.Generic;
using System.Collections.Immutable;
using System.Security.Claims;
using System.Text;
@@ -454,12 +455,14 @@ namespace OpenIddict.Server
}
// If all the specified scopes are registered in the options, avoid making a database lookup.
- var scopes = context.Request.GetScopes().Except(context.Options.Scopes);
+ var scopes = new HashSet(context.Request.GetScopes(), StringComparer.Ordinal);
+ scopes.ExceptWith(context.Options.Scopes);
+
if (scopes.Count != 0)
{
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{
- scopes = scopes.Remove(await _scopeManager.GetNameAsync(scope));
+ scopes.Remove(await _scopeManager.GetNameAsync(scope));
}
}
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
index c047ba1e..b605d24c 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
@@ -5,7 +5,9 @@
*/
using System;
+using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
@@ -760,12 +762,14 @@ namespace OpenIddict.Server
}
// If all the specified scopes are registered in the options, avoid making a database lookup.
- var scopes = context.Request.GetScopes().Except(context.Options.Scopes);
+ var scopes = new HashSet(context.Request.GetScopes(), StringComparer.Ordinal);
+ scopes.ExceptWith(context.Options.Scopes);
+
if (scopes.Count != 0)
{
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{
- scopes = scopes.Remove(await _scopeManager.GetNameAsync(scope));
+ scopes.Remove(await _scopeManager.GetNameAsync(scope));
}
}
@@ -1422,7 +1426,7 @@ namespace OpenIddict.Server
}
var presenters = context.Principal.GetPresenters();
- if (presenters.Count == 0)
+ if (presenters.IsDefaultOrEmpty)
{
// Note: presenters may be empty during a grant_type=refresh_token request if the refresh token
// was issued to a public client but cannot be null for an authorization or device code grant request.
@@ -1725,7 +1729,7 @@ namespace OpenIddict.Server
// When an explicit scope parameter has been included in the token request
// but was missing from the initial request, the request MUST be rejected.
// See http://tools.ietf.org/html/rfc6749#section-6 for more information.
- var scopes = context.Principal.GetScopes();
+ var scopes = new HashSet(context.Principal.GetScopes(), StringComparer.Ordinal);
if (scopes.Count == 0)
{
context.Logger.LogError("The token request was rejected because the 'scope' parameter was not allowed.");
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.cs
index 0f456114..95f41642 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.cs
@@ -3855,10 +3855,11 @@ namespace OpenIddict.Server
// If the granted access token scopes differ from the requested scopes, return the granted scopes
// list as a parameter to inform the client application of the fact the scopes set will be reduced.
+ var scopes = new HashSet(context.AccessTokenPrincipal.GetScopes(), StringComparer.Ordinal);
if ((context.EndpointType == OpenIddictServerEndpointType.Token && context.Request.IsAuthorizationCodeGrantType()) ||
- !context.AccessTokenPrincipal.GetScopes().SetEquals(context.Request.GetScopes()))
+ !scopes.SetEquals(context.Request.GetScopes()))
{
- context.Response.Scope = string.Join(" ", context.AccessTokenPrincipal.GetScopes());
+ context.Response.Scope = string.Join(" ", scopes);
}
return default;
diff --git a/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs b/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs
index bf9595f5..db53b44f 100644
--- a/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs
+++ b/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs
@@ -9,7 +9,6 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.IO;
-using System.Linq;
using System.Security.Claims;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
@@ -172,8 +171,9 @@ namespace OpenIddict.Validation.DataProtection
static string GetProperty(IReadOnlyDictionary properties, string name)
=> properties.TryGetValue(name, out var value) ? value : null;
- static IEnumerable GetArrayProperty(IReadOnlyDictionary properties, string name)
- => properties.TryGetValue(name, out var value) ? JArray.Parse(value).Values() : Enumerable.Empty();
+ static ImmutableArray GetArrayProperty(IReadOnlyDictionary properties, string name)
+ => properties.TryGetValue(name, out var value) ?
+ JArray.Parse(value).Values().ToImmutableArray() : ImmutableArray.Create();
static DateTimeOffset? GetDateProperty(IReadOnlyDictionary properties, string name)
=> properties.TryGetValue(name, out var value) ? (DateTimeOffset?)
diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
index a6f851bb..f145ed1e 100644
--- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
+++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
@@ -409,7 +409,8 @@ namespace OpenIddict.Validation
}
// If the access token doesn't have any audience attached, return an error.
- if (!context.Principal.HasAudience())
+ var audiences = context.Principal.GetAudiences();
+ if (audiences.IsDefaultOrEmpty)
{
context.Logger.LogError("The request was rejected because the access token had no audience attached.");
@@ -421,7 +422,7 @@ namespace OpenIddict.Validation
}
// If the access token doesn't include any registered audience, return an error.
- if (context.Principal.GetAudiences().Intersect(context.Options.Audiences).IsEmpty)
+ if (!audiences.Intersect(context.Options.Audiences, StringComparer.Ordinal).Any())
{
context.Logger.LogError("The request was rejected because the access token had no valid audience.");
diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs
index 11543477..eaf52914 100644
--- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs
+++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs
@@ -42,15 +42,8 @@ namespace OpenIddict.Abstractions.Tests.Primitives
AcrValues = value
};
- // Act
- var actualValues = request.GetAcrValues();
-
- // Assert
- Assert.Equal(values.Length, actualValues.Count);
- foreach (var val in actualValues)
- {
- Assert.Contains(val, values);
- }
+ // Act and assert
+ Assert.Equal(values, request.GetAcrValues());
}
[Fact]
@@ -77,7 +70,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[InlineData(" code id_token", new[] { "code", "id_token" })]
[InlineData("code code id_token", new[] { "code", "id_token" })]
[InlineData("code CODE id_token", new[] { "code", "CODE", "id_token" })]
- public void GetResponseTypes_ReturnsExpectedResponseTypes(string value, string[] responseTypes)
+ public void GetResponseTypes_ReturnsExpectedResponseTypes(string value, string[] values)
{
// Arrange
var request = new OpenIddictRequest
@@ -85,15 +78,8 @@ namespace OpenIddict.Abstractions.Tests.Primitives
ResponseType = value
};
- // Act
- var actualResponseTypes = request.GetResponseTypes();
-
- // Assert
- Assert.Equal(responseTypes.Length, actualResponseTypes.Count);
- foreach (var rt in actualResponseTypes)
- {
- Assert.Contains(rt, responseTypes);
- }
+ // Act and assert
+ Assert.Equal(values, request.GetResponseTypes());
}
[Fact]
@@ -127,15 +113,8 @@ namespace OpenIddict.Abstractions.Tests.Primitives
Scope = scope
};
- // Act
- var actualScopes = request.GetScopes();
-
- // Assert
- Assert.Equal(scopes.Length, actualScopes.Count);
- foreach (var scp in actualScopes)
- {
- Assert.Contains(scp, scopes);
- }
+ // Act and assert
+ Assert.Equal(scopes, request.GetScopes());
}
[Fact]