diff --git a/openid-connect-client/.classpath b/openid-connect-client/.classpath index bf96ac098..b5b1093d8 100644 --- a/openid-connect-client/.classpath +++ b/openid-connect-client/.classpath @@ -10,5 +10,9 @@ + + + + diff --git a/openid-connect-client/.settings/org.eclipse.jdt.core.prefs b/openid-connect-client/.settings/org.eclipse.jdt.core.prefs index 62a317c86..5738c9c7a 100644 --- a/openid-connect-client/.settings/org.eclipse.jdt.core.prefs +++ b/openid-connect-client/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,23 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=warning +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error diff --git a/openid-connect-client/.settings/org.eclipse.jdt.launching.prefs b/openid-connect-client/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 000000000..d211d3263 --- /dev/null +++ b/openid-connect-client/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java index 2005886ff..592a2d041 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java @@ -426,7 +426,7 @@ public class AbstractOIDCAuthenticationFilter extends logger.debug("tokenEndpointURI = " + serverConfig.getTokenEndpointURI()); logger.debug("form = " + form); } - +; String jsonString = null; try { @@ -470,25 +470,27 @@ public class AbstractOIDCAuthenticationFilter extends DynamicJwtSigningAndValidationService jwtValidator = new DynamicJwtSigningAndValidationService(serverConfig.getX509SigningUrl(), serverConfig.getJwkSigningUrl(), serverConfig.getClientSecret()); if (jsonRoot.getAsJsonObject().get("id_token") != null) { + + try { + idToken = IdToken.parse(jsonRoot.getAsJsonObject().get("id_token").getAsString()); + + } catch (AuthenticationServiceException e) { + + // I suspect this could happen + + logger.error("Problem parsing id_token: " + e); + // e.printStackTrace(); + + throw new AuthenticationServiceException("Problem parsing id_token return from Token endpoint: " + e); + } if(jwtValidator.validateSignature(jsonRoot.getAsJsonObject().get("id_token").getAsString()) - && jwtValidator.validateIssuedJwt(idToken, serverConfig.getIssuer()) - && jwtValidator.validateAudience(idToken, serverConfig.getClientId()) + && idToken.getClaims().getIssuer().equals(serverConfig.getIssuer()) + && idToken.getClaims().getIssuer().equals(serverConfig.getClientId()) && jwtValidator.isJwtExpired(idToken) && jwtValidator.validateIssuedAt(idToken)){ - try { - idToken = IdToken.parse(jsonRoot.getAsJsonObject().get("id_token").getAsString()); - - } catch (Exception e) { - - // I suspect this could happen - - logger.error("Problem parsing id_token: " + e); - // e.printStackTrace(); - - throw new AuthenticationServiceException("Problem parsing id_token return from Token endpoint: " + e); - } + } else{ throw new AuthenticationServiceException("Problem verifying id_token"); diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java index c5f27688f..ae4693469 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java @@ -15,20 +15,17 @@ ******************************************************************************/ package org.mitre.openid.connect.client; -import java.io.File; -import java.net.URL; import java.security.Key; - -import org.mitre.jwt.signer.service.impl.DynamicJwtSigningAndValidationService; -import org.mitre.util.Utility; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException; +import org.mitre.key.fetch.KeyFetcher; /** * @author nemonik * */ public class OIDCServerConfiguration { - - private DynamicJwtSigningAndValidationService dynamic; private String authorizationEndpointURI; @@ -126,42 +123,57 @@ public class OIDCServerConfiguration { this.jwkSigningUrl = jwkSigningUrl; } - // FIXME: this should not throw Exception - public Key getSigningKey() throws Exception { + public Key getSigningKey(){ if(signingKey == null){ if(x509SigningUrl != null){ - File file = new File(x509SigningUrl); - URL url = file.toURI().toURL(); - signingKey = Utility.retrieveX509Key(url); + try { + signingKey = KeyFetcher.retrieveX509Key(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } else if (jwkSigningUrl != null){ - File file = new File(jwkSigningUrl); - URL url = file.toURI().toURL(); - signingKey = Utility.retrieveJwkKey(url); + try { + signingKey = KeyFetcher.retrieveJwkKey(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } return signingKey; } - // FIXME: this should not throw Exception - public Key getEncryptionKey() throws Exception { + public Key getEncryptionKey(){ if(encryptKey == null){ if(x509EncryptUrl != null){ - File file = new File(x509EncryptUrl); - URL url = file.toURI().toURL(); - encryptKey = Utility.retrieveX509Key(url); + try { + encryptKey = KeyFetcher.retrieveX509Key(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } else if (jwkEncryptUrl != null){ - File file = new File(jwkEncryptUrl); - URL url = file.toURI().toURL(); - encryptKey = Utility.retrieveJwkKey(url); + try { + encryptKey = KeyFetcher.retrieveJwkKey(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } return encryptKey; } - - // FIXME: this should not throw exception - public void checkKeys() throws Exception { + + public void checkKeys(){ encryptKey = null; signingKey = null; getEncryptionKey(); @@ -180,12 +192,5 @@ public class OIDCServerConfiguration { + x509SigningUrl + ", jwkSigningUrl=" + jwkSigningUrl + "]"; } - - // TODO: what is this function for? nobody uses it, and it seems backwards for construction - public DynamicJwtSigningAndValidationService getDynamic() throws Exception{ - dynamic = new DynamicJwtSigningAndValidationService(getX509SigningUrl(), getJwkSigningUrl(), getClientSecret()); - return dynamic; - } - } \ No newline at end of file diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java index 48f44358e..ba208afc9 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java @@ -1,16 +1,25 @@ package org.mitre.openid.connect.client; +import static org.junit.Assert.assertEquals; + import java.net.URL; import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.key.fetch.KeyFetcher; import org.mitre.util.Utility; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import junit.framework.TestCase; - -public class OIDCServerConfigurationTest extends TestCase { +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class OIDCServerConfigurationTest{ private URL jwkUrl = this.getClass().getResource("/jwk/jwk"); private URL x509Url = this.getClass().getResource("/x509/x509"); @@ -22,16 +31,15 @@ public class OIDCServerConfigurationTest extends TestCase { * @throws java.lang.Exception */ @Before - public void setUp() throws Exception { + public void setUp(){ oidc = new OIDCServerConfiguration(); - super.setUp(); } /** * @throws java.lang.Exception */ @After - public void tearDown() throws Exception { + public void tearDown(){ } /** @@ -39,31 +47,49 @@ public class OIDCServerConfigurationTest extends TestCase { * @throws Exception */ @Test - public void testGetSigningKeyBoth() throws Exception { + public void testGetSigningKeyBoth(){ oidc.setX509SigningUrl(x509Url.getPath()); oidc.setJwkSigningUrl(jwkUrl.getPath()); Key key = oidc.getSigningKey(); - assertEquals(key, Utility.retrieveX509Key(x509Url)); + try { + assertEquals(key, KeyFetcher.retrieveX509Key()); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } @Test - public void testGetSigningKeyJwk() throws Exception { + public void testGetSigningKeyJwk(){ oidc.setX509SigningUrl(null); oidc.setJwkSigningUrl(jwkUrl.getPath()); Key key1 = oidc.getSigningKey(); - assertEquals(key1, Utility.retrieveJwkKey(jwkUrl)); + try { + assertEquals(key1, KeyFetcher.retrieveJwkKey()); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } @Test - public void testGetSigningKeyX509() throws Exception { + public void testGetSigningKeyX509(){ oidc.setX509SigningUrl(x509Url.getPath()); oidc.setJwkSigningUrl(null); Key key2 = oidc.getSigningKey(); - assertEquals(key2, Utility.retrieveX509Key(x509Url)); + try { + assertEquals(key2, KeyFetcher.retrieveX509Key()); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } @Test - public void testGetSigningKeyNone() throws Exception { + public void testGetSigningKeyNone(){ oidc.setX509SigningUrl(null); oidc.setJwkSigningUrl(null); Key key3 = oidc.getSigningKey(); @@ -71,44 +97,52 @@ public class OIDCServerConfigurationTest extends TestCase { } @Test - public void testGetEncryptionKeyBoth() throws Exception { + public void testGetEncryptionKeyBoth(){ oidc.setX509EncryptUrl(x509EncryptedUrl.getPath()); oidc.setJwkEncryptUrl(jwkEncryptedUrl.getPath()); Key key = oidc.getEncryptionKey(); - assertEquals(key, Utility.retrieveX509Key(x509EncryptedUrl)); + try { + assertEquals(key, KeyFetcher.retrieveX509Key()); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } @Test - public void testGetEncryptionKeyJwk() throws Exception { + public void testGetEncryptionKeyJwk(){ oidc.setX509EncryptUrl(null); oidc.setJwkEncryptUrl(jwkEncryptedUrl.getPath()); Key key1 = oidc.getEncryptionKey(); - assertEquals(key1, Utility.retrieveJwkKey(jwkEncryptedUrl)); + try { + assertEquals(key1, KeyFetcher.retrieveJwkKey()); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } @Test - public void testGetEncryptionKeyX509() throws Exception { + public void testGetEncryptionKeyX509(){ oidc.setX509EncryptUrl(x509EncryptedUrl.getPath()); oidc.setJwkEncryptUrl(null); Key key2 = oidc.getEncryptionKey(); - assertEquals(key2, Utility.retrieveX509Key(x509EncryptedUrl)); + try { + assertEquals(key2, KeyFetcher.retrieveX509Key()); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } @Test - public void testGetEncryptionKeyNone() throws Exception { + public void testGetEncryptionKeyNone(){ oidc.setX509EncryptUrl(null); oidc.setJwkEncryptUrl(null); Key key3 = oidc.getEncryptionKey(); assertEquals(key3, null); } - - @Test - public void testGetDynamic() throws Exception { - oidc.setX509SigningUrl(x509Url.getPath()); - oidc.setJwkSigningUrl(jwkUrl.getPath()); - oidc.setClientSecret("foo"); - assertEquals(oidc.getDynamic().getSigningX509Url(), x509Url.getPath()); - assertEquals(oidc.getDynamic().getSigningJwkUrl(), jwkUrl.getPath()); - assertEquals(oidc.getDynamic().getClientSecret(), "foo"); - } } diff --git a/openid-connect-client/src/test/resources/test-context.xml b/openid-connect-client/src/test/resources/test-context.xml new file mode 100644 index 000000000..d9a6435a6 --- /dev/null +++ b/openid-connect-client/src/test/resources/test-context.xml @@ -0,0 +1,46 @@ + + + + + + + + + + file:db/tables/accesstoken.sql + file:db/tables/address.sql + file:db/tables/approvedsite.sql + file:db/tables/authorities.sql + file:db/tables/clientdetails.sql + file:db/tables/event.sql + file:db/tables/granttypes.sql + file:db/tables/idtoken.sql + file:db/tables/idtokenclaims.sql + file:db/tables/refreshtoken.sql + file:db/tables/scope.sql + file:db/tables/userinfo.sql + file:db/tables/whitelistedsite.sql + + classpath:test-data.sql + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/openid-connect-common/.classpath b/openid-connect-common/.classpath index bf96ac098..6f70891b9 100644 --- a/openid-connect-common/.classpath +++ b/openid-connect-common/.classpath @@ -1,14 +1,18 @@ - + + + + + diff --git a/openid-connect-common/.settings/org.eclipse.jdt.core.prefs b/openid-connect-common/.settings/org.eclipse.jdt.core.prefs index d2a6e1e36..d47a0fc68 100644 --- a/openid-connect-common/.settings/org.eclipse.jdt.core.prefs +++ b/openid-connect-common/.settings/org.eclipse.jdt.core.prefs @@ -1,9 +1,19 @@ -#Fri Mar 16 16:16:57 EDT 2012 eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=warning +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error diff --git a/openid-connect-common/.settings/org.eclipse.jdt.launching.prefs b/openid-connect-common/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 000000000..d211d3263 --- /dev/null +++ b/openid-connect-common/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java index 86a0ce452..b73113120 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java @@ -117,10 +117,15 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean { * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet(){ - mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()) - .getStandardName()); + try { + mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()) + .getStandardName()); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } logger.debug(JwsAlgorithm.getByName(getAlgorithm()).getStandardName() + " ECDSA Signer ready for business"); @@ -135,23 +140,23 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean { */ @Override public String generateSignature(String signatureBase) throws NoSuchAlgorithmException { - Mac _mac = getMac(); + afterPropertiesSet(); if (passphrase == null) { throw new IllegalArgumentException("Passphrase cannot be null"); } try { - _mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac + mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac .getAlgorithm())); - _mac.update(signatureBase.getBytes("UTF-8")); + mac.update(signatureBase.getBytes("UTF-8")); } catch (GeneralSecurityException e) { logger.error(e); } catch (UnsupportedEncodingException e) { logger.error(e); } - byte[] sigBytes = _mac.doFinal(); + byte[] sigBytes = mac.doFinal(); String sig = new String(Base64.encodeBase64URLSafe(sigBytes)); @@ -172,15 +177,7 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean { public void setPassphrase(String passphrase) { this.passphrase = passphrase; } - - // TODO: this this indirection to a lazy constructor necessary? - private Mac getMac() throws NoSuchAlgorithmException { - if(mac == null){ - mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()) - .getStandardName()); - } - return mac; - } + /* * (non-Javadoc) diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java index b394d4153..75a773999 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java @@ -177,13 +177,18 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { public String generateSignature(String signatureBase) throws NoSuchAlgorithmException { String sig = null; - Signature _signer = getSigner(); + try { + initializeSigner(); + } catch (GeneralSecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } try { - _signer.initSign(privateKey); - _signer.update(signatureBase.getBytes("UTF-8")); + signer.initSign(privateKey); + signer.update(signatureBase.getBytes("UTF-8")); - byte[] sigBytes = _signer.sign(); + byte[] sigBytes = signer.sign(); sig = (new String(Base64.encodeBase64URLSafe(sigBytes))).replace("=", ""); } catch (GeneralSecurityException e) { @@ -230,13 +235,9 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { public void setPrivateKey(RSAPrivateKey privateKey) { this.privateKey = privateKey; } - - // TODO: this this indirection to a lazy constructor really necessary? - private Signature getSigner() throws NoSuchAlgorithmException{ - if(signer == null){ - signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName()); - } - return signer; + + public void initializeSigner() throws NoSuchAlgorithmException{ + signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName()); } /* diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java index 042d3fc41..708f537f3 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java @@ -41,17 +41,6 @@ public interface JwtSigningAndValidationService { */ public boolean isJwtExpired(Jwt jwt); - /** - * Checks to see if this JWT has been issued by us - * - * @param jwt - * the JWT to check the issuer of - * @param expectedIssuer - * the expected issuer - * @return true if the JWT was issued by this expected issuer, false if not - */ - public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer); - /** * Checks the signature of the given JWT against all configured signers, * returns true if at least one of the signers validates it. @@ -63,14 +52,7 @@ public interface JwtSigningAndValidationService { */ public boolean validateSignature(String jwtString) throws NoSuchAlgorithmException; - /** - * Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm. - * Use the default algorithm to sign. - * - * @param jwt the jwt to sign - * @return the signed jwt - * @throws NoSuchAlgorithmException - */ + /** * Checks to see when this JWT was issued * @@ -81,17 +63,6 @@ public interface JwtSigningAndValidationService { */ public boolean validateIssuedAt(Jwt jwt); - /** - * Checks the audience that the given JWT against the client_id of the Client - * - * @param jwt - * @param clientId - * the string representation of the client_id - * @return true if the audience matches the clinet_id, false if otherwise - * @throws NoSuchAlgorithmException - */ - public boolean validateAudience(Jwt jwt, String clientId); - /** * Checks to see if the nonce parameter sent in the Authorization Request * is equal to the nonce parameter in the id token @@ -112,6 +83,15 @@ public interface JwtSigningAndValidationService { * @param alg the name of the algorithm to use, as specified in JWS s.6 * @return the signed jwt */ + + /** + * Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm. + * Use the default algorithm to sign. + * + * @param jwt the jwt to sign + * @return the signed jwt + * @throws NoSuchAlgorithmException + */ public void signJwt(Jwt jwt) throws NoSuchAlgorithmException; //TODO: implement later; only need signJwt(Jwt jwt) for now diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java index e3cc3a833..81e7c539a 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java @@ -29,18 +29,6 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni } } - @Override - public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) { - - String iss = jwt.getClaims().getIssuer(); - - if (iss.equals(expectedIssuer)) { - return true; - } - - return false; - } - @Override public boolean validateSignature(String jwtString) throws NoSuchAlgorithmException { @@ -63,16 +51,6 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni } } - @Override - public boolean validateAudience(Jwt jwt, String expectedAudience) { - - if(jwt.getClaims().getAudience().equals(expectedAudience)){ - return true; - } else { - return false; - } - } - @Override public boolean validateNonce(Jwt jwt, String nonce) { if(jwt.getClaims().getNonce().equals(nonce)){ diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java index 0c327d890..abb8a2a54 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java @@ -1,10 +1,14 @@ package org.mitre.jwt.signer.service.impl; import java.io.File; +import java.net.MalformedURLException; import java.net.URL; import java.security.Key; +import java.security.NoSuchAlgorithmException; import java.security.PublicKey; +import java.security.cert.CertificateException; import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -15,6 +19,7 @@ import org.mitre.jwt.signer.JwtSigner; import org.mitre.jwt.signer.impl.HmacSigner; import org.mitre.jwt.signer.impl.PlaintextSigner; import org.mitre.jwt.signer.impl.RsaSigner; +import org.mitre.key.fetch.KeyFetcher; import org.mitre.util.Utility; @@ -40,18 +45,38 @@ public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAnd setClientSecret(clientSecret); } - // FIXME: this function should not throw Exception - public Key getSigningKey() throws Exception { + public Key getSigningKey() { if(signingKey == null){ if(x509SigningUrl != null){ File file = new File(x509SigningUrl); - URL url = file.toURI().toURL(); - signingKey = Utility.retrieveX509Key(url); + URL url; + try { + url = file.toURI().toURL(); + signingKey = KeyFetcher.retrieveX509Key(); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } else if (jwkSigningUrl != null){ File file = new File(jwkSigningUrl); - URL url = file.toURI().toURL(); - signingKey = Utility.retrieveJwkKey(url); + URL url; + try { + url = file.toURI().toURL(); + signingKey = KeyFetcher.retrieveJwkKey(); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } return signingKey; @@ -156,17 +181,6 @@ public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAnd return false; } - @Override - public boolean validateAudience(Jwt jwt, String clientId) { - - if(jwt.getClaims().getAudience().equals(clientId)){ - return true; - } - else{ - return false; - } - } - @Override public boolean validateNonce(Jwt jwt, String nonce) { if(jwt.getClaims().getNonce().equals(nonce)){ diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java index c2a9256e0..f1078ce75 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java @@ -67,7 +67,7 @@ public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAnd * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet(){ // used for debugging... if (!signers.isEmpty()) { logger.info(this.toString()); @@ -175,17 +175,6 @@ public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAnd return false; } - @Override - public boolean validateAudience(Jwt jwt, String clientId) { - - if(clientId.equals(jwt.getClaims().getAudience())){ - return true; - } - else{ - return false; - } - } - @Override public boolean validateNonce(Jwt jwt, String nonce) { if(nonce.equals(jwt.getClaims().getNonce())){ diff --git a/openid-connect-common/src/main/java/org/mitre/key/fetch/KeyFetcher.java b/openid-connect-common/src/main/java/org/mitre/key/fetch/KeyFetcher.java new file mode 100644 index 000000000..bf2eea1ab --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/key/fetch/KeyFetcher.java @@ -0,0 +1,145 @@ +package org.mitre.key.fetch; + +import java.io.InputStream; +import java.math.BigInteger; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.codec.binary.Base64; +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.mitre.jwk.model.EC; +import org.mitre.jwk.model.Jwk; +import org.mitre.jwk.model.Rsa; +import org.mitre.openid.connect.client.OIDCServerConfiguration; + +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResponseExtractor; +import org.springframework.web.client.RestTemplate; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +public class KeyFetcher { + + public static List retrieveJwk(){ + + OIDCServerConfiguration serverConfig = new OIDCServerConfiguration(); + + List keys = new ArrayList(); + + HttpClient httpClient = new DefaultHttpClient(); + HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + RestTemplate restTemplate = new RestTemplate(httpFactory); + MultiValueMap form = new LinkedMultiValueMap(); + + String jsonString = null; + + try { + jsonString = restTemplate.postForObject( + serverConfig.getTokenEndpointURI(), form, String.class); + } catch (HttpClientErrorException httpClientErrorException) { + + throw new AuthenticationServiceException( + "Unable to obtain Access Token."); + } + + JsonObject json = (JsonObject) new JsonParser().parse(jsonString); + JsonArray getArray = json.getAsJsonArray("jwk"); + + for(int i = 0; i < getArray.size(); i++){ + + JsonObject object = getArray.get(i).getAsJsonObject(); + String algorithm = object.get("alg").getAsString(); + + if(algorithm.equals("RSA")){ + Rsa rsa = new Rsa(object); + keys.add(rsa); + } + + else{ + EC ec = new EC(object); + keys.add(ec); + } + } + return keys; + } + + public static Key retrieveX509Key() throws CertificateException { + + OIDCServerConfiguration serverConfig = new OIDCServerConfiguration(); + + HttpClient httpClient = new DefaultHttpClient(); + HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + RestTemplate restTemplate = new RestTemplate(httpFactory); + MultiValueMap form = new LinkedMultiValueMap(); + + InputStream jsonStream = null; + + try { + jsonStream = restTemplate.postForObject( + serverConfig.getTokenEndpointURI(), form, InputStream.class); + } catch (HttpClientErrorException httpClientErrorException) { + + throw new AuthenticationServiceException( + "Unable to obtain Access Token."); + } + + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate) factory.generateCertificate(jsonStream); + Key key = cert.getPublicKey(); + + return key; + } + + public static Key retrieveJwkKey() throws NoSuchAlgorithmException, InvalidKeySpecException{ + + OIDCServerConfiguration serverConfig = new OIDCServerConfiguration(); + + HttpClient httpClient = new DefaultHttpClient(); + HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + RestTemplate restTemplate = new RestTemplate(httpFactory); + MultiValueMap form = new LinkedMultiValueMap(); + + String jsonString = null; + + try { + jsonString = restTemplate.postForObject( + serverConfig.getTokenEndpointURI(), form, String.class); + } catch (HttpClientErrorException httpClientErrorException) { + + throw new AuthenticationServiceException( + "Unable to obtain Access Token."); + } + + JsonObject json = (JsonObject) new JsonParser().parse(jsonString); + JsonArray getArray = json.getAsJsonArray("jwk"); + JsonObject object = getArray.get(0).getAsJsonObject(); + + byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString()); + BigInteger modulus = new BigInteger(modulusByte); + byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString()); + BigInteger exponent = new BigInteger(exponentByte); + + RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); + KeyFactory factory = KeyFactory.getInstance("RSA"); + PublicKey pub = factory.generatePublic(spec); + + return pub; + } + +} diff --git a/openid-connect-common/src/main/java/org/mitre/util/Utility.java b/openid-connect-common/src/main/java/org/mitre/util/Utility.java index 35acac409..60ed60d08 100644 --- a/openid-connect-common/src/main/java/org/mitre/util/Utility.java +++ b/openid-connect-common/src/main/java/org/mitre/util/Utility.java @@ -69,60 +69,5 @@ public class Utility { } return issuer; } - - // FIXME: this should use a rest template and sould not throw Exception - public static List retrieveJwk(URL path) throws Exception { - List keys = new ArrayList(); - - JsonParser parser = new JsonParser(); - JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(path.openStream()))).getAsJsonObject(); - JsonArray getArray = json.getAsJsonArray("jwk"); - - for(int i = 0; i < getArray.size(); i++){ - - JsonObject object = getArray.get(i).getAsJsonObject(); - String algorithm = object.get("alg").getAsString(); - - if(algorithm.equals("RSA")){ - Rsa rsa = new Rsa(object); - keys.add(rsa); - } - else{ - EC ec = new EC(object); - keys.add(ec); - } - } - return keys; - } - - // FIXME: this should use a rest template and sould not throw Exception - public static Key retrieveX509Key(URL url) throws Exception { - - CertificateFactory factory = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) factory.generateCertificate(url.openStream()); - Key key = cert.getPublicKey(); - - return key; - } - - // FIXME: this should use a rest template and sould not throw Exception - public static Key retrieveJwkKey(URL url) throws Exception { - - JsonParser parser = new JsonParser(); - JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject(); - JsonArray getArray = json.getAsJsonArray("jwk"); - JsonObject object = getArray.get(0).getAsJsonObject(); - - byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString()); - BigInteger modulus = new BigInteger(modulusByte); - byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString()); - BigInteger exponent = new BigInteger(exponentByte); - - RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); - KeyFactory factory = KeyFactory.getInstance("RSA"); - PublicKey pub = factory.generatePublic(spec); - - return pub; - } } diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac256Test.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac256Test.java new file mode 100644 index 000000000..6ace0a0be --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac256Test.java @@ -0,0 +1,68 @@ +package org.mitre.jwt.signer.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwt.model.Jwt; +import org.mitre.jwt.model.JwtClaims; +import org.mitre.jwt.model.JwtHeader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class Hmac256Test{ + + URL claimsUrl = this.getClass().getResource("/jwt/claims"); + URL hs256Url = this.getClass().getResource("/jwt/hs256"); + + Jwt jwt = null; + JwtClaims claims = null; + JwtHeader header = null; + + /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException + * @throws java.lang.Exception + */ + @Before + public void setUp() throws JsonIOException, JsonSyntaxException, IOException{ + JsonParser parser = new JsonParser(); + JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(hs256Url.openStream()))).getAsJsonObject(); + claims = new JwtClaims(claimsObject); + header = new JwtHeader(headerObject); + jwt = new Jwt(header, claims, null); + + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown(){ + } + + @Test + public void testHmacSigner256() throws Exception { + setUp(); + HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret"); + jwt = hmac.sign(jwt); + assertEquals(hmac.verify(jwt.toString()), true); + } +} + \ No newline at end of file diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac384Test.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac384Test.java new file mode 100644 index 000000000..efac2ef49 --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac384Test.java @@ -0,0 +1,68 @@ +package org.mitre.jwt.signer.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwt.model.Jwt; +import org.mitre.jwt.model.JwtClaims; +import org.mitre.jwt.model.JwtHeader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class Hmac384Test { + + URL claimsUrl = this.getClass().getResource("/jwt/claims"); + URL hs384Url = this.getClass().getResource("/jwt/hs384"); + + Jwt jwt = null; + JwtClaims claims = null; + JwtHeader header = null; + + /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException + * @throws java.lang.Exception + */ + @Before + public void setUp() throws JsonIOException, JsonSyntaxException, IOException{ + JsonParser parser = new JsonParser(); + JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(hs384Url.openStream()))).getAsJsonObject(); + claims = new JwtClaims(claimsObject); + header = new JwtHeader(headerObject); + jwt = new Jwt(header, claims, null); + + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown(){ + } + + @Test + public void testHmacSigner384() throws Exception { + setUp(); + HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret"); + jwt = hmac.sign(jwt); + assertEquals(hmac.verify(jwt.toString()), true); + } + +} diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac512Test.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac512Test.java new file mode 100644 index 000000000..d4b06049e --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Hmac512Test.java @@ -0,0 +1,68 @@ +package org.mitre.jwt.signer.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwt.model.Jwt; +import org.mitre.jwt.model.JwtClaims; +import org.mitre.jwt.model.JwtHeader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class Hmac512Test { + + URL claimsUrl = this.getClass().getResource("/jwt/claims"); + URL hs512Url = this.getClass().getResource("/jwt/hs512"); + + Jwt jwt = null; + JwtClaims claims = null; + JwtHeader header = null; + + /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException + * @throws java.lang.Exception + */ + @Before + public void setUp() throws JsonIOException, JsonSyntaxException, IOException{ + JsonParser parser = new JsonParser(); + JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(hs512Url.openStream()))).getAsJsonObject(); + claims = new JwtClaims(claimsObject); + header = new JwtHeader(headerObject); + jwt = new Jwt(header, claims, null); + + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown(){ + } + + @Test + public void testHmacSigner512() throws Exception { + setUp(); + HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret"); + jwt = hmac.sign(jwt); + assertEquals(hmac.verify(jwt.toString()), true); + } + +} diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java index 446212872..f67a9e476 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java @@ -1,22 +1,31 @@ package org.mitre.jwt.signer.impl; +import static org.junit.Assert.assertEquals; + import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; +import java.security.NoSuchAlgorithmException; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mitre.jwt.model.Jwt; import org.mitre.jwt.model.JwtClaims; import org.mitre.jwt.model.JwtHeader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import com.google.gson.JsonIOException; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; -import junit.framework.TestCase; - -public class PlaintextSignerTest extends TestCase { +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class PlaintextSignerTest{ URL claimsUrl = this.getClass().getResource("/jwt/claims"); URL plaintextUrl = this.getClass().getResource("/jwt/plaintext"); @@ -25,13 +34,16 @@ public class PlaintextSignerTest extends TestCase { JwtHeader header = null; /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException * @throws java.lang.Exception */ @Before - public void setUp(URL url) throws Exception { + public void setUp() throws JsonIOException, JsonSyntaxException, IOException { JsonParser parser = new JsonParser(); JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); - JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(plaintextUrl.openStream()))).getAsJsonObject(); claims = new JwtClaims(claimsObject); header = new JwtHeader(headerObject); jwt = new Jwt(header, claims, null); @@ -41,12 +53,12 @@ public class PlaintextSignerTest extends TestCase { * @throws java.lang.Exception */ @After - public void tearDown() throws Exception { + public void tearDown() { } @Test - public void testPlaintextSigner() throws Exception { - setUp(plaintextUrl); + public void testPlaintextSigner() throws JsonIOException, JsonSyntaxException, IOException, NoSuchAlgorithmException { + setUp(); PlaintextSigner plaintext = new PlaintextSigner(); jwt = plaintext.sign(jwt); assertEquals(plaintext.verify(jwt.toString()), true); diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa256Test.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa256Test.java new file mode 100644 index 000000000..1d9ac0f97 --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa256Test.java @@ -0,0 +1,82 @@ +package org.mitre.jwt.signer.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwt.model.Jwt; +import org.mitre.jwt.model.JwtClaims; +import org.mitre.jwt.model.JwtHeader; +import org.mitre.jwt.signer.JwsAlgorithm; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class Rsa256Test{ + + + URL claimsUrl = this.getClass().getResource("/jwt/claims"); + URL rs256Url = this.getClass().getResource("/jwt/rs256"); + + Jwt jwt = null; + JwtClaims claims = null; + JwtHeader header = null; + KeyPairGenerator keyGen; + KeyPair keyPair; + PublicKey publicKey; + PrivateKey privateKey; + + /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException + * @throws java.lang.Exception + */ + @Before + public void setUp() throws JsonIOException, JsonSyntaxException, IOException{ + JsonParser parser = new JsonParser(); + JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(rs256Url.openStream()))).getAsJsonObject(); + claims = new JwtClaims(claimsObject); + header = new JwtHeader(headerObject); + jwt = new Jwt(header, claims, null); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown(){ + } + + @Test + public void testRsaSigner256() throws Exception { + + keyGen = KeyPairGenerator.getInstance("RSA"); + keyPair = keyGen.generateKeyPair(); + publicKey = keyPair.getPublic(); + privateKey = keyPair.getPrivate(); + RsaSigner rsa = new RsaSigner(JwsAlgorithm.RS256.toString(), publicKey, privateKey); + jwt = rsa.sign(jwt); + assertEquals(rsa.verify(jwt.toString()), true); + + } + +} \ No newline at end of file diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa384Test.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa384Test.java new file mode 100644 index 000000000..c3039ac90 --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa384Test.java @@ -0,0 +1,81 @@ +package org.mitre.jwt.signer.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwt.model.Jwt; +import org.mitre.jwt.model.JwtClaims; +import org.mitre.jwt.model.JwtHeader; +import org.mitre.jwt.signer.JwsAlgorithm; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class Rsa384Test { + + URL claimsUrl = this.getClass().getResource("/jwt/claims"); + URL rs384Url = this.getClass().getResource("/jwt/rs384"); + + Jwt jwt = null; + JwtClaims claims = null; + JwtHeader header = null; + KeyPairGenerator keyGen; + KeyPair keyPair; + PublicKey publicKey; + PrivateKey privateKey; + + /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException + * @throws java.lang.Exception + */ + @Before + public void setUp() throws JsonIOException, JsonSyntaxException, IOException{ + JsonParser parser = new JsonParser(); + JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(rs384Url.openStream()))).getAsJsonObject(); + claims = new JwtClaims(claimsObject); + header = new JwtHeader(headerObject); + jwt = new Jwt(header, claims, null); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown(){ + } + + @Test + public void testRsaSigner384() throws Exception{ + setUp(); + keyGen = KeyPairGenerator.getInstance("RSA"); + keyPair = keyGen.generateKeyPair(); + publicKey = keyPair.getPublic(); + privateKey = keyPair.getPrivate(); + RsaSigner rsa = new RsaSigner(JwsAlgorithm.RS384.toString(), publicKey, privateKey); + jwt = rsa.sign(jwt); + assertEquals(rsa.verify(jwt.toString()), true); + + } + +} diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa512Test.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa512Test.java new file mode 100644 index 000000000..8da0a4b1f --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/Rsa512Test.java @@ -0,0 +1,81 @@ +package org.mitre.jwt.signer.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwt.model.Jwt; +import org.mitre.jwt.model.JwtClaims; +import org.mitre.jwt.model.JwtHeader; +import org.mitre.jwt.signer.JwsAlgorithm; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class Rsa512Test { + + URL claimsUrl = this.getClass().getResource("/jwt/claims"); + URL rs512Url = this.getClass().getResource("/jwt/rs512"); + + Jwt jwt = null; + JwtClaims claims = null; + JwtHeader header = null; + KeyPairGenerator keyGen; + KeyPair keyPair; + PublicKey publicKey; + PrivateKey privateKey; + + /** + * @throws IOException + * @throws JsonSyntaxException + * @throws JsonIOException + * @throws java.lang.Exception + */ + @Before + public void setUp() throws JsonIOException, JsonSyntaxException, IOException{ + JsonParser parser = new JsonParser(); + JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject(); + JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(rs512Url.openStream()))).getAsJsonObject(); + claims = new JwtClaims(claimsObject); + header = new JwtHeader(headerObject); + jwt = new Jwt(header, claims, null); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown(){ + } + + @Test + public void testRsaSigner512() throws Exception{ + setUp(); + keyGen = KeyPairGenerator.getInstance("RSA"); + keyPair = keyGen.generateKeyPair(); + publicKey = keyPair.getPublic(); + privateKey = keyPair.getPrivate(); + RsaSigner rsa = new RsaSigner(JwsAlgorithm.RS512.toString(), publicKey, privateKey); + jwt = rsa.sign(jwt); + assertEquals(rsa.verify(jwt.toString()), true); + + } + +} diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java index 95391cea0..d65298590 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java @@ -1,5 +1,7 @@ package org.mitre.jwt.signer.service.impl; +import static org.junit.Assert.assertEquals; + import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; @@ -10,12 +12,17 @@ import junit.framework.TestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mitre.jwt.signer.JwtSigner; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -public class DynamicJwtSigningAndValidationServiceTest extends TestCase { +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class DynamicJwtSigningAndValidationServiceTest { URL x509Url = this.getClass().getResource("/x509/x509Cert"); URL jwkUrl = this.getClass().getResource("/jwk/rsaOnly"); @@ -29,7 +36,6 @@ public class DynamicJwtSigningAndValidationServiceTest extends TestCase { */ @Before public void setUp() throws Exception { - super.setUp(); } /** diff --git a/openid-connect-common/src/test/java/org/mitre/key/fetch/KeyFetcherTest.java b/openid-connect-common/src/test/java/org/mitre/key/fetch/KeyFetcherTest.java new file mode 100644 index 000000000..cf3f87a8e --- /dev/null +++ b/openid-connect-common/src/test/java/org/mitre/key/fetch/KeyFetcherTest.java @@ -0,0 +1,70 @@ +package org.mitre.key.fetch; + +import static org.junit.Assert.assertEquals; + + +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.List; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mitre.jwk.model.EC; +import org.mitre.jwk.model.Jwk; +import org.mitre.jwk.model.Rsa; +import org.mitre.openid.connect.client.OIDCServerConfiguration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class KeyFetcherTest { + + private KeyFetcher keyFetch; + + @Before + public void setUp(){ + keyFetch = EasyMock.createMock(KeyFetcher.class); + } + + @After + public void tearDown(){ + } + + @Test + public void retrieveJwkTest(){ + //EasyMock.expect(keyFetch.retrieveJwk()).andReturn(Rsa(new JsonObject(object))).once(); + } + + @Test + public void retrieveX509Key(){ + + } + + @Test + public void retriveJwkKey(){ + + } + +} diff --git a/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java b/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java index 674e2306a..66ebc7cd6 100644 --- a/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java +++ b/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java @@ -3,6 +3,8 @@ */ package org.mitre.util; +import static org.junit.Assert.assertEquals; + import java.security.Key; import java.security.KeyFactory; import java.security.PublicKey; @@ -23,10 +25,14 @@ import junit.framework.TestCase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mitre.jwk.model.Jwk; import org.mitre.jwk.model.Rsa; import org.mitre.jwk.model.EC; +import org.mitre.key.fetch.KeyFetcher; import org.mitre.util.Utility; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -42,7 +48,9 @@ import org.bouncycastle.jce.provider.JCEECPublicKey; * @author DERRYBERRY * */ -public class UtilityTest extends TestCase{ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath:test-context.xml" }) +public class UtilityTest { URL url = this.getClass().getResource("/jwk/jwkSuccess"); URL certUrl = this.getClass().getResource("/x509/x509Cert"); @@ -53,7 +61,6 @@ public class UtilityTest extends TestCase{ */ @Before public void setUp() throws Exception { - super.setUp(); } /** @@ -74,7 +81,7 @@ public class UtilityTest extends TestCase{ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject(); JsonArray getArray = json.getAsJsonArray("jwk"); - List list = Utility.retrieveJwk(url); + List list = KeyFetcher.retrieveJwk(); for(int i = 0; i < list.size(); i++){ @@ -108,7 +115,7 @@ public class UtilityTest extends TestCase{ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject(); JsonArray getArray = json.getAsJsonArray("jwk"); - List list = Utility.retrieveJwk(url); + List list = KeyFetcher.retrieveJwk(); for(int i = 0; i < list.size(); i++){ Jwk jwk = list.get(i); @@ -133,14 +140,14 @@ public class UtilityTest extends TestCase{ public void testRetriveX509Key() throws Exception { CertificateFactory factory = CertificateFactory.getInstance("X.509"); X509Certificate x509 = (X509Certificate) factory.generateCertificate(certUrl.openStream()); - Key key = Utility.retrieveX509Key(certUrl); + Key key = KeyFetcher.retrieveX509Key(); assertEquals(x509.getPublicKey(), key); assertEquals("RSA", key.getAlgorithm()); assertEquals("X.509", key.getFormat()); } public void testRetriveJwkKey() throws Exception { - Key key = Utility.retrieveJwkKey(rsaUrl); + Key key = KeyFetcher.retrieveJwkKey(); JsonParser parser = new JsonParser(); JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(rsaUrl.openStream()))).getAsJsonObject(); diff --git a/openid-connect-common/src/test/resources/test-context.xml b/openid-connect-common/src/test/resources/test-context.xml new file mode 100644 index 000000000..c849de679 --- /dev/null +++ b/openid-connect-common/src/test/resources/test-context.xml @@ -0,0 +1,40 @@ + + + + + + + + + + file:db/tables/accesstoken.sql + file:db/tables/address.sql + file:db/tables/approvedsite.sql + file:db/tables/authorities.sql + file:db/tables/clientdetails.sql + file:db/tables/event.sql + file:db/tables/granttypes.sql + file:db/tables/idtoken.sql + file:db/tables/idtokenclaims.sql + file:db/tables/refreshtoken.sql + file:db/tables/scope.sql + file:db/tables/userinfo.sql + file:db/tables/whitelistedsite.sql + + classpath:test-data.sql + + + + + + + + + + + \ No newline at end of file diff --git a/openid-connect-server/.settings/org.eclipse.jdt.core.prefs b/openid-connect-server/.settings/org.eclipse.jdt.core.prefs index 34653a858..d47a0fc68 100644 --- a/openid-connect-server/.settings/org.eclipse.jdt.core.prefs +++ b/openid-connect-server/.settings/org.eclipse.jdt.core.prefs @@ -1,9 +1,19 @@ -#Wed Jan 04 13:07:35 EST 2012 eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=warning +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error diff --git a/openid-connect-server/.settings/org.eclipse.jdt.launching.prefs b/openid-connect-server/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 000000000..d211d3263 --- /dev/null +++ b/openid-connect-server/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java index 346626ccd..c46694b7e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java @@ -69,9 +69,9 @@ public class CheckIDEndpoint { } // check the issuer (sanity check) - if (!jwtSignerService.validateIssuedJwt(token, configBean.getIssuer())) { - throw new InvalidJwtIssuerException("The JWT issuer is invalid."); - } + //if (!jwtSignerService.validateIssuedJwt(token, configBean.getIssuer())) { + // throw new InvalidJwtIssuerException("The JWT issuer is invalid."); + //} // pass the claims directly (the view doesn't care about other fields) return new ModelAndView("jsonIdTokenView", "entity", token.getClaims());