moved jwk/x509 publishing over to nimbus-jose (mostly)
parent
fca30cd13f
commit
10ab55a7e2
|
@ -16,11 +16,18 @@
|
||||||
package org.mitre.jwt.signer.service;
|
package org.mitre.jwt.signer.service;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
public interface JwtSigningAndValidationService {
|
public interface JwtSigningAndValidationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all public keys for this service, mapped by their ID
|
||||||
|
*/
|
||||||
|
public Map<String, PublicKey> getAllPublicKeys();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the signature of the given JWT against all configured signers,
|
* Checks the signature of the given JWT against all configured signers,
|
||||||
* returns true if at least one of the signers validates it.
|
* returns true if at least one of the signers validates it.
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.mitre.jwt.signer.service.impl;
|
package org.mitre.jwt.signer.service.impl;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -30,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import com.nimbusds.jose.JOSEException;
|
import com.nimbusds.jose.JOSEException;
|
||||||
import com.nimbusds.jose.JWSSigner;
|
import com.nimbusds.jose.JWSSigner;
|
||||||
import com.nimbusds.jose.JWSVerifier;
|
import com.nimbusds.jose.JWSVerifier;
|
||||||
|
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService, InitializingBean {
|
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService, InitializingBean {
|
||||||
|
@ -133,4 +135,20 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, PublicKey> getAllPublicKeys() {
|
||||||
|
Map<String, PublicKey> keys = new HashMap<String, PublicKey>();
|
||||||
|
|
||||||
|
// pull all keys out of the verifiers if we know how
|
||||||
|
for (String keyId : verifiers.keySet()) {
|
||||||
|
JWSVerifier verifier = verifiers.get(keyId);
|
||||||
|
if (verifier instanceof RSASSAVerifier) {
|
||||||
|
// we know how to do RSA public keys
|
||||||
|
keys.put(keyId, ((RSASSAVerifier) verifier).getPublicKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.mitre.openid.connect.view;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -28,8 +29,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.mitre.jwt.signer.JwtSigner;
|
|
||||||
import org.mitre.jwt.signer.impl.RsaSigner;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -78,22 +77,19 @@ public class JwkKeyListView extends AbstractView {
|
||||||
|
|
||||||
|
|
||||||
//BiMap<String, PublicKey> keyMap = (BiMap<String, PublicKey>) model.get("keys");
|
//BiMap<String, PublicKey> keyMap = (BiMap<String, PublicKey>) model.get("keys");
|
||||||
Map<String, JwtSigner> signers = (Map<String, JwtSigner>) model.get("signers");
|
Map<String, PublicKey> keys = (Map<String, PublicKey>) model.get("keys");
|
||||||
|
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
JsonArray keys = new JsonArray();
|
JsonArray keyList = new JsonArray();
|
||||||
obj.add("keys", keys);
|
obj.add("keys", keyList);
|
||||||
|
|
||||||
for (String keyId : signers.keySet()) {
|
for (String keyId : keys.keySet()) {
|
||||||
|
|
||||||
JwtSigner src = signers.get(keyId);
|
PublicKey key = keys.get(keyId);
|
||||||
|
|
||||||
if (src instanceof RsaSigner) {
|
if (key instanceof RSAPublicKey) {
|
||||||
|
|
||||||
RsaSigner rsaSigner = (RsaSigner) src;
|
|
||||||
|
|
||||||
RSAPublicKey rsa = (RSAPublicKey) rsaSigner.getPublicKey(); // we're sure this is an RSAPublicKey b/c this is an RsaSigner
|
|
||||||
|
|
||||||
|
RSAPublicKey rsa = (RSAPublicKey) key;
|
||||||
|
|
||||||
BigInteger mod = rsa.getModulus();
|
BigInteger mod = rsa.getModulus();
|
||||||
BigInteger exp = rsa.getPublicExponent();
|
BigInteger exp = rsa.getPublicExponent();
|
||||||
|
@ -109,7 +105,7 @@ public class JwkKeyListView extends AbstractView {
|
||||||
o.addProperty("exp", e64);
|
o.addProperty("exp", e64);
|
||||||
o.addProperty("kid", keyId);
|
o.addProperty("kid", keyId);
|
||||||
|
|
||||||
keys.add(o);
|
keyList.add(o);
|
||||||
} // TODO: deal with non-RSA key types
|
} // TODO: deal with non-RSA key types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,32 +8,21 @@ import java.io.OutputStreamWriter;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.PublicKey;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.DERObjectIdentifier;
|
|
||||||
import org.bouncycastle.asn1.x509.BasicConstraints;
|
|
||||||
import org.bouncycastle.asn1.x509.X509Extensions;
|
|
||||||
import org.bouncycastle.jce.X509Principal;
|
import org.bouncycastle.jce.X509Principal;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.openssl.PEMWriter;
|
import org.bouncycastle.openssl.PEMWriter;
|
||||||
import org.bouncycastle.x509.X509V3CertificateGenerator;
|
import org.bouncycastle.x509.X509V3CertificateGenerator;
|
||||||
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
|
|
||||||
import org.mitre.jwt.signer.JwtSigner;
|
|
||||||
import org.mitre.jwt.signer.impl.RsaSigner;
|
|
||||||
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -41,10 +30,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.servlet.view.AbstractView;
|
import org.springframework.web.servlet.view.AbstractView;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jricher
|
* @author jricher
|
||||||
*
|
*
|
||||||
|
@ -65,20 +50,20 @@ public class X509CertificateView extends AbstractView {
|
||||||
|
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
|
||||||
Map<String, JwtSigner> signers = (Map<String, JwtSigner>) model.get("signers");
|
Map<String, PublicKey> keys = (Map<String, PublicKey>) model.get("keys");
|
||||||
|
|
||||||
response.setContentType("application/x-pem-file");
|
response.setContentType("application/x-pem-file");
|
||||||
|
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream());
|
OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream());
|
||||||
PEMWriter pemWriter = new PEMWriter(writer);
|
PEMWriter pemWriter = new PEMWriter(writer);
|
||||||
|
|
||||||
for (String keyId : signers.keySet()) {
|
for (String keyId : keys.keySet()) {
|
||||||
|
|
||||||
JwtSigner src = signers.get(keyId);
|
PublicKey key = keys.get(keyId);
|
||||||
|
|
||||||
if (src instanceof RsaSigner) {
|
if (key instanceof RSAPublicKey) {
|
||||||
|
|
||||||
RsaSigner rsaSigner = (RsaSigner) src;
|
RSAPublicKey rsa = (RSAPublicKey) key;
|
||||||
|
|
||||||
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
|
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
|
||||||
|
|
||||||
|
@ -88,9 +73,11 @@ public class X509CertificateView extends AbstractView {
|
||||||
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * daysNotValidAfter )));
|
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * daysNotValidAfter )));
|
||||||
v3CertGen.setSubjectDN(new X509Principal("CN=" + config.getIssuer() + ", OU=None, O=None L=None, C=None"));
|
v3CertGen.setSubjectDN(new X509Principal("CN=" + config.getIssuer() + ", OU=None, O=None L=None, C=None"));
|
||||||
|
|
||||||
v3CertGen.setPublicKey(rsaSigner.getPublicKey());
|
v3CertGen.setPublicKey(key);
|
||||||
v3CertGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
|
v3CertGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
|
||||||
|
|
||||||
|
// FIXME: need to get the private keys over here, too, or make one up
|
||||||
|
/*
|
||||||
try {
|
try {
|
||||||
X509Certificate cert = v3CertGen.generate(rsaSigner.getPrivateKey());
|
X509Certificate cert = v3CertGen.generate(rsaSigner.getPrivateKey());
|
||||||
pemWriter.writeObject(cert);
|
pemWriter.writeObject(cert);
|
||||||
|
@ -108,7 +95,7 @@ public class X509CertificateView extends AbstractView {
|
||||||
pemWriter.flush();
|
pemWriter.flush();
|
||||||
writer.flush();
|
writer.flush();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.openid.connect.web;
|
package org.mitre.openid.connect.web;
|
||||||
|
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.mitre.jwt.signer.JwtSigner;
|
|
||||||
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
@ -34,21 +34,21 @@ public class JsonWebKeyEndpoint {
|
||||||
public ModelAndView getJwk() {
|
public ModelAndView getJwk() {
|
||||||
|
|
||||||
// map from key id to signer
|
// map from key id to signer
|
||||||
Map<String, JwtSigner> signers = jwtService.getAllSigners();
|
Map<String, PublicKey> keys = jwtService.getAllPublicKeys();
|
||||||
|
|
||||||
// TODO: check if keys are empty, return a 404 here or just an empty list?
|
// TODO: check if keys are empty, return a 404 here or just an empty list?
|
||||||
|
|
||||||
return new ModelAndView("jwkKeyList", "signers", signers);
|
return new ModelAndView("jwkKeyList", "keys", keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping("/x509")
|
@RequestMapping("/x509")
|
||||||
public ModelAndView getX509() {
|
public ModelAndView getX509() {
|
||||||
// map from key id to signer
|
// map from key id to signer
|
||||||
Map<String, JwtSigner> signers = jwtService.getAllSigners();
|
Map<String, PublicKey> keys = jwtService.getAllPublicKeys();
|
||||||
|
|
||||||
// TODO: check if keys are empty, return a 404 here or just an empty list?
|
// TODO: check if keys are empty, return a 404 here or just an empty list?
|
||||||
|
|
||||||
return new ModelAndView("x509certs", "signers", signers);
|
return new ModelAndView("x509certs", "keys", keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue