Browse Source

React to nullable annotations changes in .NET 5.0 and update OpenIddictParameter.ToString() to use the invariant culture

pull/1170/head
Kévin Chalet 6 years ago
parent
commit
b19fdffea4
  1. 2
      shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs
  2. 9
      src/OpenIddict.Abstractions/OpenIddictResources.resx
  3. 16
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  4. 11
      src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
  5. 40
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  6. 8
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  7. 24
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs
  8. 40
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs
  9. 8
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  10. 24
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs
  11. 2
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs
  12. 10
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs
  13. 2
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs
  14. 8
      src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
  15. 9
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  16. 8
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  17. 7
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  18. 5
      src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
  19. 71
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  20. 2
      src/OpenIddict.Server/OpenIddictServerOptions.cs
  21. 3
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs
  22. 8
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs
  23. 2
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs
  24. 34
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs
  25. 2
      src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
  26. 10
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs
  27. 8
      src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
  28. 4
      src/OpenIddict.Validation/OpenIddictValidationService.cs
  29. 38
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs
  30. 2
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs
  31. 20
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs
  32. 21
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs
  33. 6
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs

2
shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs

@ -16,7 +16,7 @@ namespace OpenIddict.Extensions
/// <param name="type">The type to introspect.</param>
/// <param name="definition">The generic type definition.</param>
/// <returns>A <see cref="Type"/> instance if the base type was found, <c>null</c> otherwise.</returns>
public static Type FindGenericBaseType(Type type, Type definition)
public static Type? FindGenericBaseType(Type type, Type definition)
=> FindGenericBaseTypes(type, definition).FirstOrDefault();
/// <summary>

9
src/OpenIddict.Abstractions/OpenIddictResources.resx

@ -152,7 +152,7 @@ When implementing custom token deserialization, a 'oi_tkn_typ' claim containing
<value>A sign-in response cannot be returned from this endpoint.</value>
</data>
<data name="ID0011" xml:space="preserve">
<value>The specified principal doesn't contain any claims-based identity.
<value>The specified principal is null or doesn't contain a claims-based identity.
Make sure that 'ClaimsPrincipal.Identity' is not null.</value>
</data>
<data name="ID0012" xml:space="preserve">
@ -184,7 +184,7 @@ Alternatively, you can disable the built-in database-based server features by en
<value>An unknown error occurred while creating a token entry.</value>
</data>
<data name="ID0020" xml:space="preserve">
<value>A token entry cannot be created from a null principal.</value>
<value>A token entry cannot be created from a null principal or from a principal containing a null or invalid identity.</value>
</data>
<data name="ID0021" xml:space="preserve">
<value>The token entry cannot be found in the database.</value>
@ -1113,6 +1113,9 @@ To register the OpenIddict core services, reference the 'OpenIddict.Core' packag
<data name="ID0285" xml:space="preserve">
<value>Endpoint addresses must be unique across endpoints.</value>
</data>
<data name="ID0286" xml:space="preserve">
<value>The specified principal doesn't contain a valid claims-based identity.</value>
</data>
<data name="ID2000" xml:space="preserve">
<value>The security token is missing.</value>
</data>
@ -1483,7 +1486,7 @@ To register the OpenIddict core services, reference the 'OpenIddict.Core' packag
<value>ECDsa.ExportParameters() shouldn't return an unnamed curve.</value>
</data>
<data name="ID4006" xml:space="preserve">
<value>The principal shouldn't be null at this point.</value>
<value>The principal and its attached identity shouldn't be null at this point.</value>
</data>
<data name="ID4007" xml:space="preserve">
<value>The response shouldn't be null at this point.</value>

16
src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs

