diff --git a/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx b/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx
index 18e595bb..be9f64a8 100644
--- a/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx
+++ b/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx
@@ -2487,6 +2487,10 @@ This may indicate that the hashed entry is corrupted or malformed.
An exception occurred while trying to revoke the token '{Identifier}'.
{Locked}
+
+ A signing key of type '{Type}' was ignored because its EC curve couldn't be inferred.
+ {Locked}
+
Removes orphaned tokens and authorizations from the database.
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
index cd4eda92..f1b42567 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
@@ -1198,15 +1198,24 @@ namespace OpenIddict.Server
continue;
}
+ var curve = IsCurve(parameters.Value, ECCurve.NamedCurves.nistP256) ? JsonWebKeyECTypes.P256 :
+ IsCurve(parameters.Value, ECCurve.NamedCurves.nistP384) ? JsonWebKeyECTypes.P384 :
+ IsCurve(parameters.Value, ECCurve.NamedCurves.nistP521) ? JsonWebKeyECTypes.P521 : null;
+
+ if (string.IsNullOrEmpty(curve))
+ {
+ context.Logger.LogWarning(SR.GetResourceString(SR.ID6180), credentials.Key.GetType().Name);
+
+ continue;
+ }
+
Debug.Assert(parameters.Value.Q.X is not null &&
parameters.Value.Q.Y is not null, SR.GetResourceString(SR.ID4004));
Debug.Assert(parameters.Value.Curve.IsNamed, SR.GetResourceString(SR.ID4005));
key.Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve;
- key.Crv = IsCurve(parameters.Value, ECCurve.NamedCurves.nistP256) ? JsonWebKeyECTypes.P256 :
- IsCurve(parameters.Value, ECCurve.NamedCurves.nistP384) ? JsonWebKeyECTypes.P384 :
- IsCurve(parameters.Value, ECCurve.NamedCurves.nistP521) ? JsonWebKeyECTypes.P521 : null;
+ key.Crv = curve;
// Note: both X and Y must be base64url-encoded.
// See https://tools.ietf.org/html/rfc7518#section-6.2.1.2
@@ -1241,6 +1250,10 @@ namespace OpenIddict.Server
#if SUPPORTS_ECDSA
static bool IsCurve(ECParameters parameters, ECCurve curve) =>
+ // 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);
#endif
diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs
index 22a695a3..4c66b5ef 100644
--- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs
+++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs
@@ -1274,30 +1274,26 @@ namespace OpenIddict.Server.IntegrationTests
#if SUPPORTS_ECDSA
[Theory]
[InlineData(
- /* oid: */ "1.2.840.10045.3.1.7",
- /* curve: */ nameof(ECCurve.NamedCurves.nistP256),
+ /* oid: */ "1.2.840.10045.3.1.7", // P-256
/* d: */ "C0vacBwq1FnQ1N0FHXuuwTlw7Or0neOm2r3AdIKLDKI=",
/* x: */ "7eu+fVtuma+LVD4eH6CxrBX8366cnhPpvgeoeYL7oqw=",
/* y: */ "4qRkITJZ4p5alm0VpLPd+I11wq8vMUHUhbJm1Crx+Zs=")]
[InlineData(
- /* oid: */ "1.3.132.0.34",
- /* curve: */ nameof(ECCurve.NamedCurves.nistP384),
+ /* oid: */ "1.3.132.0.34", // P-384
/* d: */ "B2JSdvTbRD/T5Sv7QsGBHPX9yGo2zn3Et5OWrjNauQ2kl+jFkXg5Iy2Vfak7W0ZQ",
/* x: */ "qqsUwddWjXhCWiaUCOUORJIzvp6QDXv1vroHPR4N0C3UqSKkJ5hNiBHaYdRYCnvC",
/* y: */ "QpbQFKBOXgeAKQQub/9QWZPvzNEjXq7aJjHlw4hiY+9QhGPn4qHUaeeI0qlaJ/t2")]
[InlineData(
- /* oid: */ "1.3.132.0.35",
- /* curve: */ nameof(ECCurve.NamedCurves.nistP521),
+ /* oid: */ "1.3.132.0.35", // P-521
/* d: */ "ALong1stsWvTLufObn3SPfM8s9VsTG73nXv4mkzGFUmB1r7rda+cpYXU99rFV/kX6zBkFl7Y9TZ2ZyZLFnyUpE4j",
/* x: */ "AS+aCMpMbSO4ga/hUsVIIidqmcQiiT+N9o/5hJ9UVA/vHAKDvWTjuKz+JZfOiR9J+GDUcDZS56UbGG83IosMJMM6",
/* y: */ "AcYkfsb/kTKpcPhYsRPAYV7ibwTN/CdiAM8QuCElAV6wBGfuX1LUmK6ldDVJjytpSz1EmGvzR0T7UCcZcgITqWc2")]
- public async Task HandleCryptographyRequest_EcdsaSecurityKeysAreCorrectlyExposed(
- string oid, string curve, string d, string x, string y)
+ public async Task HandleCryptographyRequest_EcdsaSecurityKeysAreCorrectlyExposed(string oid, string d, string x, string y)
{
// Arrange
var parameters = new ECParameters
{
- Curve = ECCurve.CreateFromOid(new Oid(oid, curve)),
+ Curve = ECCurve.CreateFromValue(oid),
D = Convert.FromBase64String(d),
Q = new ECPoint
{