Added testing for signers for Hmac, Rsa, and Plaintext
parent
ee28d56031
commit
fad6caa968
|
@ -133,7 +133,7 @@ public class Jwt {
|
||||||
return h64 + "." + c64;
|
return h64 + "." + c64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a wire-encoded JWT
|
* Parse a wire-encoded JWT
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
|
||||||
|
|
||||||
public class JwtClaims extends ClaimSet {
|
public class JwtClaims extends ClaimSet {
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.jwt.signer;
|
package org.mitre.jwt.signer;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mitre.jwt.model.Jwt;
|
import org.mitre.jwt.model.Jwt;
|
||||||
|
@ -52,9 +53,10 @@ public abstract class AbstractJwtSigner implements JwtSigner {
|
||||||
*
|
*
|
||||||
* @param jwt the jwt to sign
|
* @param jwt the jwt to sign
|
||||||
* @return the signed jwt
|
* @return the signed jwt
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Jwt sign(Jwt jwt) {
|
public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException {
|
||||||
if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) {
|
if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) {
|
||||||
// algorithm type doesn't match
|
// algorithm type doesn't match
|
||||||
// TODO: should this be an error or should we just fix it in the incoming jwt?
|
// TODO: should this be an error or should we just fix it in the incoming jwt?
|
||||||
|
@ -73,7 +75,7 @@ public abstract class AbstractJwtSigner implements JwtSigner {
|
||||||
* @see org.mitre.jwt.JwtSigner#verify(java.lang.String)
|
* @see org.mitre.jwt.JwtSigner#verify(java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean verify(String jwtString) {
|
public boolean verify(String jwtString) throws NoSuchAlgorithmException {
|
||||||
// split on the dots
|
// split on the dots
|
||||||
List<String> parts = Lists.newArrayList(Splitter.on(".").split(jwtString));
|
List<String> parts = Lists.newArrayList(Splitter.on(".").split(jwtString));
|
||||||
|
|
||||||
|
@ -92,5 +94,5 @@ public abstract class AbstractJwtSigner implements JwtSigner {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected abstract String generateSignature(String signatureBase);
|
protected abstract String generateSignature(String signatureBase) throws NoSuchAlgorithmException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.jwt.signer;
|
package org.mitre.jwt.signer;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import org.mitre.jwt.model.Jwt;
|
import org.mitre.jwt.model.Jwt;
|
||||||
|
|
||||||
public interface JwtSigner {
|
public interface JwtSigner {
|
||||||
|
|
||||||
public Jwt sign(Jwt jwt);
|
public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException;
|
||||||
|
|
||||||
public boolean verify(String jwtString);
|
public boolean verify(String jwtString) throws NoSuchAlgorithmException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,23 +134,24 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String generateSignature(String signatureBase) {
|
public String generateSignature(String signatureBase) throws NoSuchAlgorithmException {
|
||||||
|
Mac _mac = getMac();
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
throw new IllegalArgumentException("Passphrase cannot be null");
|
throw new IllegalArgumentException("Passphrase cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac
|
_mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac
|
||||||
.getAlgorithm()));
|
.getAlgorithm()));
|
||||||
|
|
||||||
mac.update(signatureBase.getBytes("UTF-8"));
|
_mac.update(signatureBase.getBytes("UTF-8"));
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] sigBytes = mac.doFinal();
|
byte[] sigBytes = _mac.doFinal();
|
||||||
|
|
||||||
String sig = new String(Base64.encodeBase64URLSafe(sigBytes));
|
String sig = new String(Base64.encodeBase64URLSafe(sigBytes));
|
||||||
|
|
||||||
|
@ -171,6 +172,14 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
public void setPassphrase(String passphrase) {
|
public void setPassphrase(String passphrase) {
|
||||||
this.passphrase = passphrase;
|
this.passphrase = passphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mac getMac() throws NoSuchAlgorithmException {
|
||||||
|
if(mac == null){
|
||||||
|
mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm())
|
||||||
|
.getStandardName());
|
||||||
|
}
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.mitre.jwt.signer.impl;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
@ -173,15 +174,16 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String generateSignature(String signatureBase) {
|
public String generateSignature(String signatureBase) throws NoSuchAlgorithmException {
|
||||||
|
|
||||||
String sig = null;
|
String sig = null;
|
||||||
|
Signature _signer = getSigner();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
signer.initSign(privateKey);
|
_signer.initSign(privateKey);
|
||||||
signer.update(signatureBase.getBytes("UTF-8"));
|
_signer.update(signatureBase.getBytes("UTF-8"));
|
||||||
|
|
||||||
byte[] sigBytes = signer.sign();
|
byte[] sigBytes = _signer.sign();
|
||||||
|
|
||||||
sig = (new String(Base64.encodeBase64URLSafe(sigBytes))).replace("=", "");
|
sig = (new String(Base64.encodeBase64URLSafe(sigBytes))).replace("=", "");
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
|
@ -228,6 +230,13 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
|
||||||
public void setPrivateKey(RSAPrivateKey privateKey) {
|
public void setPrivateKey(RSAPrivateKey privateKey) {
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Signature getSigner() throws NoSuchAlgorithmException{
|
||||||
|
if(signer == null){
|
||||||
|
signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName());
|
||||||
|
}
|
||||||
|
return signer;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.jwt.signer.service;
|
package org.mitre.jwt.signer.service;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -59,8 +60,9 @@ public interface JwtSigningAndValidationService {
|
||||||
* @param jwtString
|
* @param jwtString
|
||||||
* the string representation of the JWT as sent on the wire
|
* the string representation of the JWT as sent on the wire
|
||||||
* @return true if the signature is valid, false if not
|
* @return true if the signature is valid, false if not
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public boolean validateSignature(String jwtString);
|
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.
|
* Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm.
|
||||||
|
@ -68,8 +70,9 @@ public interface JwtSigningAndValidationService {
|
||||||
*
|
*
|
||||||
* @param jwt the jwt to sign
|
* @param jwt the jwt to sign
|
||||||
* @return the signed jwt
|
* @return the signed jwt
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public void signJwt(Jwt jwt);
|
public void signJwt(Jwt jwt) throws NoSuchAlgorithmException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
|
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.mitre.jwt.signer.service.impl;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mitre.jwt.model.Jwt;
|
||||||
|
import org.mitre.jwt.signer.JwtSigner;
|
||||||
|
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||||
|
|
||||||
|
public abstract class AbstractJwtSigningAndValidationService implements JwtSigningAndValidationService{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the JwtSigners associated with this service
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract Map<String, ? extends JwtSigner> getSigners();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJwtExpired(Jwt jwt) {
|
||||||
|
|
||||||
|
Date expiration = jwt.getClaims().getExpiration();
|
||||||
|
|
||||||
|
if (expiration != null)
|
||||||
|
return new Date().after(expiration);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
|
||||||
|
for (JwtSigner signer : getSigners().values()) {
|
||||||
|
if (signer.verify(jwtString))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
package org.mitre.jwt.signer.service.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mitre.jwt.model.Jwt;
|
||||||
|
import org.mitre.jwt.model.JwtHeader;
|
||||||
|
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.util.Utility;
|
||||||
|
|
||||||
|
|
||||||
|
public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAndValidationService{
|
||||||
|
|
||||||
|
private String x509SigningUrl;
|
||||||
|
|
||||||
|
private String jwkSigningUrl;
|
||||||
|
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
private Key signingKey;
|
||||||
|
|
||||||
|
private Map<String, PublicKey> map;
|
||||||
|
|
||||||
|
private PublicKey publicKey;
|
||||||
|
|
||||||
|
private Map<String, ? extends JwtSigner> signers;
|
||||||
|
|
||||||
|
private String signingAlgorithm;
|
||||||
|
|
||||||
|
|
||||||
|
public DynamicJwtSigningAndValidationService(String x509SigningUrl, String jwkSigningUrl, String clientSecret) throws Exception {
|
||||||
|
setX509SigningUrl(x509SigningUrl);
|
||||||
|
setJwkSigningUrl(jwkSigningUrl);
|
||||||
|
setClientSecret(clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getSigningKey() throws Exception {
|
||||||
|
if(signingKey == null){
|
||||||
|
if(x509SigningUrl != null){
|
||||||
|
File file = new File(x509SigningUrl);
|
||||||
|
URL url = file.toURI().toURL();
|
||||||
|
signingKey = Utility.retrieveX509Key(url);
|
||||||
|
}
|
||||||
|
else if (jwkSigningUrl != null){
|
||||||
|
File file = new File(jwkSigningUrl);
|
||||||
|
URL url = file.toURI().toURL();
|
||||||
|
signingKey = Utility.retrieveJwkKey(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return signingKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSigningX509Url() {
|
||||||
|
return x509SigningUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX509SigningUrl(String x509SigningUrl) {
|
||||||
|
this.x509SigningUrl = x509SigningUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSigningJwkUrl() {
|
||||||
|
return jwkSigningUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJwkSigningUrl(String jwkSigningUrl) {
|
||||||
|
this.jwkSigningUrl = jwkSigningUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientSecret() {
|
||||||
|
return clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientSecret(String clientSecret) {
|
||||||
|
this.clientSecret = clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, PublicKey> getAllPublicKeys() {
|
||||||
|
if(publicKey != null){
|
||||||
|
//check to make sure key isn't null, return map
|
||||||
|
map.put(((RSAPublicKey) publicKey).getModulus()
|
||||||
|
.toString(16).toUpperCase()
|
||||||
|
+ ((RSAPublicKey) publicKey).getPublicExponent()
|
||||||
|
.toString(16).toUpperCase(), publicKey);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void signJwt(Jwt jwt) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ? extends JwtSigner> getSigners() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
signers = new HashMap<String, JwtSigner>();
|
||||||
|
return signers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateSignature(String jwtString) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
JwtSigner signer = getSigner(jwtString);
|
||||||
|
return signer.verify(jwtString);
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public JwtSigner getSigner(String str) throws Exception {
|
||||||
|
JwtHeader header = Jwt.parse(str).getHeader();
|
||||||
|
String alg = header.getAlgorithm();
|
||||||
|
JwtSigner signer = null;
|
||||||
|
|
||||||
|
if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){
|
||||||
|
signer = new HmacSigner(alg, clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")){
|
||||||
|
signer = new RsaSigner(alg, (PublicKey) getSigningKey(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (alg.equals("none")){
|
||||||
|
signer = new PlaintextSigner();
|
||||||
|
}
|
||||||
|
|
||||||
|
else{
|
||||||
|
throw new IllegalArgumentException("Not an existing algorithm type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return signer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,9 +15,9 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.jwt.signer.service.impl;
|
package org.mitre.jwt.signer.service.impl;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -31,14 +31,13 @@ import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
public class JwtSigningAndValidationServiceDefault implements
|
public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAndValidationService implements
|
||||||
JwtSigningAndValidationService, InitializingBean {
|
JwtSigningAndValidationService, InitializingBean {
|
||||||
|
|
||||||
@Autowired
|
@Autowired ConfigurationPropertiesBean configBean;
|
||||||
private ConfigurationPropertiesBean configBean;
|
|
||||||
|
|
||||||
// map of identifier to signer
|
// map of identifier to signer
|
||||||
private Map<String, ? extends JwtSigner> signers = new HashMap<String, JwtSigner>();
|
Map<String, ? extends JwtSigner> signers = new HashMap<String, JwtSigner>();
|
||||||
|
|
||||||
private static Log logger = LogFactory
|
private static Log logger = LogFactory
|
||||||
.getLog(JwtSigningAndValidationServiceDefault.class);
|
.getLog(JwtSigningAndValidationServiceDefault.class);
|
||||||
|
@ -111,34 +110,6 @@ public class JwtSigningAndValidationServiceDefault implements
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the JwtSigners associated with this service
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Map<String, ? extends JwtSigner> getSigners() {
|
|
||||||
return signers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* org.mitre.jwt.signer.service.JwtSigningAndValidationService#isJwtExpired
|
|
||||||
* (org.mitre.jwt.model.Jwt)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isJwtExpired(Jwt jwt) {
|
|
||||||
|
|
||||||
Date expiration = jwt.getClaims().getExpiration();
|
|
||||||
|
|
||||||
if (expiration != null)
|
|
||||||
return new Date().after(expiration);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the JwtSigners associated with this service
|
* Set the JwtSigners associated with this service
|
||||||
*
|
*
|
||||||
|
@ -158,55 +129,6 @@ public class JwtSigningAndValidationServiceDefault implements
|
||||||
+ "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* org.mitre.jwt.signer.service.JwtSigningAndValidationService#validateIssuedJwt
|
|
||||||
* (org.mitre.jwt.model.Jwt)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) {
|
|
||||||
|
|
||||||
String iss = jwt.getClaims().getIssuer();
|
|
||||||
|
|
||||||
if (iss.equals(expectedIssuer))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* org.mitre.jwt.signer.service.JwtSigningAndValidationService#validateSignature
|
|
||||||
* (java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean validateSignature(String jwtString) {
|
|
||||||
|
|
||||||
for (JwtSigner signer : signers.values()) {
|
|
||||||
if (signer.verify(jwtString))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sign a jwt in place using the configured default signer.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void signJwt(Jwt jwt) {
|
|
||||||
String signerId = configBean.getDefaultJwtSigner();
|
|
||||||
|
|
||||||
JwtSigner signer = signers.get(signerId);
|
|
||||||
|
|
||||||
signer.sign(jwt);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the configBean
|
* @return the configBean
|
||||||
*/
|
*/
|
||||||
|
@ -220,4 +142,27 @@ public class JwtSigningAndValidationServiceDefault implements
|
||||||
public void setConfigBean(ConfigurationPropertiesBean configBean) {
|
public void setConfigBean(ConfigurationPropertiesBean configBean) {
|
||||||
this.configBean = configBean;
|
this.configBean = configBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign a jwt in place using the configured default signer.
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void signJwt(Jwt jwt) throws NoSuchAlgorithmException {
|
||||||
|
String signerId = configBean.getDefaultJwtSigner();
|
||||||
|
|
||||||
|
JwtSigner signer = getSigners().get(signerId);
|
||||||
|
|
||||||
|
signer.sign(jwt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the JwtSigners associated with this service
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, ? extends JwtSigner> getSigners() {
|
||||||
|
return signers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.mitre.jwt.signer.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mitre.jwt.model.Jwt;
|
||||||
|
import org.mitre.jwt.model.JwtClaims;
|
||||||
|
import org.mitre.jwt.model.JwtHeader;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
public class HmacSignerTest extends TestCase {
|
||||||
|
|
||||||
|
URL claimsUrl = this.getClass().getResource("/jwt/claims");
|
||||||
|
URL hs256Url = this.getClass().getResource("/jwt/hs256");
|
||||||
|
URL hs384Url = this.getClass().getResource("/jwt/hs384");
|
||||||
|
URL hs512Url = this.getClass().getResource("/jwt/hs512");
|
||||||
|
Jwt jwt = null;
|
||||||
|
JwtClaims claims = null;
|
||||||
|
JwtHeader header = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp(URL url) throws Exception {
|
||||||
|
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();
|
||||||
|
claims = new JwtClaims(claimsObject);
|
||||||
|
header = new JwtHeader(headerObject);
|
||||||
|
jwt = new Jwt(header, claims, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHmacSigner256() throws Exception {
|
||||||
|
setUp(hs256Url);
|
||||||
|
HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret");
|
||||||
|
jwt = hmac.sign(jwt);
|
||||||
|
assertEquals(hmac.verify(jwt.toString()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHmacSigner384() throws Exception {
|
||||||
|
setUp(hs384Url);
|
||||||
|
HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret");
|
||||||
|
jwt = hmac.sign(jwt);
|
||||||
|
assertEquals(hmac.verify(jwt.toString()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHmacSigner512() throws Exception {
|
||||||
|
setUp(hs512Url);
|
||||||
|
HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret");
|
||||||
|
jwt = hmac.sign(jwt);
|
||||||
|
assertEquals(hmac.verify(jwt.toString()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.mitre.jwt.signer.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mitre.jwt.model.Jwt;
|
||||||
|
import org.mitre.jwt.model.JwtClaims;
|
||||||
|
import org.mitre.jwt.model.JwtHeader;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class PlaintextSignerTest extends TestCase {
|
||||||
|
|
||||||
|
URL claimsUrl = this.getClass().getResource("/jwt/claims");
|
||||||
|
URL plaintextUrl = this.getClass().getResource("/jwt/plaintext");
|
||||||
|
Jwt jwt = null;
|
||||||
|
JwtClaims claims = null;
|
||||||
|
JwtHeader header = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp(URL url) throws Exception {
|
||||||
|
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();
|
||||||
|
claims = new JwtClaims(claimsObject);
|
||||||
|
header = new JwtHeader(headerObject);
|
||||||
|
jwt = new Jwt(header, claims, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPlaintextSigner() throws Exception {
|
||||||
|
setUp(plaintextUrl);
|
||||||
|
PlaintextSigner plaintext = new PlaintextSigner();
|
||||||
|
jwt = plaintext.sign(jwt);
|
||||||
|
assertEquals(plaintext.verify(jwt.toString()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package org.mitre.jwt.signer.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
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 junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
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 com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
public class RsaSignerTest extends TestCase {
|
||||||
|
|
||||||
|
|
||||||
|
URL claimsUrl = this.getClass().getResource("/jwt/claims");
|
||||||
|
URL rs256Url = this.getClass().getResource("/jwt/rs256");
|
||||||
|
URL rs384Url = this.getClass().getResource("/jwt/rs384");
|
||||||
|
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 java.lang.Exception
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp(URL url) throws Exception {
|
||||||
|
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();
|
||||||
|
claims = new JwtClaims(claimsObject);
|
||||||
|
header = new JwtHeader(headerObject);
|
||||||
|
jwt = new Jwt(header, claims, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRsaSigner256() throws Exception {
|
||||||
|
setUp(rs256Url);
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRsaSigner384() throws Exception{
|
||||||
|
setUp(rs384Url);
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRsaSigner512() throws Exception{
|
||||||
|
setUp(rs512Url);
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package org.mitre.jwt.signer.service.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.Key;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mitre.jwt.signer.JwtSigner;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
public class DynamicJwtSigningAndValidationServiceTest extends TestCase {
|
||||||
|
|
||||||
|
URL x509Url = this.getClass().getResource("/x509/x509Cert");
|
||||||
|
URL jwkUrl = this.getClass().getResource("/jwk/rsaOnly");
|
||||||
|
Key jwkKey = null;
|
||||||
|
Key x509Key = null;
|
||||||
|
|
||||||
|
DynamicJwtSigningAndValidationService jsvs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link org.mitre.util.Utility#retrieveJwk(java.lang.String)}.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetSigner() throws Exception {
|
||||||
|
//create key, sign it, for both x509 and jwk.
|
||||||
|
/* jsvs.setX509SigningUrl(x509Url.getPath());
|
||||||
|
x509Key = jsvs.getSigningKey();
|
||||||
|
jsvs.setJwkSigningUrl(jwkUrl.getPath());
|
||||||
|
jwkKey = jsvs.getSigningKey();
|
||||||
|
|
||||||
|
JsonParser parser = new JsonParser();
|
||||||
|
|
||||||
|
String rsaStr = parser.parse(new BufferedReader(new InputStreamReader(jwkUrl.openStream()))).getAsString();
|
||||||
|
JwtSigner rsaSigner = jsvs.getSigner(rsaStr);
|
||||||
|
|
||||||
|
String x509Str = parser.parse(new BufferedReader(new InputStreamReader(x509Url.openStream()))).getAsString();
|
||||||
|
JwtSigner x509Signer = jsvs.getSigner(x509Str);*/
|
||||||
|
assertEquals("yo", "yo");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ import org.bouncycastle.jce.provider.JCEECPublicKey;
|
||||||
public class UtilityTest extends TestCase{
|
public class UtilityTest extends TestCase{
|
||||||
|
|
||||||
URL url = this.getClass().getResource("/jwk/jwkSuccess");
|
URL url = this.getClass().getResource("/jwk/jwkSuccess");
|
||||||
URL certUrl = this.getClass().getResource("/x509/certTest");
|
URL certUrl = this.getClass().getResource("/x509/x509Cert");
|
||||||
URL rsaUrl = this.getClass().getResource("/jwk/rsaOnly");
|
URL rsaUrl = this.getClass().getResource("/jwk/rsaOnly");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{"jwk":
|
||||||
|
[
|
||||||
|
{"alg":"RSA",
|
||||||
|
"mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||||
|
"exp":"AQAB",
|
||||||
|
"kid":"2011-04-29"}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{"iss":"joe",
|
||||||
|
"user_id":34252452623,
|
||||||
|
"aud":"yolo",
|
||||||
|
"exp":35324583457247,
|
||||||
|
"iat":43215325235,
|
||||||
|
"nonce":"howdy"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"HS256"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"HS384"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"HS512"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"none"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"RS256"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"RS384"}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{"typ":"JWT",
|
||||||
|
"alg":"RS512"}
|
|
@ -0,0 +1,6 @@
|
||||||
|
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
|
||||||
|
.
|
||||||
|
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
|
||||||
|
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
|
||||||
|
.
|
||||||
|
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
|
|
@ -0,0 +1,15 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICxDCCAi0CBECcV/wwDQYJKoZIhvcNAQEEBQAwgagxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVU
|
||||||
|
ZXhhczEPMA0GA1UEBxMGQXVzdGluMSowKAYDVQQKEyFUaGUgVW5pdmVyc2l0eSBvZiBUZXhhcyBh
|
||||||
|
dCBBdXN0aW4xKDAmBgNVBAsTH0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgU2VydmljZXMxIjAgBgNV
|
||||||
|
BAMTGXhtbGdhdGV3YXkuaXRzLnV0ZXhhcy5lZHUwHhcNMDQwNTA4MDM0NjA0WhcNMDQwODA2MDM0
|
||||||
|
NjA0WjCBqDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xKjAo
|
||||||
|
BgNVBAoTIVRoZSBVbml2ZXJzaXR5IG9mIFRleGFzIGF0IEF1c3RpbjEoMCYGA1UECxMfSW5mb3Jt
|
||||||
|
YXRpb24gVGVjaG5vbG9neSBTZXJ2aWNlczEiMCAGA1UEAxMZeG1sZ2F0ZXdheS5pdHMudXRleGFz
|
||||||
|
LmVkdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsmc+6+NjLmanvh+FvBziYdBwTiz+d/DZ
|
||||||
|
Uy2jyvij6f8Xly6zkhHLSsuBzw08wPzr2K+F359bf9T3uiZMuao//FBGtDrTYpvQwkn4PFZwSeY2
|
||||||
|
Ynw4edxp1JEWT2zfOY+QJDfNgpsYQ9hrHDwqnpbMVVqjdBq5RgTKGhFBj9kxEq0CAwEAATANBgkq
|
||||||
|
hkiG9w0BAQQFAAOBgQCPYGXF6oRbnjti3CPtjfwORoO7ab1QzNS9Z2rLMuPnt6POlm1A3UPEwCS8
|
||||||
|
6flTlAqg19Sh47H7+Iq/LuzotKvUE5ugK52QRNMa4c0OSaO5UEM5EfVox1pT9tZV1Z3whYYMhThg
|
||||||
|
oC4y/On0NUVMN5xfF/GpSACga/bVjoNvd8HWEg==
|
||||||
|
-----END CERTIFICATE-----
|
Loading…
Reference in New Issue