From a63c03313596b94356ede22490c36410f5234db9 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 15 Feb 2012 11:57:27 -0500 Subject: [PATCH 1/7] updated formatting of JWK endpoint to be compliant (still could use a kid field) --- .../java/org/mitre/openid/connect/view/JwkKeyListView.java | 4 +++- .../org/mitre/openid/connect/web/JsonWebKeyEndpoint.java | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/mitre/openid/connect/view/JwkKeyListView.java b/server/src/main/java/org/mitre/openid/connect/view/JwkKeyListView.java index ecbf2e57d..af7794a0d 100644 --- a/server/src/main/java/org/mitre/openid/connect/view/JwkKeyListView.java +++ b/server/src/main/java/org/mitre/openid/connect/view/JwkKeyListView.java @@ -72,7 +72,9 @@ public class JwkKeyListView extends AbstractView { String e64 = Base64.encodeBase64URLSafeString(exp.toByteArray()); JsonObject o = new JsonObject(); - + + o.addProperty("use", "sig"); + o.addProperty("alg", "RSA"); o.addProperty("mod", m64); o.addProperty("exp", e64); diff --git a/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java b/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java index e1a9abb0a..b5abb363a 100644 --- a/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java +++ b/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java @@ -3,7 +3,9 @@ package org.mitre.openid.connect.web; import java.security.PublicKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPublicKey; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.springframework.beans.factory.annotation.Autowired; @@ -24,7 +26,10 @@ public class JsonWebKeyEndpoint { // TODO: check if keys are empty, return a 404 here or just an empty list? - return new ModelAndView("jwkKeyList", "entity", keys); + Map jwk = new HashMap(); + jwk.put("jwk", keys); + + return new ModelAndView("jwkKeyList", "entity", jwk); } } From 5e32e9605b16d56de65ab0525facce35cd3b7c98 Mon Sep 17 00:00:00 2001 From: Michael Joseph Walsh Date: Wed, 15 Feb 2012 12:11:10 -0500 Subject: [PATCH 2/7] refactored KeyStore unit test --- .../jwt/signer/service/impl/KeyStore.java | 18 +-- .../jwt/signer/service/impl/KeyStoreTest.java | 136 +++++++++++++++--- 2 files changed, 120 insertions(+), 34 deletions(-) diff --git a/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java b/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java index 8130e0a07..a9341d634 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java @@ -2,29 +2,18 @@ package org.mitre.jwt.signer.service.impl; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; -import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.bouncycastle.jce.X509Principal; -import org.bouncycastle.x509.X509V3CertificateGenerator; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; @@ -34,13 +23,11 @@ import org.springframework.core.io.Resource; * @author nemonik * */ -@SuppressWarnings("deprecation") public class KeyStore implements InitializingBean { private static Log logger = LogFactory.getLog(KeyStore.class); - public static final String TYPE = java.security.KeyStore.getDefaultType(); // "BKS"; - public static final String PROVIDER = "BC"; + public static final String TYPE = java.security.KeyStore.getDefaultType(); public static final String PASSWORD = "changeit"; private String password; @@ -81,7 +68,7 @@ public class KeyStore implements InitializingBean { InputStream inputStream = null; try { - keystore = java.security.KeyStore.getInstance(TYPE); //, PROVIDER); + keystore = java.security.KeyStore.getInstance(TYPE); inputStream = location.getInputStream(); keystore.load(inputStream, this.password.toCharArray()); @@ -169,4 +156,5 @@ public class KeyStore implements InitializingBean { return "KeyStore [password=" + password + ", location=" + location + ", keystore=" + keystore + "]"; } + } diff --git a/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java b/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java index 62fdf400c..8a3e39d65 100644 --- a/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java +++ b/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java @@ -5,9 +5,19 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; import java.io.IOException; +import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.Key; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.util.Date; +import org.bouncycastle.jce.X509Principal; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.x509.X509V3CertificateGenerator; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -15,7 +25,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -@SuppressWarnings("restriction") // I know... +@SuppressWarnings({ "restriction", "deprecation" }) // I know... @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-context.xml" }) @@ -25,31 +35,119 @@ public class KeyStoreTest { @Qualifier("testKeystore") KeyStore keystore; + static { + // Need to create the certificate + Security.addProvider(new BouncyCastleProvider()); + } + + /** + * Creates a certificate. + * + * @param commonName + * @param daysNotValidBefore + * @param daysNotValidAfter + * @return + */ + private X509V3CertificateGenerator createCertificate( + String commonName, int daysNotValidBefore, int daysNotValidAfter) { + // BC sez X509V3CertificateGenerator is deprecated and the docs say to + // use another, but it seemingly isn't included jar... + X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); + + v3CertGen + .setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); + v3CertGen.setIssuerDN(new X509Principal("CN=" + commonName + + ", OU=None, O=None L=None, C=None")); + v3CertGen.setNotBefore(new Date(System.currentTimeMillis() + - (1000L * 60 * 60 * 24 * daysNotValidBefore))); + v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + + (1000L * 60 * 60 * 24 * daysNotValidAfter))); + v3CertGen.setSubjectDN(new X509Principal("CN=" + commonName + + ", OU=None, O=None L=None, C=None")); + return v3CertGen; + } + + /** + * Create an RSA KeyPair and insert into specified KeyStore + * + * @param location + * @param domainName + * @param alias + * @param keystorePassword + * @param aliasPassword + * @param daysNotValidBefore + * @param daysNotValidAfter + * @return + * @throws GeneralSecurityException + * @throws IOException + */ + public java.security.KeyStore generateRsaKeyPair( + String domainName, String alias, String aliasPassword, int daysNotValidBefore, int daysNotValidAfter) + throws GeneralSecurityException, IOException { + + java.security.KeyStore ks = keystore.getKeystore(); + + KeyPairGenerator rsaKeyPairGenerator = null; + + rsaKeyPairGenerator = KeyPairGenerator.getInstance("RSA"); + + rsaKeyPairGenerator.initialize(2048); + KeyPair rsaKeyPair = rsaKeyPairGenerator.generateKeyPair(); + + // BC sez X509V3CertificateGenerator is deprecated and the docs say to + // use another, but it seemingly isn't included jar... + X509V3CertificateGenerator v3CertGen = createCertificate(domainName, + daysNotValidBefore, daysNotValidAfter); + + RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) rsaKeyPair.getPrivate(); + + v3CertGen.setPublicKey(rsaKeyPair.getPublic()); + v3CertGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); + + // BC docs say to use another, but it seemingly isn't included... + X509Certificate certificate = v3CertGen + .generateX509Certificate(rsaPrivateKey); + + // if exist, overwrite + ks.setKeyEntry(alias, rsaPrivateKey, aliasPassword.toCharArray(), + new java.security.cert.Certificate[] { certificate }); + + keystore.setKeystore(ks); + + return ks; + } + @Test public void storeKeyPair() throws GeneralSecurityException, IOException { -// -// java.security.KeyStore ks = KeyStore.generateRsaKeyPair(keystore -// .getLocation().getFile().getPath(), "OpenID Connect Server", -// "test", KeyStore.PASSWORD, KeyStore.PASSWORD, 30, 30); -// -// keystore.setKeystore(ks); -// -// assertThat(ks, not(nullValue())); - assertThat(true, not(false)); + + java.security.KeyStore ks = null; + + try { + ks = generateRsaKeyPair("OpenID Connect Server", "storeKeyPair", "changeit", 30, 365); + + } catch (GeneralSecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + assertThat(ks, not(nullValue())); } @Test public void readKey() throws GeneralSecurityException { -// Key key = keystore.getKeystore().getKey("test", -// KeyStore.PASSWORD.toCharArray()); -// -// System.out.println("-----BEGIN PRIVATE KEY-----"); -// System.out -// .println(new sun.misc.BASE64Encoder().encode(key.getEncoded())); -// System.out.println("-----END PRIVATE KEY-----"); -// -// assertThat(key, not(nullValue())); + Key key = keystore.getKeystore().getKey("storeKeyPair", + KeyStore.PASSWORD.toCharArray()); + + System.out.println("-----BEGIN PRIVATE KEY-----"); + System.out + .println(new sun.misc.BASE64Encoder().encode(key.getEncoded())); + System.out.println("-----END PRIVATE KEY-----"); + + assertThat(key, not(nullValue())); assertThat(true, not(false)); } } From 513145f16fd45bc33b37fe7ec3d37aa7deb3449c Mon Sep 17 00:00:00 2001 From: nemonik Date: Wed, 15 Feb 2012 17:35:18 -0500 Subject: [PATCH 3/7] refactored previously commented out unit tests, cleaned up code, service now returns only unique publickeys --- .../org/mitre/jwt/signer/impl/RsaSigner.java | 52 ++++--- ...JwtSigningAndValidationServiceDefault.java | 78 +++++----- .../jwt/signer/service/impl/KeyStore.java | 8 +- server/src/main/resources/keystore.jks | Bin 2196 -> 2195 bytes .../src/test/java/org/mitre/jwt/JwtTest.java | 136 ++++++++---------- .../jwt/signer/service/impl/KeyStoreTest.java | 23 ++- server/src/test/resources/keystore.jks | Bin 2196 -> 2195 bytes 7 files changed, 148 insertions(+), 149 deletions(-) diff --git a/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java b/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java index c697db8ab..96f4e2e88 100644 --- a/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java +++ b/server/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java @@ -4,6 +4,7 @@ import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; @@ -83,19 +84,14 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { private static Log logger = LogFactory.getLog(RsaSigner.class); - public static final String PROVIDER = "BC"; public static final String DEFAULT_PASSWORD = "changeit"; -// static { -// Security.addProvider(new BouncyCastleProvider()); -// } - private KeyStore keystore; private String alias; private String password; - private RSAPrivateKey privateKey; - private RSAPublicKey publicKey; + private PrivateKey privateKey; + private PublicKey publicKey; private Signature signer; /** @@ -113,7 +109,7 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { public RsaSigner(String algorithmName, KeyStore keystore, String alias) { this(algorithmName, keystore, alias, DEFAULT_PASSWORD); } - + /** * @param algorithmName * @param keystore @@ -136,14 +132,23 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { } } + /** + * Default constructor + */ + public RsaSigner(String algorithmName, RSAPublicKey publicKey, RSAPrivateKey privateKey) { + super(algorithmName); + this.publicKey = publicKey; + this.privateKey = privateKey; + } + @Override public void afterPropertiesSet() throws Exception { KeyPair keyPair = keystore.getKeyPairForAlias(alias, password); - publicKey = ((RSAPublicKey) keyPair.getPublic()); - privateKey = (RSAPrivateKey) keyPair.getPrivate(); + publicKey = keyPair.getPublic(); + privateKey = keyPair.getPrivate(); - logger.debug("RSA Signer ready for business"); + logger.debug( Algorithm.getByName(getAlgorithm()).getStandardName() + " RSA Signer ready for business"); } @@ -152,15 +157,17 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { */ @Override protected String generateSignature(String signatureBase) { - + try { signer.initSign(privateKey); signer.update(signatureBase.getBytes("UTF-8")); } catch (GeneralSecurityException e) { + System.out.println("boooom 1"); // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block + System.out.println("boooom 2"); e.printStackTrace(); } @@ -176,7 +183,7 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { // TODO Auto-generated catch block e.printStackTrace(); } - + return sig; } @@ -192,6 +199,10 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { return password; } + public PrivateKey getPrivateKey() { + return privateKey; + } + public PublicKey getPublicKey() { return publicKey; } @@ -208,6 +219,10 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { this.password = password; } + public void setPrivateKey(RSAPrivateKey privateKey) { + this.privateKey = privateKey; + } + /* * (non-Javadoc) * @@ -220,6 +235,9 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { + ", publicKey=" + publicKey + ", signer=" + signer + "]"; } + /* (non-Javadoc) + * @see org.mitre.jwt.signer.AbstractJwtSigner#verify(java.lang.String) + */ @Override public boolean verify(String jwtString) { @@ -251,12 +269,4 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean { return true; } - - public RSAPrivateKey getPrivateKey() { - return privateKey; - } - - public void setPrivateKey(RSAPrivateKey privateKey) { - this.privateKey = privateKey; - } } diff --git a/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java b/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java index 50723a51a..9af5f71c8 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java @@ -1,8 +1,11 @@ package org.mitre.jwt.signer.service.impl; import java.security.PublicKey; +import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -23,31 +26,35 @@ public class JwtSigningAndValidationServiceDefault implements /** * default constructor - */ - public JwtSigningAndValidationServiceDefault() { + */ + public JwtSigningAndValidationServiceDefault() { } /** * Create JwtSigningAndValidationServiceDefault * - * @param signer List of JwtSigners to associate with this service + * @param signer + * List of JwtSigners to associate with this service */ - public JwtSigningAndValidationServiceDefault(List signer) { + public JwtSigningAndValidationServiceDefault( + List signer) { setSigners(signer); } - - - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + + /* + * (non-Javadoc) + * + * @see + * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override public void afterPropertiesSet() throws Exception { // used for debugging... if (!signers.isEmpty()) { - logger.info(this.toString()); + logger.info(this.toString()); } - - logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JwtSigningAndValidationServiceDefault is open for business"); + + logger.info("JwtSigningAndValidationServiceDefault is open for business"); } /* @@ -59,30 +66,31 @@ public class JwtSigningAndValidationServiceDefault implements */ @Override public List getAllPublicKeys() { - // TODO Iterate through the signers, gather up, and return all the PublicKeys - - List publicKeys = new ArrayList(); - PublicKey publicKey; - - for (JwtSigner signer: signers) { - + + Map map = new HashMap(); + + PublicKey publicKey; + + for (JwtSigner signer : signers) { + if (signer instanceof RsaSigner) { - + publicKey = ((RsaSigner) signer).getPublicKey(); - + if (publicKey != null) - publicKeys.add(((RsaSigner) signer).getPublicKey()); - + map.put(((RSAPublicKey) publicKey).getModulus() + .toString(16).toUpperCase() + + ((RSAPublicKey) publicKey).getPublicExponent() + .toString(16).toUpperCase(), publicKey); + } else if (signer instanceof EcdsaSigner) { - - publicKey = ((EcdsaSigner) signer).getPublicKey(); - - if (publicKey != null) - publicKeys.add(publicKey); + + // TODO } } - - return publicKeys; + + return new ArrayList(map.values()); + } /** @@ -106,7 +114,7 @@ public class JwtSigningAndValidationServiceDefault implements // TODO Auto-generated method stub return false; } - + /** * Set the JwtSigners associated with this service * @@ -132,14 +140,14 @@ public class JwtSigningAndValidationServiceDefault implements */ @Override public boolean validateIssuedJwt(Jwt jwt) { - + // TODO Verify this is correct... - for (JwtSigner signer: signers) { + for (JwtSigner signer : signers) { if (signer.verify(jwt.toString())) return true; } - + return false; } @@ -153,11 +161,11 @@ public class JwtSigningAndValidationServiceDefault implements @Override public boolean validateSignature(String jwtString) { - for (JwtSigner signer: signers) { + for (JwtSigner signer : signers) { if (signer.verify(jwtString)) return true; } - + return false; } } diff --git a/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java b/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java index a9341d634..2f5ddcdaf 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/impl/KeyStore.java @@ -1,8 +1,5 @@ package org.mitre.jwt.signer.service.impl; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.Key; @@ -10,7 +7,6 @@ import java.security.KeyPair; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; -import java.security.interfaces.RSAPrivateKey; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -107,8 +103,8 @@ public class KeyStore implements InitializingBean { // Get public key PublicKey publicKey = cert.getPublicKey(); - - return new KeyPair(publicKey, (RSAPrivateKey) key); + + return new KeyPair(publicKey, (PrivateKey) key); } return null; diff --git a/server/src/main/resources/keystore.jks b/server/src/main/resources/keystore.jks index bb424e26437aa0e5794c7d7d4610984208822b62..b3f5de2dfa28d87b4ca988023d330580ffe69a4a 100644 GIT binary patch delta 1945 zcmV;K2WI$`5t9*+8h?W&sJj3F1pzRE1pP1$1_~<%0R#am0uccL1pows1nGNY}(R`Ml=54>mK@er%avE@c)8o`h547Jrak7W8}UL4nI!pysl+ zAJaDo5f9KTt8~&2q^2ByFltzOv2g50@Xb17#lcR|3OfQ1d%E3L;yRCRVVjKdzJisF z!gRH=F0_nT>W9WUIGjwOcKJU88b0xIAcQXEi;4w_rf)ydOft3;WObGgh-DjTsn)3lMwKj4RY)v+eUwUUZoX3oI z5V4_G2^?Y{pffMq@fjx&uqlw+W~W$2o^IHt#Yxz47jX>v(r*$E{dXMo0bW39x?&0} zkoR_ROinYLiqk|ko-hr4EPqQ@7Ef{)T6ubOa{qk{P=A0dSUB%5cBO497(Ix$2Lt9X zW$YXF8?zgb)8QxW#G;RuOFO&!5T8a8=f2oR2uTUgpC-%wyu7dLS@>6g+q6!thiS`I zI8cSGsodOZXp;jf&68+k^I8aFH5piXER}pzHmE)0$qvG7==l-FE-Dk&;iM5~lGtQe zqm9JVH-9AXldU^O>;1~uWjEqm4DBQ1ANzA$8qZZYPBWOB)UpjXll4KWEa7{-p)ulF zEp=`t8`Y6@!-RtKgMtE|QYUi;nJ(*+Q0tUd+~nr#o0zs`*OBjUb6C0K-`yd1E6v;W zdWo7RQvj>(!pD&zHUjgX21=B-DQ%A~>J&7Q3x6mbCR=c>;hJj0N#b&hAX0=JV^7hA zP;aGW;3_al>qhM~)`(_mIy4Vp zR%~|Vvuoxc*AihJnE-FIi1(|@SvaNx%D`+B*ImvM9Mx)Ka6pSx)`TVrQGC`*)4mAX zAAeCd&Ive!B%;Up1OT2i9~OW^nY&4Fr<eH;;nMp$Q|FAYm+#qxP?X0R@bFM5kfFUdysEZes^`+w48gg=+} zf^X}-FgC>uu(HZPbAFPB8weR(I3xK8!hcWpq8!NN-R0Bh`N@ZKgDp`*U%6pGCsGH3 z1nkJ(-pF{M^NB^?EIFjozaup-7ga1$&nvaUk-9}RU*b@_;gJt%uKo*$(&0P95OE%t zRiI?iAT zC)r+;RH>cF@gBIK9A_HG-ieGX~x*YT=Y$O`CjX8E((`om;KjMkO*90Y5 zZnGbnDPr~6w_5m-hCdolmqbjNoOw(TE0oE)aeu*Tz$?lQlT)V(C|8UT=sl@YeX$Hy z6i5rqRTH0+;yLtTp8x;=0RRP9E;TSY0009`FoFX~FoFUx0t8PyGK4S<1_>&LNQUQV1#FW?1|WZh^rBctCp2{Vj22jw z_#2Ji*l|)-diGGB&Y3-crDn%+npwMEQC?a5mi^=36I2=1RaOy8B#Vkso~x~Sr%hnL zA#y9{XW{qSJ~YMA#m0QWe9#zE$D#)w1&uQu8j+D(lld@(9#tX)K}Kd$7YThXQ!MiQtemVrLnUPJm{&LNQU8{JLKN*Qcbg>@V5cH6E$-~#{r&v$#2@_e2y&r%CL5RmrW zMeW*dB7c55um#ChktY}fC4BhtLd=&89-8H!YBl-t$e>csHK>mRFAz>cm!m-^Eg#Zj zQ6SL8=;o9Il fwpe^8>+v^lp5p?u7z_-~>tU1ODttWp?l8G)1Xzu8 delta 1946 zcmV;L2W9w^5tI>-8h?KNK>+{&1p+XF1pY7%1_~<%0R#am0uccL1pows1nS-Dxmd*v z3<^JA!ReTak^SQ3_96Y-~k6O1EW6~@RE+N7VNh1C;ON=X(foe z@&S}HN^e|`M(P-Q!rJk7i~&?cz6~bDyHA4$S@p`4SR=f6P$rnAR$bkW5;sp1+BnWx zjGEErTsSJF!xMv4pM@f2qMyjZwipJGJOb4$ zu10pd)hNr5q-L9F4CB<%HzK>yhAl*c2EVz}v?e4TU_xHvVMyt!mkfp#@!$8KVf)^@ z^yAn^AAh@dOT1lwbC+~``9Gm>V;*JK7F=`qoPH94Eo!AS%AWsc=xSB3LXFy$c5DOu zp+tv_ix02x80l?II~FB#xe+yD@zkLj=M`Fr>gZ55wTYix*&yBEliep zdpecs%Mn7&`3H_&ACkH zQh6z2O3I6_sq9^(GzL5vPllj(SLFAdAPoyn{Bm13;YXLS&@D$BRFE_FAo*An``!&^Do{D%B^@96_7922ojK(y@TTB1mY|i6ju2 zvU=_WACpgssHaDv=SYoqVqI~=4s434gcUpsKt*^%yCzUxYNL7qv=PeWEV%QWDKGP_ zUtx{lLu4$3Ur}K_X~w2g#K2c-U5%#5nhkri-dEHM~J!&`o?BrkPT zw~(0SJX~#fg>ePDYzLe{ky1`}1M>5R35#w#6Pc3nuWt+km0Ge4JOoLiAXGtS=6^F% zUlF!;By1NoyG#PQKcJ`I>TuUYUWkIua2_f_83ZpHcmlvazg$FD`1fKY$yelveV7dG zmeSmG>$KgUq%@l%8X9D5LD;B}Zmbp*Pz~4*2w`ni+RkwnO7F_G+-uL%rN{a4NvpWyn}diUS_)sHsXA{F@@ znWE>7IC?dPY-1uPbD+~W`EPz|t2AW|VVJni^*h+tt4)srcrwC=mzbHjdI=v^6xnqK z+5d9{u9y&=acf|kz00966SS~d%IRF3yO)!E3Nic!}F#-fnJ0eXm4F(A+hDe6@ z4FLfQlT8J87BDk0F)%q=7Y#8pFfuVTFf%bRFgaS2PX%m~Mg|~%)Gfu)Jc|M{qx&)X z(Hwm7CW;`MuMwc(k;!8g$)8#vE7)aO`Ll$nBAiBgiR;f&^L{IX7SgSb}k`%LM zof^=&7eM}Pu{iWGyjVWWM7O2NXs;28toRR?d9rg7zK8tQW*&V%Q zhF>OxLWfC92O}vRy)A&xRjiaC)IIP*_Xh;SXLZ31wJ!?9%TFXB@>|qybXt! zv}jR#yUv_{%^_dBx|P-{0rINt2XRbtaA35v_}DZ7D-5JG1JaiI%FLdB(B_BtkG_l( zkMn8E13=yySt;y~E_Dx?*p^lprBZSY*$%XdE(+Xn;p~m`i^CiX0PJ9l1heD~g}dQS zuEtnuRCldtXs}p$Z gg*%o}m_KZfEdQhBvIJde`F8@RPmu%3TLc#b7IrR*WB>pF diff --git a/server/src/test/java/org/mitre/jwt/JwtTest.java b/server/src/test/java/org/mitre/jwt/JwtTest.java index bc8a6481a..5a57c6839 100644 --- a/server/src/test/java/org/mitre/jwt/JwtTest.java +++ b/server/src/test/java/org/mitre/jwt/JwtTest.java @@ -1,6 +1,8 @@ package org.mitre.jwt; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; import java.io.UnsupportedEncodingException; @@ -15,7 +17,6 @@ import org.mitre.jwt.signer.impl.PlaintextSigner; import org.mitre.jwt.signer.impl.RsaSigner; import org.mitre.jwt.signer.service.impl.KeyStore; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -25,35 +26,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; public class JwtTest { @Autowired - @Qualifier("testKeystore") KeyStore keystore; - @Test - public void testToStringPlaintext() { - Jwt jwt = new Jwt(); - jwt.getHeader().setAlgorithm("none"); - jwt.getClaims().setExpiration(new Date(1300819380L * 1000L)); - jwt.getClaims().setIssuer("joe"); - jwt.getClaims().setClaim("http://example.com/is_root", Boolean.TRUE); - - // sign it with a blank signature - JwtSigner signer = new PlaintextSigner(); - signer.sign(jwt); - - /* - * Expected string based on the following structures, serialized exactly as follows and base64 encoded: - * - * header: {"alg":"none"} - * claims: {"exp":1300819380,"iss":"joe","http://example.com/is_root":true} - */ - String expected = "eyJhbGciOiJub25lIn0.eyJleHAiOjEzMDA4MTkzODAsImlzcyI6ImpvZSIsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."; - - String actual = jwt.toString(); - - assertThat(actual, equalTo(expected)); - - } - @Test public void testGenerateHmacSignature() { Jwt jwt = new Jwt(); @@ -94,40 +68,70 @@ public class JwtTest { assertThat(jwt.getSignature(), equalTo(signature)); } - + /** * @throws Exception */ -// @Test -// public void testGenerateRsaSignature() throws Exception { -// -//// java.security.KeyStore ks = KeyStore.generateRsaKeyPair(keystore -//// .getLocation().getFile().getPath(), "OpenID Connect Server", -//// "twentyYears", KeyStore.PASSWORD, KeyStore.PASSWORD, 30, 365*20); -//// -//// keystore.setKeystore(ks); -// -// Jwt jwt = new Jwt(); -// jwt.getHeader().setType("JWT"); -// jwt.getHeader().setAlgorithm("RS256"); -// jwt.getClaims().setExpiration(new Date(1300819380L * 1000L)); -// jwt.getClaims().setIssuer("joe"); -// jwt.getClaims().setClaim("http://example.com/is_root", Boolean.TRUE); -// -// JwtSigner signer = new RsaSigner(RsaSigner.Algorithm.DEFAULT, keystore, "twentyYears"); -// ((RsaSigner) signer).afterPropertiesSet(); -// -// signer.sign(jwt); -// -// String signature = "TW0nOd_vr1rnV7yIS-lIV2-00V_zJMWxzOc3Z7k3gvMO2aIjIGjZ9nByZMI0iL5komMxYXPl_RCkbd9OKiPkk4iK5CDj7Mawbzu95LgEOOqdXO1f7-IqX9dIvJhVXXInLD3RsGvavyheIqNeFEVidLrJo30tBchB_niljEW7VeX8nSZfiCOdbOTW3hu0ycnon7wFpejb-cRP_S0iqGxCgbYXJzqPT192EHmRy_wmFxxIy9Lc84uqNkAZSIn1jVIeAemm22RoWbq0xLVLTRyiZoxJTUzac_VteiSPRNFlUQuOdxqNf0Hxqh_wVfX1mfXUzv0D8vHJVy6aIqTISmn-qg"; -// String expected = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJleHAiOjEzMDA4MTkzODAsImlzcyI6ImpvZSIsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.TW0nOd_vr1rnV7yIS-lIV2-00V_zJMWxzOc3Z7k3gvMO2aIjIGjZ9nByZMI0iL5komMxYXPl_RCkbd9OKiPkk4iK5CDj7Mawbzu95LgEOOqdXO1f7-IqX9dIvJhVXXInLD3RsGvavyheIqNeFEVidLrJo30tBchB_niljEW7VeX8nSZfiCOdbOTW3hu0ycnon7wFpejb-cRP_S0iqGxCgbYXJzqPT192EHmRy_wmFxxIy9Lc84uqNkAZSIn1jVIeAemm22RoWbq0xLVLTRyiZoxJTUzac_VteiSPRNFlUQuOdxqNf0Hxqh_wVfX1mfXUzv0D8vHJVy6aIqTISmn-qg"; -// -// String actual = jwt.toString(); -// -// assertThat(actual, equalTo(expected)); -// assertThat(jwt.getSignature(), equalTo(signature)); -// -// } + /** + * @throws Exception + */ + @Test + public void testGenerateRsaSignature() throws Exception { + + Jwt jwt = new Jwt(); + jwt.getHeader().setType("JWT"); + jwt.getHeader().setAlgorithm("RS256"); + jwt.getClaims().setExpiration(new Date(1300819380L * 1000L)); + jwt.getClaims().setIssuer("joe"); + jwt.getClaims().setClaim("http://example.com/is_root", Boolean.TRUE); + + JwtSigner signer = new RsaSigner(RsaSigner.Algorithm.RS256.toString(), keystore, "test", "changeit"); + ((RsaSigner)signer).afterPropertiesSet(); + + signer.sign(jwt); + + assertThat(jwt.getSignature(), not(nullValue())); + } + + @Test + public void testParse() { + String source = "eyJhbGciOiJub25lIn0.eyJleHAiOjEzMDA4MTkzODAsImlzcyI6ImpvZSIsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."; + + + Jwt jwt = Jwt.parse(source); + + assertThat(jwt.getHeader().getAlgorithm(), equalTo(PlaintextSigner.PLAINTEXT)); + assertThat(jwt.getClaims().getIssuer(), equalTo("joe")); + assertThat(jwt.getClaims().getExpiration(), equalTo(new Date(1300819380L * 1000L))); + assertThat((Boolean)jwt.getClaims().getClaim("http://example.com/is_root"), equalTo(Boolean.TRUE)); + + } + + @Test + public void testToStringPlaintext() { + Jwt jwt = new Jwt(); + jwt.getHeader().setAlgorithm("none"); + jwt.getClaims().setExpiration(new Date(1300819380L * 1000L)); + jwt.getClaims().setIssuer("joe"); + jwt.getClaims().setClaim("http://example.com/is_root", Boolean.TRUE); + + // sign it with a blank signature + JwtSigner signer = new PlaintextSigner(); + signer.sign(jwt); + + /* + * Expected string based on the following structures, serialized exactly as follows and base64 encoded: + * + * header: {"alg":"none"} + * claims: {"exp":1300819380,"iss":"joe","http://example.com/is_root":true} + */ + String expected = "eyJhbGciOiJub25lIn0.eyJleHAiOjEzMDA4MTkzODAsImlzcyI6ImpvZSIsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."; + + String actual = jwt.toString(); + + assertThat(actual, equalTo(expected)); + + } @Test public void testValidateHmacSignature() { @@ -158,19 +162,5 @@ public class JwtTest { assertThat(valid, equalTo(Boolean.TRUE)); } - - @Test - public void testParse() { - String source = "eyJhbGciOiJub25lIn0.eyJleHAiOjEzMDA4MTkzODAsImlzcyI6ImpvZSIsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."; - - - Jwt jwt = Jwt.parse(source); - - assertThat(jwt.getHeader().getAlgorithm(), equalTo(PlaintextSigner.PLAINTEXT)); - assertThat(jwt.getClaims().getIssuer(), equalTo("joe")); - assertThat(jwt.getClaims().getExpiration(), equalTo(new Date(1300819380L * 1000L))); - assertThat((Boolean)jwt.getClaims().getClaim("http://example.com/is_root"), equalTo(Boolean.TRUE)); - - } } diff --git a/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java b/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java index 8a3e39d65..1aa39a18d 100644 --- a/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java +++ b/server/src/test/java/org/mitre/jwt/signer/service/impl/KeyStoreTest.java @@ -25,7 +25,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -@SuppressWarnings({ "restriction", "deprecation" }) // I know... +@SuppressWarnings("deprecation") @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-context.xml" }) @@ -36,7 +36,7 @@ public class KeyStoreTest { KeyStore keystore; static { - // Need to create the certificate + // Needed to create the certificate Security.addProvider(new BouncyCastleProvider()); } @@ -48,7 +48,7 @@ public class KeyStoreTest { * @param daysNotValidAfter * @return */ - private X509V3CertificateGenerator createCertificate( + private static X509V3CertificateGenerator createCertificate( String commonName, int daysNotValidBefore, int daysNotValidAfter) { // BC sez X509V3CertificateGenerator is deprecated and the docs say to // use another, but it seemingly isn't included jar... @@ -81,7 +81,7 @@ public class KeyStoreTest { * @throws GeneralSecurityException * @throws IOException */ - public java.security.KeyStore generateRsaKeyPair( + public static java.security.KeyStore generateRsaKeyPair(KeyStore keystore, String domainName, String alias, String aliasPassword, int daysNotValidBefore, int daysNotValidAfter) throws GeneralSecurityException, IOException { @@ -117,13 +117,14 @@ public class KeyStoreTest { return ks; } + @Test public void storeKeyPair() throws GeneralSecurityException, IOException { java.security.KeyStore ks = null; try { - ks = generateRsaKeyPair("OpenID Connect Server", "storeKeyPair", "changeit", 30, 365); + ks = KeyStoreTest.generateRsaKeyPair(keystore, "OpenID Connect Server", "storeKeyPair", "changeit", 30, 365); } catch (GeneralSecurityException e) { // TODO Auto-generated catch block @@ -135,19 +136,13 @@ public class KeyStoreTest { assertThat(ks, not(nullValue())); } - + @Test public void readKey() throws GeneralSecurityException { - + Key key = keystore.getKeystore().getKey("storeKeyPair", KeyStore.PASSWORD.toCharArray()); - - System.out.println("-----BEGIN PRIVATE KEY-----"); - System.out - .println(new sun.misc.BASE64Encoder().encode(key.getEncoded())); - System.out.println("-----END PRIVATE KEY-----"); - + assertThat(key, not(nullValue())); - assertThat(true, not(false)); } } diff --git a/server/src/test/resources/keystore.jks b/server/src/test/resources/keystore.jks index bb424e26437aa0e5794c7d7d4610984208822b62..b3f5de2dfa28d87b4ca988023d330580ffe69a4a 100644 GIT binary patch delta 1945 zcmV;K2WI$`5t9*+8h?W&sJj3F1pzRE1pP1$1_~<%0R#am0uccL1pows1nGNY}(R`Ml=54>mK@er%avE@c)8o`h547Jrak7W8}UL4nI!pysl+ zAJaDo5f9KTt8~&2q^2ByFltzOv2g50@Xb17#lcR|3OfQ1d%E3L;yRCRVVjKdzJisF z!gRH=F0_nT>W9WUIGjwOcKJU88b0xIAcQXEi;4w_rf)ydOft3;WObGgh-DjTsn)3lMwKj4RY)v+eUwUUZoX3oI z5V4_G2^?Y{pffMq@fjx&uqlw+W~W$2o^IHt#Yxz47jX>v(r*$E{dXMo0bW39x?&0} zkoR_ROinYLiqk|ko-hr4EPqQ@7Ef{)T6ubOa{qk{P=A0dSUB%5cBO497(Ix$2Lt9X zW$YXF8?zgb)8QxW#G;RuOFO&!5T8a8=f2oR2uTUgpC-%wyu7dLS@>6g+q6!thiS`I zI8cSGsodOZXp;jf&68+k^I8aFH5piXER}pzHmE)0$qvG7==l-FE-Dk&;iM5~lGtQe zqm9JVH-9AXldU^O>;1~uWjEqm4DBQ1ANzA$8qZZYPBWOB)UpjXll4KWEa7{-p)ulF zEp=`t8`Y6@!-RtKgMtE|QYUi;nJ(*+Q0tUd+~nr#o0zs`*OBjUb6C0K-`yd1E6v;W zdWo7RQvj>(!pD&zHUjgX21=B-DQ%A~>J&7Q3x6mbCR=c>;hJj0N#b&hAX0=JV^7hA zP;aGW;3_al>qhM~)`(_mIy4Vp zR%~|Vvuoxc*AihJnE-FIi1(|@SvaNx%D`+B*ImvM9Mx)Ka6pSx)`TVrQGC`*)4mAX zAAeCd&Ive!B%;Up1OT2i9~OW^nY&4Fr<eH;;nMp$Q|FAYm+#qxP?X0R@bFM5kfFUdysEZes^`+w48gg=+} zf^X}-FgC>uu(HZPbAFPB8weR(I3xK8!hcWpq8!NN-R0Bh`N@ZKgDp`*U%6pGCsGH3 z1nkJ(-pF{M^NB^?EIFjozaup-7ga1$&nvaUk-9}RU*b@_;gJt%uKo*$(&0P95OE%t zRiI?iAT zC)r+;RH>cF@gBIK9A_HG-ieGX~x*YT=Y$O`CjX8E((`om;KjMkO*90Y5 zZnGbnDPr~6w_5m-hCdolmqbjNoOw(TE0oE)aeu*Tz$?lQlT)V(C|8UT=sl@YeX$Hy z6i5rqRTH0+;yLtTp8x;=0RRP9E;TSY0009`FoFX~FoFUx0t8PyGK4S<1_>&LNQUQV1#FW?1|WZh^rBctCp2{Vj22jw z_#2Ji*l|)-diGGB&Y3-crDn%+npwMEQC?a5mi^=36I2=1RaOy8B#Vkso~x~Sr%hnL zA#y9{XW{qSJ~YMA#m0QWe9#zE$D#)w1&uQu8j+D(lld@(9#tX)K}Kd$7YThXQ!MiQtemVrLnUPJm{&LNQU8{JLKN*Qcbg>@V5cH6E$-~#{r&v$#2@_e2y&r%CL5RmrW zMeW*dB7c55um#ChktY}fC4BhtLd=&89-8H!YBl-t$e>csHK>mRFAz>cm!m-^Eg#Zj zQ6SL8=;o9Il fwpe^8>+v^lp5p?u7z_-~>tU1ODttWp?l8G)1Xzu8 delta 1946 zcmV;L2W9w^5tI>-8h?KNK>+{&1p+XF1pY7%1_~<%0R#am0uccL1pows1nS-Dxmd*v z3<^JA!ReTak^SQ3_96Y-~k6O1EW6~@RE+N7VNh1C;ON=X(foe z@&S}HN^e|`M(P-Q!rJk7i~&?cz6~bDyHA4$S@p`4SR=f6P$rnAR$bkW5;sp1+BnWx zjGEErTsSJF!xMv4pM@f2qMyjZwipJGJOb4$ zu10pd)hNr5q-L9F4CB<%HzK>yhAl*c2EVz}v?e4TU_xHvVMyt!mkfp#@!$8KVf)^@ z^yAn^AAh@dOT1lwbC+~``9Gm>V;*JK7F=`qoPH94Eo!AS%AWsc=xSB3LXFy$c5DOu zp+tv_ix02x80l?II~FB#xe+yD@zkLj=M`Fr>gZ55wTYix*&yBEliep zdpecs%Mn7&`3H_&ACkH zQh6z2O3I6_sq9^(GzL5vPllj(SLFAdAPoyn{Bm13;YXLS&@D$BRFE_FAo*An``!&^Do{D%B^@96_7922ojK(y@TTB1mY|i6ju2 zvU=_WACpgssHaDv=SYoqVqI~=4s434gcUpsKt*^%yCzUxYNL7qv=PeWEV%QWDKGP_ zUtx{lLu4$3Ur}K_X~w2g#K2c-U5%#5nhkri-dEHM~J!&`o?BrkPT zw~(0SJX~#fg>ePDYzLe{ky1`}1M>5R35#w#6Pc3nuWt+km0Ge4JOoLiAXGtS=6^F% zUlF!;By1NoyG#PQKcJ`I>TuUYUWkIua2_f_83ZpHcmlvazg$FD`1fKY$yelveV7dG zmeSmG>$KgUq%@l%8X9D5LD;B}Zmbp*Pz~4*2w`ni+RkwnO7F_G+-uL%rN{a4NvpWyn}diUS_)sHsXA{F@@ znWE>7IC?dPY-1uPbD+~W`EPz|t2AW|VVJni^*h+tt4)srcrwC=mzbHjdI=v^6xnqK z+5d9{u9y&=acf|kz00966SS~d%IRF3yO)!E3Nic!}F#-fnJ0eXm4F(A+hDe6@ z4FLfQlT8J87BDk0F)%q=7Y#8pFfuVTFf%bRFgaS2PX%m~Mg|~%)Gfu)Jc|M{qx&)X z(Hwm7CW;`MuMwc(k;!8g$)8#vE7)aO`Ll$nBAiBgiR;f&^L{IX7SgSb}k`%LM zof^=&7eM}Pu{iWGyjVWWM7O2NXs;28toRR?d9rg7zK8tQW*&V%Q zhF>OxLWfC92O}vRy)A&xRjiaC)IIP*_Xh;SXLZ31wJ!?9%TFXB@>|qybXt! zv}jR#yUv_{%^_dBx|P-{0rINt2XRbtaA35v_}DZ7D-5JG1JaiI%FLdB(B_BtkG_l( zkMn8E13=yySt;y~E_Dx?*p^lprBZSY*$%XdE(+Xn;p~m`i^CiX0PJ9l1heD~g}dQS zuEtnuRCldtXs}p$Z gg*%o}m_KZfEdQhBvIJde`F8@RPmu%3TLc#b7IrR*WB>pF From e848f1d77b4d587ea181aad0f68d835821078581 Mon Sep 17 00:00:00 2001 From: nemonik Date: Wed, 15 Feb 2012 18:20:03 -0500 Subject: [PATCH 4/7] modified custom name space schema to follow versioning convention. this doesn't fix the little red X's in STS --- .../main/resources/META-INF/spring.schemas | 3 +- .../signer/service/impl/jwt-signer-1.0.xsd | 96 +++++++++++++++++++ .../WEB-INF/spring/application-context.xml | 2 +- server/src/test/resources/test-context.xml | 2 +- 4 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd diff --git a/server/src/main/resources/META-INF/spring.schemas b/server/src/main/resources/META-INF/spring.schemas index 144fa3f73..4c1b8a1de 100644 --- a/server/src/main/resources/META-INF/spring.schemas +++ b/server/src/main/resources/META-INF/spring.schemas @@ -1 +1,2 @@ -http\://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer.xsd=org/mitre/jwt/signer/service/impl/jwt-signer.xsd \ No newline at end of file +http\://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer-1.0.xsd=org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd +http\://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer.xsd=org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd \ No newline at end of file diff --git a/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd b/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd new file mode 100644 index 000000000..81b06f12c --- /dev/null +++ b/server/src/main/resources/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd @@ -0,0 +1,96 @@ + + + + + + + + + + Describes the JCE KeyStore necessary for certain + signers. + + + + + + + + + + + + + + + + + + Configures the signer service with these signers. + + + + + + + + + + + Configures an RSA signer. + + + + + + + + The reference to the bean that defines the + KeyStore. + + + + + + + The alias to the KeyPair to use for + signing/verifying. + + + + + + + The password to the KeyPair to use for + signing/verifying. + + + + + + + + + Configures an HMAC signer. + + + + + + + + The passphrase used for signing/verifying. + + + + + + + + + + + \ No newline at end of file diff --git a/server/src/main/webapp/WEB-INF/spring/application-context.xml b/server/src/main/webapp/WEB-INF/spring/application-context.xml index bbdc71b2f..e00e610a6 100644 --- a/server/src/main/webapp/WEB-INF/spring/application-context.xml +++ b/server/src/main/webapp/WEB-INF/spring/application-context.xml @@ -11,7 +11,7 @@ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.mitre.org/schema/openid-connect/jwt-signer classpath:/org/mitre/jwt/signer/service/impl/jwt-signer.xsd + http://www.mitre.org/schema/openid-connect/jwt-signer classpath:/org/mitre/jwt/signer/service/impl/jwt-signer-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> diff --git a/server/src/test/resources/test-context.xml b/server/src/test/resources/test-context.xml index fcd72a9b5..2f32e8191 100644 --- a/server/src/test/resources/test-context.xml +++ b/server/src/test/resources/test-context.xml @@ -4,7 +4,7 @@ xmlns:jwt-signer="http://www.mitre.org/schema/openid-connect/jwt-signer" xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.mitre.org/schema/openid-connect/jwt-signer http://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer.xsd" > + http://www.mitre.org/schema/openid-connect/jwt-signer http://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer-1.0.xsd" > From 9bff618481f24a92fba0ee843c621a84a2024e3a Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 16 Feb 2012 09:34:16 -0500 Subject: [PATCH 5/7] fixed appcontext entry, needs a change in eclipse XML Catalog config to work --- server/src/main/webapp/WEB-INF/spring/application-context.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/webapp/WEB-INF/spring/application-context.xml b/server/src/main/webapp/WEB-INF/spring/application-context.xml index bbdc71b2f..13500608e 100644 --- a/server/src/main/webapp/WEB-INF/spring/application-context.xml +++ b/server/src/main/webapp/WEB-INF/spring/application-context.xml @@ -11,7 +11,7 @@ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.mitre.org/schema/openid-connect/jwt-signer classpath:/org/mitre/jwt/signer/service/impl/jwt-signer.xsd + http://www.mitre.org/schema/openid-connect/jwt-signer http://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> From e8de5b4a8fecdcc16c4d4a58dac35f8439af7bb9 Mon Sep 17 00:00:00 2001 From: Michael Jett Date: Thu, 16 Feb 2012 14:50:37 -0500 Subject: [PATCH 6/7] Placeholder for static resources --- server/src/main/webapp/WEB-INF/resources/static_resources_go_here | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 server/src/main/webapp/WEB-INF/resources/static_resources_go_here diff --git a/server/src/main/webapp/WEB-INF/resources/static_resources_go_here b/server/src/main/webapp/WEB-INF/resources/static_resources_go_here new file mode 100644 index 000000000..e69de29bb From 95be182866c72de84ec907b1394cfcffbb95e0d2 Mon Sep 17 00:00:00 2001 From: nemonik Date: Thu, 16 Feb 2012 15:34:18 -0500 Subject: [PATCH 7/7] introduced Utility class to gether static methods; modified jwt signing and validation service interface, imps, and endpoint using; ... --- .../JwtSigningAndValidationService.java | 6 ++-- ...JwtSigningAndValidationServiceDefault.java | 30 +++++++++++------- .../openid/connect/web/CheckIDEndpoint.java | 9 +++--- .../swd/web/SimpleWebDiscoveryEndpoint.java | 20 ++---------- .../src/main/java/org/mitre/util/Utility.java | 31 +++++++++++++++++++ .../WEB-INF/spring/application-context.xml | 4 ++- .../src/test/java/org/mitre/jwt/JwtTest.java | 3 +- 7 files changed, 66 insertions(+), 37 deletions(-) create mode 100644 server/src/main/java/org/mitre/util/Utility.java diff --git a/server/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java b/server/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java index 6060bac53..cb0bb8f1e 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java @@ -30,9 +30,11 @@ public interface JwtSigningAndValidationService { * * @param jwt * the JWT to check the issuer of - * @return true if the JWT was issued by this AS, false if not + * @param expectedIssuer + * the expected issuer + * @return true if the JWT was issued by this expected issuer, false if not */ - public boolean validateIssuedJwt(Jwt jwt); + public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer); /** * Checks the signature of the given JWT against all configured signers, diff --git a/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java b/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java index 9af5f71c8..4168a8f00 100644 --- a/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java +++ b/server/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java @@ -3,6 +3,7 @@ package org.mitre.jwt.signer.service.impl; import java.security.PublicKey; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -19,6 +20,7 @@ import org.springframework.beans.factory.InitializingBean; public class JwtSigningAndValidationServiceDefault implements JwtSigningAndValidationService, InitializingBean { + private List signers = new ArrayList(); private static Log logger = LogFactory @@ -40,7 +42,7 @@ public class JwtSigningAndValidationServiceDefault implements List signer) { setSigners(signer); } - + /* * (non-Javadoc) * @@ -55,6 +57,7 @@ public class JwtSigningAndValidationServiceDefault implements } logger.info("JwtSigningAndValidationServiceDefault is open for business"); + } /* @@ -111,8 +114,14 @@ public class JwtSigningAndValidationServiceDefault implements */ @Override public boolean isJwtExpired(Jwt jwt) { - // TODO Auto-generated method stub - return false; + + Date expiration = jwt.getClaims().getExpiration(); + + if (expiration != null) + return new Date().after(expiration); + else + return false; + } /** @@ -125,6 +134,9 @@ public class JwtSigningAndValidationServiceDefault implements this.signers = signers; } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return "JwtSigningAndValidationServiceDefault [signers=" + signers @@ -139,15 +151,11 @@ public class JwtSigningAndValidationServiceDefault implements * (org.mitre.jwt.model.Jwt) */ @Override - public boolean validateIssuedJwt(Jwt jwt) { - - // TODO Verify this is correct... - - for (JwtSigner signer : signers) { - if (signer.verify(jwt.toString())) - return true; - } + public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) { + if (jwt.getClaims().getIssuer() == expectedIssuer) + return true; + return false; } diff --git a/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java b/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java index 182a62b22..15859f91f 100644 --- a/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java +++ b/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java @@ -1,11 +1,13 @@ package org.mitre.openid.connect.web; +import javax.servlet.http.HttpServletRequest; + import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.mitre.openid.connect.exception.ExpiredTokenException; import org.mitre.openid.connect.exception.InvalidJwtIssuerException; import org.mitre.openid.connect.exception.InvalidJwtSignatureException; import org.mitre.openid.connect.model.IdToken; -import org.mitre.openid.connect.model.IdTokenClaims; +import org.mitre.util.Utility; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,9 +20,8 @@ public class CheckIDEndpoint { @Autowired JwtSigningAndValidationService jwtSignerService; - @RequestMapping("/checkid") - public ModelAndView checkID(@RequestParam("id_token") String tokenString, ModelAndView mav) { + public ModelAndView checkID(@RequestParam("id_token") String tokenString, ModelAndView mav, HttpServletRequest request) { if (!jwtSignerService.validateSignature(tokenString)) { // can't validate @@ -37,7 +38,7 @@ public class CheckIDEndpoint { } // check the issuer (sanity check) - if (!jwtSignerService.validateIssuedJwt(token)) { + if (!jwtSignerService.validateIssuedJwt(token, Utility.findBaseUrl(request))) { throw new InvalidJwtIssuerException(); // TODO: create a view for this exception } diff --git a/server/src/main/java/org/mitre/swd/web/SimpleWebDiscoveryEndpoint.java b/server/src/main/java/org/mitre/swd/web/SimpleWebDiscoveryEndpoint.java index d70be0e9d..273c64762 100644 --- a/server/src/main/java/org/mitre/swd/web/SimpleWebDiscoveryEndpoint.java +++ b/server/src/main/java/org/mitre/swd/web/SimpleWebDiscoveryEndpoint.java @@ -3,17 +3,15 @@ package org.mitre.swd.web; import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; +import org.mitre.util.Utility; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; @Controller public class SimpleWebDiscoveryEndpoint { @@ -22,7 +20,7 @@ public class SimpleWebDiscoveryEndpoint { params={"principal", "service=http://openid.net/specs/connect/1.0/issuer"}) public ModelAndView openIdConnectIssuerDiscovery(@RequestParam("principal") String principal, ModelAndView modelAndView, HttpServletRequest request) { - String baseUrl = findBaseUrl(request); + String baseUrl = Utility.findBaseUrl(request); // look up user, see if they're local // if so, return this server @@ -42,7 +40,7 @@ public class SimpleWebDiscoveryEndpoint { @RequestMapping("/.well-known/openid-configuration") public ModelAndView providerConfiguration(ModelAndView modelAndView, HttpServletRequest request) { - String baseUrl = findBaseUrl(request); + String baseUrl = Utility.findBaseUrl(request); /* * version string Version of the provider response. "3.0" is the default. @@ -90,17 +88,5 @@ public class SimpleWebDiscoveryEndpoint { return modelAndView; } - - - private String findBaseUrl(HttpServletRequest request) { - String baseUrl = String.format("%s://%s%s", request.getScheme(), request.getServerName(), request.getContextPath()); - - if ((request.getScheme().equals("http") && request.getServerPort() != 80) - || (request.getScheme().equals("https") && request.getServerPort() != 443)) { - // nonstandard port, need to include it - baseUrl = String.format("%s://%s:%d%s", request.getScheme(), request.getServerName(), request.getServerPort(), request.getContextPath()); - } - return baseUrl; - } } diff --git a/server/src/main/java/org/mitre/util/Utility.java b/server/src/main/java/org/mitre/util/Utility.java new file mode 100644 index 000000000..8799c3cb9 --- /dev/null +++ b/server/src/main/java/org/mitre/util/Utility.java @@ -0,0 +1,31 @@ +package org.mitre.util; + +import javax.servlet.http.HttpServletRequest; + +/** + * A collection of utility methods. + * + */ +public class Utility { + + /** + * Returns the base URL from a HttpServletRequest + * + * @param request + * @return + */ + public static String findBaseUrl(HttpServletRequest request) { + String issuer = String.format("%s://%s%s", request.getScheme(), + request.getServerName(), request.getContextPath()); + + if ((request.getScheme().equals("http") && request.getServerPort() != 80) + || (request.getScheme().equals("https") && request + .getServerPort() != 443)) { + // nonstandard port, need to include it + issuer = String.format("%s://%s:%d%s", request.getScheme(), + request.getServerName(), request.getServerPort(), + request.getContextPath()); + } + return issuer; + } +} diff --git a/server/src/main/webapp/WEB-INF/spring/application-context.xml b/server/src/main/webapp/WEB-INF/spring/application-context.xml index 13500608e..f49e60b56 100644 --- a/server/src/main/webapp/WEB-INF/spring/application-context.xml +++ b/server/src/main/webapp/WEB-INF/spring/application-context.xml @@ -11,7 +11,7 @@ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.mitre.org/schema/openid-connect/jwt-signer http://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer.xsd + http://www.mitre.org/schema/openid-connect/jwt-signer http://www.mitre.org/schema/openid-connect/jwt-signer/jwt-signer-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> @@ -73,6 +73,8 @@ + + diff --git a/server/src/test/java/org/mitre/jwt/JwtTest.java b/server/src/test/java/org/mitre/jwt/JwtTest.java index 5a57c6839..214c7b9f5 100644 --- a/server/src/test/java/org/mitre/jwt/JwtTest.java +++ b/server/src/test/java/org/mitre/jwt/JwtTest.java @@ -158,9 +158,8 @@ public class JwtTest { String jwtString = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjEzMDA4MTkzODAsImlzcyI6ImpvZSIsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.iGBPJj47S5q_HAhSoQqAdcS6A_1CFj3zrLaImqNbt9E"; boolean valid = signer.verify(jwtString); - + assertThat(valid, equalTo(Boolean.TRUE)); } - }