@ -525,7 +525,7 @@ namespace OpenIddict.Abstractions
foreach (var element in document.RootElement.EnumerateArray())
{
var value = element.GetString();
if (builder.Contains(value, StringComparer.OrdinalIgnoreCase))
if (string.IsNullOrEmpty(value) || builder.Contains(value, StringComparer.OrdinalIgnoreCase))
{
continue;
}
@ -1061,6 +1061,11 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
if (principal.Identity is not ClaimsIdentity identity)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0286), nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -1070,7 +1075,7 @@ namespace OpenIddict.Abstractions
if (!string.IsNullOrEmpty(value))
{
((ClaimsIdentity) principal.Identity).AddClaim(type, value);
identity.AddClaim(type, value);
}
return principal;
@ -1119,6 +1124,11 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
if (principal.Identity is not ClaimsIdentity identity)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0286), nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -1128,7 +1138,7 @@ namespace OpenIddict.Abstractions
foreach (var value in values.Distinct(StringComparer.Ordinal))
{
((ClaimsIdentity) principal.Identity).AddClaim(type, value);
identity.AddClaim(type, value);
}
return principal;

11
src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs

@ -258,7 +258,7 @@ namespace OpenIddict.Abstractions
return value.GetInt64().GetHashCode();
case JsonValueKind.String:
return value.GetString().GetHashCode();
return value.GetString()!.GetHashCode();
case JsonValueKind.Array:
{
@ -420,12 +420,15 @@ namespace OpenIddict.Abstractions
{
null => string.Empty,
string value => value,
bool value => value ? bool.TrueString : bool.FalseString,
long value => value.ToString(CultureInfo.InvariantCulture),
string value => value,
string?[] value => string.Join(", ", value),
JsonElement value => value.ToString(),
var value => value.ToString()
_ => throw new InvalidOperationException(SR.GetResourceString(SR.ID0194))
};
/// <summary>
@ -799,7 +802,7 @@ namespace OpenIddict.Abstractions
static string?[]? CreateArray(JsonElement value)
{
var array = new string[value.GetArrayLength()];
var array = new string?[value.GetArrayLength()];
using var enumerator = value.EnumerateArray();
for (var index = 0; enumerator.MoveNext(); index++)

40
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs

@ -404,7 +404,13 @@ namespace OpenIddict.EntityFramework
foreach (var property in document.RootElement.EnumerateObject())
{
builder[CultureInfo.GetCultureInfo(property.Name)] = property.Value.GetString();
var value = property.Value.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder[CultureInfo.GetCultureInfo(property.Name)] = value;
}
return builder.ToImmutable();
@ -450,7 +456,13 @@ namespace OpenIddict.EntityFramework
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();
@ -485,7 +497,13 @@ namespace OpenIddict.EntityFramework
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();
@ -555,7 +573,13 @@ namespace OpenIddict.EntityFramework
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();
@ -590,7 +614,13 @@ namespace OpenIddict.EntityFramework
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();

8
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs

@ -500,7 +500,13 @@ namespace OpenIddict.EntityFramework
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();

24
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs

@ -265,7 +265,13 @@ namespace OpenIddict.EntityFramework
foreach (var property in document.RootElement.EnumerateObject())
{
builder[CultureInfo.GetCultureInfo(property.Name)] = property.Value.GetString();
var value = property.Value.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder[CultureInfo.GetCultureInfo(property.Name)] = value;
}
return builder.ToImmutable();
@ -311,7 +317,13 @@ namespace OpenIddict.EntityFramework
foreach (var property in document.RootElement.EnumerateObject())
{
builder[CultureInfo.GetCultureInfo(property.Name)] = property.Value.GetString();
var value = property.Value.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder[CultureInfo.GetCultureInfo(property.Name)] = value;
}
return builder.ToImmutable();
@ -403,7 +415,13 @@ namespace OpenIddict.EntityFramework
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();

40
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs

@ -448,7 +448,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var property in document.RootElement.EnumerateObject())
{
builder[CultureInfo.GetCultureInfo(property.Name)] = property.Value.GetString();
var value = property.Value.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder[CultureInfo.GetCultureInfo(property.Name)] = value;
}
return builder.ToImmutable();
@ -494,7 +500,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();
@ -529,7 +541,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();
@ -599,7 +617,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();
@ -634,7 +658,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();

8
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs

@ -568,7 +568,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();

24
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs

@ -281,7 +281,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var property in document.RootElement.EnumerateObject())
{
builder[CultureInfo.GetCultureInfo(property.Name)] = property.Value.GetString();
var value = property.Value.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder[CultureInfo.GetCultureInfo(property.Name)] = value;
}
return builder.ToImmutable();
@ -327,7 +333,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var property in document.RootElement.EnumerateObject())
{
builder[CultureInfo.GetCultureInfo(property.Name)] = property.Value.GetString();
var value = property.Value.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder[CultureInfo.GetCultureInfo(property.Name)] = value;
}
return builder.ToImmutable();
@ -419,7 +431,13 @@ namespace OpenIddict.EntityFrameworkCore
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var value = element.GetString();
if (string.IsNullOrEmpty(value))
{
continue;
}
builder.Add(value);
}
return builder.ToImmutable();

