placeholder
parent
e0b56bc72a
commit
d763a954da
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -78,4 +79,15 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -282,6 +329,8 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue