From 6be2b4f65eaf37b17aef756a6553389159ee8ed7 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 21 May 2015 13:08:35 -0400 Subject: [PATCH] added ES* and PS* support for signed objects --- ...DefaultJWTSigningAndValidationService.java | 14 ++++++--- .../webapp/resources/template/client.html | 30 +++++++++++++------ .../discovery/web/DiscoveryEndpoint.java | 11 +++++-- .../JWTBearerAuthenticationProvider.java | 10 ++++++- .../request/ConnectOAuth2RequestFactory.java | 12 ++++++-- .../openid/connect/util/IdTokenHashUtils.java | 6 ++-- 6 files changed, 61 insertions(+), 22 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java index 153b175a8..b4f18df01 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java @@ -35,6 +35,8 @@ import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSSigner; import com.nimbusds.jose.JWSVerifier; +import com.nimbusds.jose.crypto.ECDSASigner; +import com.nimbusds.jose.crypto.ECDSAVerifier; import com.nimbusds.jose.crypto.MACSigner; import com.nimbusds.jose.crypto.MACVerifier; import com.nimbusds.jose.crypto.RSASSASigner; @@ -100,7 +102,6 @@ public class DefaultJWTSigningAndValidationService implements JWTSigningAndValid for (JWK key : keyStore.getKeys()) { if (!Strings.isNullOrEmpty(key.getKeyID())) { // use the key ID that's built into the key itself - // TODO (#641): deal with JWK thumbprints this.keys.put(key.getKeyID(), key); } else { // create a random key id @@ -173,9 +174,14 @@ public class DefaultJWTSigningAndValidationService implements JWTSigningAndValid } else if (jwk instanceof ECKey) { // build EC signers & verifiers - // TODO: add support for EC keys - logger.warn("EC Keys are not yet supported."); - + if (jwk.isPrivate()) { + ECDSASigner signer = new ECDSASigner(((ECKey) jwk).getD().decodeToBigInteger()); + signers.put(id, signer); + } + + ECDSAVerifier verifier = new ECDSAVerifier(((ECKey) jwk).getX().decodeToBigInteger(), ((ECKey) jwk).getY().decodeToBigInteger()); + verifiers.put(id, verifier); + } else if (jwk instanceof OctetSequenceKey) { // build HMAC signers & verifiers diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index bc4acc2be..10f1de08e 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -479,15 +479,18 @@
@@ -584,6 +587,9 @@ + + + @@ -603,6 +609,9 @@ + + + @@ -654,6 +663,9 @@ + + + diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java index 9ca0282dd..3170cd9ba 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java @@ -288,8 +288,15 @@ public class DiscoveryEndpoint { Collection serverSigningAlgs = signService.getAllSigningAlgsSupported(); Collection clientSymmetricSigningAlgs = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512); - Collection clientSymmetricAndAsymmetricSigningAlgs = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512); - Collection clientSymmetricAndAsymmetricSigningAlgsWithNone = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, Algorithm.NONE); + Collection clientSymmetricAndAsymmetricSigningAlgs = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, + JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, + JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, + JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512); + Collection clientSymmetricAndAsymmetricSigningAlgsWithNone = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, + JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, + JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, + JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512, + Algorithm.NONE); ArrayList grantTypes = Lists.newArrayList("authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "client_credentials", "urn:ietf:params:oauth:grant_type:redelegate"); Map m = new HashMap(); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java index e522baea3..8e453b6de 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java @@ -117,8 +117,16 @@ public class JWTBearerAuthenticationProvider implements AuthenticationProvider { } else if (client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY) && (alg.equals(JWSAlgorithm.RS256) || alg.equals(JWSAlgorithm.RS384) - || alg.equals(JWSAlgorithm.RS512))) { + || alg.equals(JWSAlgorithm.RS512) + || alg.equals(JWSAlgorithm.ES256) + || alg.equals(JWSAlgorithm.ES384) + || alg.equals(JWSAlgorithm.ES512) + || alg.equals(JWSAlgorithm.PS256) + || alg.equals(JWSAlgorithm.PS384) + || alg.equals(JWSAlgorithm.PS512))) { + // it's a known public/private key algorithm + JWTSigningAndValidationService validator = validators.getValidator(client.getJwksUri()); if (validator == null) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java index 06d860c59..7f630e583 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java @@ -205,12 +205,18 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory { if (alg.equals(JWSAlgorithm.RS256) || alg.equals(JWSAlgorithm.RS384) - || alg.equals(JWSAlgorithm.RS512)) { + || alg.equals(JWSAlgorithm.RS512) + || alg.equals(JWSAlgorithm.ES256) + || alg.equals(JWSAlgorithm.ES384) + || alg.equals(JWSAlgorithm.ES512) + || alg.equals(JWSAlgorithm.PS256) + || alg.equals(JWSAlgorithm.PS384) + || alg.equals(JWSAlgorithm.PS512)) { - // it's RSA, need to find the JWK URI and fetch the key + // it's a public key, need to find the JWK URI and fetch the key if (client.getJwksUri() == null) { - throw new InvalidClientException("Client must have a JWKS URI registered to use signed request objects."); + throw new InvalidClientException("Client must have a JWKS registered to use signed request objects with a public key."); } // check JWT signature diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java index 0f30d1008..3be84b56e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java @@ -74,15 +74,15 @@ public class IdTokenHashUtils { //as the JWSAlgorithm to hash the token. String hashAlg = null; - if (signingAlg.equals(JWSAlgorithm.HS256) || signingAlg.equals(JWSAlgorithm.ES256) || signingAlg.equals(JWSAlgorithm.RS256)) { + if (signingAlg.equals(JWSAlgorithm.HS256) || signingAlg.equals(JWSAlgorithm.ES256) || signingAlg.equals(JWSAlgorithm.RS256) || signingAlg.equals(JWSAlgorithm.PS256)) { hashAlg = "SHA-256"; } - else if (signingAlg.equals(JWSAlgorithm.ES384) || signingAlg.equals(JWSAlgorithm.HS384) || signingAlg.equals(JWSAlgorithm.RS384)) { + else if (signingAlg.equals(JWSAlgorithm.ES384) || signingAlg.equals(JWSAlgorithm.HS384) || signingAlg.equals(JWSAlgorithm.RS384) || signingAlg.equals(JWSAlgorithm.PS384)) { hashAlg = "SHA-384"; } - else if (signingAlg.equals(JWSAlgorithm.ES512) || signingAlg.equals(JWSAlgorithm.HS512) || signingAlg.equals(JWSAlgorithm.RS512)) { + else if (signingAlg.equals(JWSAlgorithm.ES512) || signingAlg.equals(JWSAlgorithm.HS512) || signingAlg.equals(JWSAlgorithm.RS512) || signingAlg.equals(JWSAlgorithm.PS512)) { hashAlg = "SHA-512"; }