2
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs

@ -155,7 +155,7 @@ namespace OpenIddict.Server.AspNetCore
else
{
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.Principal.GetTokenType()), SR.GetResourceString(SR.ID4009));
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID4010));

10
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs

@ -189,7 +189,13 @@ namespace OpenIddict.Server.DataProtection
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var item = element.GetString();
if (string.IsNullOrEmpty(item))
{
continue;
}
builder.Add(item);
}
return builder.ToImmutable();
@ -264,7 +270,7 @@ namespace OpenIddict.Server.DataProtection
Claims.Private.TokenId or
Claims.Private.UserCodeLifetime));
Write(writer, principal.Identity.AuthenticationType, principal, properties);
Write(writer, principal.Identity?.AuthenticationType, principal, properties);
writer.Flush();
// Note: the following local methods closely matches the logic used by ASP.NET Core's

2
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs

@ -167,7 +167,7 @@ namespace OpenIddict.Server.Owin
else
{
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.Principal.GetTokenType()), SR.GetResourceString(SR.ID4009));
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID4010));

8
src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs

@ -371,7 +371,7 @@ namespace OpenIddict.Server
return default;
static Uri? GetEndpointAbsoluteUri(Uri? issuer, Uri endpoint)
static Uri? GetEndpointAbsoluteUri(Uri? issuer, Uri? endpoint)
{
// If the endpoint is disabled (i.e a null address is specified), return null.
if (endpoint is null)
@ -1248,8 +1248,8 @@ namespace OpenIddict.Server
// Warning: on .NET Framework 4.x and .NET Core 2.1, exported ECParameters generally have
// a null OID value attached. To work around this limitation, both the friendly names and
// the raw OID value are compared to determine whether the curve is of the specified type.
string.Equals(parameters.Curve.Oid.Value, curve.Oid.Value, StringComparison.Ordinal) ||
string.Equals(parameters.Curve.Oid.FriendlyName, curve.Oid.FriendlyName, StringComparison.Ordinal);
string.Equals(parameters.Curve.Oid?.Value, curve.Oid?.Value, StringComparison.Ordinal) ||
string.Equals(parameters.Curve.Oid?.FriendlyName, curve.Oid?.FriendlyName, StringComparison.Ordinal);
#endif
static byte[] GetCertificateHash(X509Certificate2 certificate, HashAlgorithmName algorithm)
@ -1257,7 +1257,7 @@ namespace OpenIddict.Server
#if SUPPORTS_CERTIFICATE_HASHING_WITH_SPECIFIED_ALGORITHM
return certificate.GetCertHash(algorithm);
#else
using var hash = CryptoConfig.CreateFromName(algorithm.Name) as HashAlgorithm;
using var hash = CryptoConfig.CreateFromName(algorithm.Name!) as HashAlgorithm;
if (hash is null || hash is KeyedHashAlgorithm)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0217));

9
src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs

@ -8,6 +8,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
@ -1331,7 +1332,7 @@ namespace OpenIddict.Server
return default;
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var presenters = context.Principal.GetPresenters();
if (presenters.IsDefaultOrEmpty)
@ -1415,7 +1416,7 @@ namespace OpenIddict.Server
return default;
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Validate the redirect_uri sent by the client application as part of this token request.
// Note: for pure OAuth 2.0 requests, redirect_uri is only mandatory if the authorization request
@ -1484,7 +1485,7 @@ namespace OpenIddict.Server
return default;
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: the ValidateProofKeyForCodeExchangeRequirement handler (invoked earlier) ensures
// a code_verifier is specified if the proof key for code exchange requirement was enforced
@ -1605,7 +1606,7 @@ namespace OpenIddict.Server
return default;
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// When an explicit scope parameter has been included in the token request
// but was missing from the initial request, the request MUST be rejected.

