placeholder

pull/485/merge
William Kim 2013-08-26 11:33:21 -04:00
parent e0b56bc72a
commit d763a954da
3 changed files with 76 additions and 15 deletions

View File

@ -33,7 +33,7 @@ import com.nimbusds.jose.util.Base64URL;
* @author wkim * @author wkim
* *
*/ */
public class PlainSigner implements JWSSigner { public final class PlainSigner implements JWSSigner {
@Override @Override

View File

@ -28,6 +28,7 @@ import com.nimbusds.jose.PlainHeader;
import com.nimbusds.jose.ReadOnlyJWSHeader; import com.nimbusds.jose.ReadOnlyJWSHeader;
import com.nimbusds.jose.Requirement; import com.nimbusds.jose.Requirement;
import com.nimbusds.jose.util.Base64URL; import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.PlainJWT;
/** /**
* Verifier to support "alg:none" JWS signing option (no signature). * Verifier to support "alg:none" JWS signing option (no signature).
@ -35,7 +36,7 @@ import com.nimbusds.jose.util.Base64URL;
* @author wkim * @author wkim
* *
*/ */
public class PlainVerifier implements JWSVerifier { public final class PlainVerifier implements JWSVerifier {
// the NONE alg constant lives in the Algorithm superclass of JWSAlgorithm, not allowing its use as a JWSAlgorithm object. // the NONE alg constant lives in the Algorithm superclass of JWSAlgorithm, not allowing its use as a JWSAlgorithm object.
// redefining the constant here for convenience. // redefining the constant here for convenience.
@ -77,5 +78,16 @@ public class PlainVerifier implements JWSVerifier {
} }
} }
/**
* Verifies that the third signature component of the JWT is null.
*
* @param jwt
* @return
*/
public static boolean verify(PlainJWT jwt) {
return jwt.getParsedParts()[2] == null;
}
} }

View File

@ -27,6 +27,8 @@ import java.util.Set;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.mitre.jose.keystore.JWKSetKeyStore; import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.signer.PlainSigner;
import org.mitre.jwt.signer.PlainVerifier;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -36,6 +38,7 @@ import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSSigner; import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.PlainHeader;
import com.nimbusds.jose.crypto.MACSigner; import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier; import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jose.crypto.RSASSASigner;
@ -44,10 +47,14 @@ import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.JWK; import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.OctetSequenceKey; import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.PlainJWT;
import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jwt.SignedJWT;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService { public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService {
public static final String ALG_NONE = "none"; // TODO storing a default "alg:none" id smells a bit..
// map of identifier to signer // map of identifier to signer
private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>(); private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
@ -156,6 +163,11 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @throws NoSuchAlgorithmException If there is no appropriate algorithm to tie the keys to. * @throws NoSuchAlgorithmException If there is no appropriate algorithm to tie the keys to.
*/ */
private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, InvalidKeySpecException { private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, InvalidKeySpecException {
signers.put(ALG_NONE, new PlainSigner());
verifiers.put(ALG_NONE, new PlainVerifier());
for (Map.Entry<String, JWK> jwkEntry : keys.entrySet()) { for (Map.Entry<String, JWK> jwkEntry : keys.entrySet()) {
String id = jwkEntry.getKey(); String id = jwkEntry.getKey();
@ -199,7 +211,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* Sign a jwt in place using the configured default signer. * Sign a jwt in place using the configured default signer.
*/ */
@Override @Override
public void signJwt(SignedJWT jwt) { public void signJwt(JWT jwt) {
if (getDefaultSignerKeyId() == null) { if (getDefaultSignerKeyId() == null) {
throw new IllegalStateException("Tried to call default signing with no default signer ID set"); throw new IllegalStateException("Tried to call default signing with no default signer ID set");
} }
@ -207,7 +219,22 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
JWSSigner signer = signers.get(getDefaultSignerKeyId()); JWSSigner signer = signers.get(getDefaultSignerKeyId());
try { try {
jwt.sign(signer);
// the sign() method is not a part of the JWT interface,
// hence this if/else structure.
if (signer instanceof PlainSigner) {
if (!(jwt instanceof PlainJWT)) {
throw new JOSEException("This JWT object is not a plain JWT.");
}
// At this point, this is a plain JWT and is already good-to-go.
} else { // we have a signable JWS at this point.
((SignedJWT) jwt).sign(signer);
}
} catch (JOSEException e) { } catch (JOSEException e) {
logger.error("Failed to sign JWT, error was: ", e); logger.error("Failed to sign JWT, error was: ", e);
@ -216,7 +243,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
} }
@Override @Override
public void signJwt(SignedJWT jwt, JWSAlgorithm alg) { public void signJwt(JWT jwt, JWSAlgorithm alg) {
JWSSigner signer = null; JWSSigner signer = null;
@ -227,23 +254,43 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
} }
} }
if (signer == null) {
//If we can't find an algorithm that matches, we can't sign
logger.error("No matching algirthm found for alg=" + alg);
}
try { try {
jwt.sign(signer);
if (signer == null) {
//If we can't find an algorithm that matches, we can't sign
logger.error("No matching algirthm found for alg=" + alg);
} else if (signer instanceof PlainSigner) {
if (!(jwt.getHeader() instanceof PlainHeader)) {
throw new JOSEException("Invalid header. This signer is for use with Plain JWTs only.");
}
// do nothing because PlainJWT is good already.
} else { // we have a signable JWS at this point.
((SignedJWT) jwt).sign(signer);
}
} catch (JOSEException e) { } catch (JOSEException e) {
logger.error("Failed to sign JWT, error was: ", e); logger.error("Failed to sign JWT, error was: ", e);
} }
} }
@Override @Override
public boolean validateSignature(SignedJWT jwt) { public boolean validateSignature(JWT jwt) {
if (getDefaultSigningAlgorithm().equals(JWSAlgorithm.NONE) {
if (jwt instanceof PlainJWT) {
return
}
}
for (JWSVerifier verifier : verifiers.values()) { for (JWSVerifier verifier : verifiers.values()) {
try { try {
@ -281,6 +328,8 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
public Collection<JWSAlgorithm> getAllSigningAlgsSupported() { public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>(); Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>();
//TODO add 'none'
for (JWSSigner signer : signers.values()) { for (JWSSigner signer : signers.values()) {
algs.addAll(signer.supportedAlgorithms()); algs.addAll(signer.supportedAlgorithms());