8
src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs

@ -742,7 +742,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken) &&
!context.Principal.HasTokenType(TokenTypeHints.RefreshToken))
@ -789,7 +789,7 @@ namespace OpenIddict.Server
}
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId));
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// When the introspected token is an access token, the caller must be listed either as a presenter
// (i.e the party the token was issued to) or as an audience (i.e a resource server/API).
@ -885,7 +885,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
context.TokenId = context.Principal.GetClaim(Claims.JwtId);
context.TokenUsage = context.Principal.GetTokenType();
@ -945,7 +945,7 @@ namespace OpenIddict.Server
}
Debug.Assert(!string.IsNullOrEmpty(context.Request.ClientId), SR.FormatID4000(Parameters.ClientId));
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Don't return application-specific claims if the token is not an access token.
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken))

7
src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs

@ -7,6 +7,7 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OpenIddict.Abstractions;
@ -684,7 +685,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken) &&
!context.Principal.HasTokenType(TokenTypeHints.RefreshToken))
@ -731,7 +732,7 @@ namespace OpenIddict.Server
}
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId));
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// When the revoked token is an access token, the caller must be listed either as a presenter
// (i.e the party the token was issued to) or as an audience (i.e a resource server/API).
@ -836,7 +837,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Extract the token identifier from the authentication principal.
var identifier = context.Principal.GetTokenId();

5
src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs

@ -8,6 +8,7 @@ using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OpenIddict.Abstractions;
@ -461,7 +462,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: when receiving an access token, its audiences list cannot be used for the "aud" claim
// as the client application is not the intented audience but only an authorized presenter.
@ -495,7 +496,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
context.Subject = context.Principal.GetClaim(Claims.Subject);

71
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -823,7 +823,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Extract the token identifier from the authentication principal.
// If no token identifier can be found, this indicates that the token
@ -1030,7 +1030,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var identifier = context.Principal.GetAuthorizationId();
if (string.IsNullOrEmpty(identifier))
@ -1089,7 +1089,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Don't validate the lifetime of id_tokens used as id_token_hints.
if (context.EndpointType is OpenIddictServerEndpointType.Authorization or OpenIddictServerEndpointType.Logout)
@ -1355,8 +1355,6 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
if (context.EndpointType is not (OpenIddictServerEndpointType.Authorization or
OpenIddictServerEndpointType.Device or
OpenIddictServerEndpointType.Token or
@ -1365,7 +1363,7 @@ namespace OpenIddict.Server
throw new InvalidOperationException(SR.GetResourceString(SR.ID0010));
}
if (context.Principal.Identity is null)
if (context.Principal is not { Identity: ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0011));
}
@ -1384,18 +1382,19 @@ namespace OpenIddict.Server
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0013));
}
return default;
}
if (!context.Principal.Identity.IsAuthenticated)
else
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0014));
}
if (!context.Principal.Identity.IsAuthenticated)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0014));
}
if (string.IsNullOrEmpty(context.Principal.GetClaim(Claims.Subject)))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0015));
if (string.IsNullOrEmpty(context.Principal.GetClaim(Claims.Subject)))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0015));
}
}
return default;
@ -1425,7 +1424,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
switch (context.EndpointType)
{
@ -1497,7 +1496,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Always include the "openid" scope when the developer doesn't explicitly call SetScopes.
// Note: the application is allowed to specify a different "scopes": in this case,
@ -1534,7 +1533,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Add the validated client_id to the list of authorized presenters,
// unless the presenters were explicitly set by the developer.
@ -1570,7 +1569,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// When a "resources" property cannot be found in the ticket, infer it from the "audiences" property.
if (context.Principal.HasAudience() && !context.Principal.HasResource())
@ -1609,7 +1608,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
(context.GenerateAccessToken, context.IncludeAccessToken) = context.EndpointType switch
{
@ -1723,7 +1722,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// If no authorization code, device code or refresh token is returned, don't create an authorization.
if (!context.GenerateAuthorizationCode && !context.GenerateDeviceCode && !context.GenerateRefreshToken)
@ -1809,7 +1808,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Create a new principal containing only the filtered claims.
// Actors identities are also filtered (delegation scenarios).
@ -1927,7 +1926,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Create a new principal containing only the filtered claims.
// Actors identities are also filtered (delegation scenarios).
@ -2012,7 +2011,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: a device code principal is produced when a device code is included in the response or when a
// device code entry is replaced when processing a sign-in response sent to the verification endpoint.
@ -2092,7 +2091,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Create a new principal containing only the filtered claims.
// Actors identities are also filtered (delegation scenarios).
@ -2176,7 +2175,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Replace the principal by a new one containing only the filtered claims.
// Actors identities are also filtered (delegation scenarios).
@ -2289,7 +2288,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Create a new principal containing only the filtered claims.
// Actors identities are also filtered (delegation scenarios).
@ -2379,7 +2378,7 @@ namespace OpenIddict.Server
default: return;
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Extract the token identifier from the authentication principal.
// If no token identifier can be found, this indicates that the token has no backing database entry.
@ -2526,7 +2525,7 @@ namespace OpenIddict.Server
Claims.Private.Scope or
Claims.Private.TokenType));
if (principal is null)
if (principal is null or { Identity: not ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0020));
}
@ -2785,7 +2784,7 @@ namespace OpenIddict.Server
Claims.Private.ExpirationDate or
Claims.Private.TokenType));
if (principal is null)
if (principal is null or { Identity: not ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0022));
}
@ -3031,7 +3030,7 @@ namespace OpenIddict.Server
Claims.Private.ExpirationDate or
Claims.Private.TokenType));
if (principal is null)
if (principal is null or { Identity: not ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0022));
}
@ -3197,7 +3196,7 @@ namespace OpenIddict.Server
return;
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var principal = context.DeviceCodePrincipal;
if (principal is null)
@ -3361,7 +3360,7 @@ namespace OpenIddict.Server
Claims.Private.ExpirationDate or
Claims.Private.TokenType));
if (principal is null)
if (principal is null or { Identity: not ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0022));
}
@ -3644,7 +3643,7 @@ namespace OpenIddict.Server
Claims.Private.ExpirationDate or
Claims.Private.TokenType));
if (principal is null)
if (principal is null or { Identity: not ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0022));
}
@ -3900,7 +3899,7 @@ namespace OpenIddict.Server
}
};
hash = CryptoConfig.CreateFromName(algorithm.Name) as HashAlgorithm;
hash = CryptoConfig.CreateFromName(algorithm.Name!) as HashAlgorithm;
}
return hash;
@ -4034,7 +4033,7 @@ namespace OpenIddict.Server
Claims.Private.ExpirationDate or
Claims.Private.TokenType));
if (principal is null)
if (principal is null or { Identity: not ClaimsIdentity })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0022));
}
@ -4227,7 +4226,7 @@ namespace OpenIddict.Server
return default;
static Uri? GetEndpointAbsoluteUri(Uri? issuer, Uri endpoint)
static Uri? GetEndpointAbsoluteUri(Uri? issuer, Uri? endpoint)
{
// If the endpoint is disabled (i.e a null address is specified), return null.
if (endpoint is null)

2
src/OpenIddict.Server/OpenIddictServerOptions.cs

@ -80,7 +80,7 @@ namespace OpenIddict.Server
/// <summary>
/// Gets the absolute and relative URIs associated to the cryptography endpoint.
/// </summary>
public List<Uri> CryptographyEndpointUris { get; } = new List<Uri>
public List<Uri> CryptographyEndpointUris { get; } = new()
{
new Uri("/.well-known/jwks", UriKind.Relative)
};

3
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs

@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
@ -152,7 +153,7 @@ namespace OpenIddict.Validation.AspNetCore
else
{
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.Principal.GetTokenType()), SR.GetResourceString(SR.ID4009));
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID4010));

8
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs

@ -186,7 +186,13 @@ namespace OpenIddict.Validation.DataProtection
foreach (var element in document.RootElement.EnumerateArray())
{
builder.Add(element.GetString());
var item = element.GetString();
if (string.IsNullOrEmpty(item))
{
continue;
}
builder.Add(item);
}
return builder.ToImmutable();

2
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs

@ -164,7 +164,7 @@ namespace OpenIddict.Validation.Owin
else
{
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.Principal.GetTokenType()), SR.GetResourceString(SR.ID4009));
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID4010));

34
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs

@ -123,6 +123,7 @@ namespace OpenIddict.Validation.SystemNetHttp
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
@ -133,22 +134,25 @@ namespace OpenIddict.Validation.SystemNetHttp
throw new InvalidOperationException(SR.GetResourceString(SR.ID0173));
}
// Note: System.Net.Http doesn't expose convenient methods allowing to create
// query strings from existing key/value pairs. To work around this limitation,
// a FormUrlEncodedContent is instantiated and used to manually create the URL.
using var content = new FormUrlEncodedContent(
from parameter in context.Transaction.Request.GetParameters()
let values = (string[]?) parameter.Value
where values is not null
from value in values
select new KeyValuePair<string, string>(parameter.Key, value));
var builder = new UriBuilder(request.RequestUri)
if (request.RequestUri is not null)
{
Query = await content.ReadAsStringAsync()
};
request.RequestUri = builder.Uri;
// Note: System.Net.Http doesn't expose convenient methods allowing to create
// query strings from existing key/value pairs. To work around this limitation,
// a FormUrlEncodedContent is instantiated and used to manually create the URL.
using var content = new FormUrlEncodedContent(
from parameter in context.Transaction.Request.GetParameters()
let values = (string[]?) parameter.Value
where values is not null
from value in values
select new KeyValuePair<string, string>(parameter.Key, value));
var builder = new UriBuilder(request.RequestUri)
{
Query = await content.ReadAsStringAsync()
};
request.RequestUri = builder.Uri;
}
}
}

2
src/OpenIddict.Validation/OpenIddictValidationBuilder.cs

@ -330,7 +330,7 @@ namespace Microsoft.Extensions.DependencyInjection
return AddEncryptionCertificate(certificate);
static X509Certificate2 GetCertificate(StoreLocation location, string thumbprint)
static X509Certificate2? GetCertificate(StoreLocation location, string thumbprint)
{
using var store = new X509Store(StoreName.My, location);
store.Open(OpenFlags.ReadOnly);

10
src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs

@ -384,13 +384,19 @@ namespace OpenIddict.Validation
case JsonElement { ValueKind: JsonValueKind.Array } value:
foreach (var element in value.EnumerateArray())
{
identity.AddClaim(new Claim(parameter.Key, element.ToString(),
var item = element.GetString();
if (string.IsNullOrEmpty(item))
{
continue;
}
identity.AddClaim(new Claim(parameter.Key, item,
GetClaimValueType(value.ValueKind), issuer, issuer, identity));
}
break;
case JsonElement value:
identity.AddClaim(new Claim(parameter.Key, value.ToString(),
identity.AddClaim(new Claim(parameter.Key, value.ToString()!,
GetClaimValueType(value.ValueKind), issuer, issuer, identity));
break;

8
src/OpenIddict.Validation/OpenIddictValidationHandlers.cs

@ -641,7 +641,7 @@ namespace OpenIddict.Validation
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var date = context.Principal.GetExpirationDate();
if (date.HasValue && date.Value < DateTimeOffset.UtcNow)
@ -683,7 +683,7 @@ namespace OpenIddict.Validation
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// If no explicit audience has been configured,
// skip the default audience validation.
@ -755,7 +755,7 @@ namespace OpenIddict.Validation
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var identifier = context.Principal.GetTokenId();
if (string.IsNullOrEmpty(identifier))
@ -818,7 +818,7 @@ namespace OpenIddict.Validation
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var identifier = context.Principal.GetAuthorizationId();
if (string.IsNullOrEmpty(identifier))

4
src/OpenIddict.Validation/OpenIddictValidationService.cs

@ -458,7 +458,7 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri);
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
return context.Principal;
}
@ -521,7 +521,7 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri);
}
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
return context.Principal;
}

38
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs

@ -1169,9 +1169,9 @@ namespace OpenIddict.Abstractions.Tests.Primitives
principal.SetDestinations(destinations.ToImmutable());
// Assert
Assert.Equal(@"[""access_token"",""id_token""]", principal.FindFirst(Claims.Name).Properties[Properties.Destinations]);
Assert.Equal(@"[""id_token""]", principal.FindFirst(Claims.Email).Properties[Properties.Destinations]);
Assert.DoesNotContain(Properties.Destinations, principal.FindFirst(Claims.Nonce).Properties);
Assert.Equal(@"[""access_token"",""id_token""]", principal.FindFirst(Claims.Name)!.Properties[Properties.Destinations]);
Assert.Equal(@"[""id_token""]", principal.FindFirst(Claims.Email)!.Properties[Properties.Destinations]);
Assert.DoesNotContain(Properties.Destinations, principal.FindFirst(Claims.Nonce)!.Properties);
}
[Theory]
@ -1241,7 +1241,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
// Assert
Assert.Single(clone.Claims);
Assert.Null(clone.FindFirst(Claims.Subject));
Assert.Equal("Bob le Bricoleur", clone.FindFirst(Claims.Name).Value);
Assert.Equal("Bob le Bricoleur", clone.FindFirst(Claims.Name)!.Value);
}
[Fact]
@ -1259,9 +1259,9 @@ namespace OpenIddict.Abstractions.Tests.Primitives
var clone = identity.Clone(claim => claim.Type == Claims.Name);
// Assert
Assert.Single(clone.Actor.Claims);
Assert.Single(clone.Actor!.Claims);
Assert.Null(clone.Actor.FindFirst(Claims.Subject));
Assert.Equal("Bob le Bricoleur", clone.Actor.FindFirst(Claims.Name).Value);
Assert.Equal("Bob le Bricoleur", clone.Actor.FindFirst(Claims.Name)!.Value);
}
[Fact]
@ -1280,7 +1280,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
// Assert
Assert.Single(clone.Claims);
Assert.Null(clone.FindFirst(Claims.Subject));
Assert.Equal("Bob le Bricoleur", clone.FindFirst(Claims.Name).Value);
Assert.Equal("Bob le Bricoleur", clone.FindFirst(Claims.Name)!.Value);
}
[Fact]
@ -1308,7 +1308,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
identity.AddClaim(Claims.Name, "Bob le Bricoleur");
// Assert
Assert.Equal("Bob le Bricoleur", identity.FindFirst(Claims.Name).Value);
Assert.Equal("Bob le Bricoleur", identity.FindFirst(Claims.Name)!.Value);
}
[Theory]
@ -1324,7 +1324,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
// Act
identity.AddClaim(Claims.Name, "Bob le Bricoleur", ImmutableArray.Create(destinations));
var claim = identity.FindFirst(Claims.Name);
var claim = identity.FindFirst(Claims.Name)!;
// Assert
Assert.Equal("Bob le Bricoleur", claim.Value);
@ -1344,7 +1344,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
// Act
identity.AddClaim(Claims.Name, "Bob le Bricoleur", destinations);
var claim = identity.FindFirst(Claims.Name);
var claim = identity.FindFirst(Claims.Name)!;
// Assert
Assert.Equal("Bob le Bricoleur", claim.Value);
@ -2422,13 +2422,27 @@ namespace OpenIddict.Abstractions.Tests.Primitives
Assert.Equal("principal", exception.ParamName);
}
[Fact]
public void SetClaim_ThrowsAnExceptionForNullIdentity()
{
// Arrange
var principal = new ClaimsPrincipal();
// Act and assert
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", "value"));
Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message);
}
[Theory]
[InlineData(null)]
[InlineData("")]
public void SetClaim_ThrowsAnExceptionForNullOrEmptyProperty(string type)
public void SetClaim_ThrowsAnExceptionForNullOrEmptyType(string type)
{
// Arrange
var principal = new ClaimsPrincipal();
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
// Act and assert
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim(type, "value"));

2
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs

@ -446,7 +446,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
""logo_uri"": ""https://client.example.org/logo.png"",
""jwks_uri"": ""https://client.example.org/my_public_keys.jwks"",
""example_extension_parameter"": ""example_value""
}");
}")!;
var options = new JsonSerializerOptions
{

20
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs

@ -38,7 +38,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
}
[Fact]
public void Count_ReturnsZeroForInteger()
public void Count_ReturnsZeroForLongValue()
{
// Arrange
var parameter = new OpenIddictParameter(42);
@ -614,6 +614,24 @@ namespace OpenIddict.Abstractions.Tests.Primitives
Assert.Empty(parameter.ToString());
}
[Fact]
public void ToString_ReturnsBooleanValue()
{
// Arrange, act and assert
Assert.Equal(bool.TrueString, new OpenIddictParameter(true).ToString());
Assert.Equal(bool.FalseString, new OpenIddictParameter(false).ToString());
}
[Fact]
public void ToString_ReturnsLongValue()
{
// Arrange
var parameter = new OpenIddictParameter(42);
// Act and assert
Assert.Equal("42", parameter.ToString());
}
[Fact]
public void ToString_ReturnsStringValue()
{

21
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs

@ -256,14 +256,14 @@ namespace OpenIddict.Server.IntegrationTests
// Note: a dictionary is deliberately not used here to allow multiple parameters with the
// same name to be specified. While initially not allowed by the core OAuth2 specification,
// this is required for derived drafts like the OAuth2 token exchange specification.
var parameters = new List<KeyValuePair<string, string?>>();
var parameters = new List<KeyValuePair<string?, string?>>();
foreach (var parameter in request.GetParameters())
{
// If the parameter is null or empty, send an empty value.
if (OpenIddictParameter.IsNullOrEmpty(parameter.Value))
{
parameters.Add(new KeyValuePair<string, string?>(parameter.Key, string.Empty));
parameters.Add(new KeyValuePair<string?, string?>(parameter.Key, string.Empty));
continue;
}
@ -276,7 +276,7 @@ namespace OpenIddict.Server.IntegrationTests
foreach (var value in values)
{
parameters.Add(new KeyValuePair<string, string?>(parameter.Key, value));
parameters.Add(new KeyValuePair<string?, string?>(parameter.Key, value));
}
}
@ -286,19 +286,28 @@ namespace OpenIddict.Server.IntegrationTests
foreach (var parameter in parameters)
{
if (string.IsNullOrEmpty(parameter.Key))
{
continue;
}
if (builder.Length != 0)
{
builder.Append('&');
}
builder.Append(UrlEncoder.Default.Encode(parameter.Key));
builder.Append('=');
builder.Append(UrlEncoder.Default.Encode(parameter.Value));
if (!string.IsNullOrEmpty(parameter.Value))
{
builder.Append('=');
builder.Append(UrlEncoder.Default.Encode(parameter.Value));
}
}
if (!uri.IsAbsoluteUri)
{
uri = new Uri(HttpClient.BaseAddress, uri);
uri = new Uri(HttpClient.BaseAddress!, uri);
}
uri = new UriBuilder(uri) { Query = builder.ToString() }.Uri;

6
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs

@ -238,8 +238,7 @@ namespace OpenIddict.Server.IntegrationTests
var response = await client.GetAsync("/.well-known/openid-configuration");
// Assert
Assert.Equal(client.HttpClient.BaseAddress.AbsoluteUri,
(string?) response[Metadata.Issuer]);
Assert.Equal(client.HttpClient.BaseAddress!.AbsoluteUri, (string?) response[Metadata.Issuer]);
}
[Fact]
@ -257,8 +256,7 @@ namespace OpenIddict.Server.IntegrationTests
var response = await client.GetAsync("/.well-known/openid-configuration");
// Assert
Assert.Equal("https://www.fabrikam.com/",
(string?) response[Metadata.Issuer]);
Assert.Equal("https://www.fabrikam.com/", (string?) response[Metadata.Issuer]);
}
[Fact]

Loading…
Cancel
Save