提交 ade64192 编写于 作者: M MaxKey

Jwt Service optimize

上级 db151cc9
......@@ -52,7 +52,7 @@ import com.nimbusds.jose.jwk.RSAKey;
*/
public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAndDecryptionService {
private static Logger logger = LoggerFactory.getLogger(DefaultJwtEncryptionAndDecryptionService.class);
private static Logger _logger = LoggerFactory.getLogger(DefaultJwtEncryptionAndDecryptionService.class);
// map of identifier to encrypter
private Map<String, JWEEncrypter> encrypters = new HashMap<String, JWEEncrypter>();
......@@ -106,6 +106,25 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
buildEncryptersAndDecrypters();
}
public DefaultJwtEncryptionAndDecryptionService(String jwkSetString, String defaultEncryptionKeyId,String defaultAlgorithm) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
JWKSetKeyStore keyStore = new JWKSetKeyStore("{\"keys\": [" + jwkSetString + "]}");
this.defaultEncryptionKeyId = defaultEncryptionKeyId;
this.defaultAlgorithm = JWEAlgorithm.parse(defaultAlgorithm);
_logger.trace(" encryptAlgorithm {}" , defaultAlgorithm);
// convert all keys in the keystore to a map based on key id
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
this.keys.put(key.getKeyID(), key);
} else {
throw new IllegalArgumentException("Tried to load a key from a keystore without a 'kid' field: " + key);
}
}
buildEncryptersAndDecrypters();
}
@PostConstruct
......@@ -158,6 +177,14 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
public JWEAlgorithm getDefaultAlgorithm() {
return defaultAlgorithm;
}
public JWEAlgorithm getDefaultAlgorithm(String algorithm) {
if(algorithm.startsWith("RSA")) {
return defaultAlgorithm;
}else {
return JWEAlgorithm.DIR;
}
}
public void setDefaultAlgorithm(String algorithm) {
defaultAlgorithm = JWEAlgorithm.parse(algorithm);
......@@ -182,7 +209,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
jwt.encrypt(encrypter);
} catch (JOSEException e) {
logger.error("Failed to encrypt JWT, error was: ", e);
_logger.error("Failed to encrypt JWT, error was: ", e);
}
}
......@@ -202,7 +229,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
jwt.decrypt(decrypter);
} catch (JOSEException e) {
logger.error("Failed to decrypt JWT, error was: ", e);
_logger.error("Failed to decrypt JWT, error was: ", e);
}
}
......@@ -231,7 +258,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
RSADecrypter decrypter = new RSADecrypter(((RSAKey) jwk).toRSAPrivateKey());
decrypters.put(id, decrypter);
} else {
logger.warn("No private key for key #" + jwk.getKeyID());
_logger.warn("No private key for key #" + jwk.getKeyID());
}
// add support for EC keys
......@@ -246,7 +273,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
decrypters.put(id, decrypter);
} else {
logger.warn("Unknown key type: " + jwk);
_logger.warn("Unknown key type: " + jwk);
}
}
......
......@@ -46,7 +46,8 @@ import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService {
final static Logger _logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
// map of identifier to signer
private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
......@@ -111,7 +112,39 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
buildSignersAndVerifiers();
}
/**
* Build this service based on the given keystore. All keys must have a key
* id ({@code kid}) field in order to be used.
* see DefaultJwtSigningAndValidationService(JWKSetKeyStore keyStore)
* @param jwkSetString
* @param defaultSignerKeyId
* @param defaultAlgorithm
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws JOSEException
*/
public DefaultJwtSigningAndValidationService(String jwkSetString, String defaultSignerKeyId,String defaultAlgorithm) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
JWKSetKeyStore keyStore = new JWKSetKeyStore("{\"keys\": [" + jwkSetString + "]}");
this.defaultSignerKeyId = defaultSignerKeyId;
this.defaultAlgorithm = JWSAlgorithm.parse(defaultAlgorithm);
_logger.trace(" signingAlg {}" , defaultAlgorithm);
// convert all keys in the keystore to a map based on key id
if (keyStore!= null && keyStore.getJwkSet() != null) {
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
// use the key ID that's built into the key itself
// (#641): deal with JWK thumbprints
this.keys.put(key.getKeyID(), key);
} else {
// create a random key id
String fakeKid = UUID.randomUUID().toString();
this.keys.put(fakeKid, key);
}
}
}
buildSignersAndVerifiers();
}
/**
* @return the defaultSignerKeyId
*/
......
......@@ -25,7 +25,6 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.maxkey.entity.apps.AppsJwtDetails;
......@@ -34,12 +33,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.Payload;
import com.nimbusds.jwt.JWT;
......@@ -101,15 +97,18 @@ public class JwtAdapter extends AbstractAuthorizeAdapter {
@Override
public Object sign(Object data,String signatureKey,String signature) {
if(!jwtDetails.getSignature().equalsIgnoreCase("none")) {
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+jwtDetails.getSignatureKey()+"]}");
try {
DefaultJwtSigningAndValidationService jwtSignerService =
new DefaultJwtSigningAndValidationService(jwkSetKeyStore);
jwtSignerService.setDefaultSignerKeyId(jwtDetails.getId() + "_sig");
jwtSignerService.setDefaultSigningAlgorithmName(jwtDetails.getSignature());
JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
_logger.trace(" signingAlg {}" , signingAlg);
jwtToken = new SignedJWT(new JWSHeader(signingAlg), jwtClaims);
new DefaultJwtSigningAndValidationService(
jwtDetails.getSignatureKey(),
jwtDetails.getId() + "_sig",
jwtDetails.getSignature()
);
jwtToken = new SignedJWT(
new JWSHeader(jwtSignerService.getDefaultSigningAlgorithm()),
jwtClaims
);
// sign it with the server's key
jwtSignerService.signJwt((SignedJWT) jwtToken);
return jwtToken;
......@@ -127,22 +126,14 @@ public class JwtAdapter extends AbstractAuthorizeAdapter {
@Override
public Object encrypt(Object data, String algorithmKey, String algorithm) {
if(!jwtDetails.getAlgorithm().equalsIgnoreCase("none")) {
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+jwtDetails.getAlgorithmKey()+"]}");
try {
DefaultJwtEncryptionAndDecryptionService jwtEncryptionService =
new DefaultJwtEncryptionAndDecryptionService(jwkSetKeyStore);
jwtEncryptionService.setDefaultEncryptionKeyId(jwtDetails.getId() + "_enc");
jwtEncryptionService.setDefaultAlgorithm(jwtDetails.getAlgorithm());
JWEAlgorithm encryptAlgorithm = null;
if(jwtDetails.getAlgorithm().startsWith("RSA")) {
encryptAlgorithm = jwtEncryptionService.getDefaultAlgorithm();
}else {
encryptAlgorithm = JWEAlgorithm.DIR;
}
_logger.trace(" encryptAlgorithm {}" , encryptAlgorithm);
EncryptionMethod encryptionMethod =
jwtEncryptionService.parseEncryptionMethod(jwtDetails.getEncryptionMethod());
new DefaultJwtEncryptionAndDecryptionService(
jwtDetails.getAlgorithmKey(),
jwtDetails.getId() + "_enc",
jwtDetails.getAlgorithm()
);
Payload payload;
if(jwtToken instanceof SignedJWT) {
payload = ((SignedJWT)jwtToken).getPayload();
......@@ -151,9 +142,12 @@ public class JwtAdapter extends AbstractAuthorizeAdapter {
}
// Example Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
//JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM);
JWEHeader jweHeader = new JWEHeader(
jwtEncryptionService.getDefaultAlgorithm(jwtDetails.getAlgorithm()),
jwtEncryptionService.parseEncryptionMethod(jwtDetails.getEncryptionMethod())
);
jweObject = new JWEObject(
new JWEHeader.Builder(new JWEHeader(encryptAlgorithm,encryptionMethod))
new JWEHeader.Builder(jweHeader)
.contentType("JWT") // required to indicate nested JWT
.build(),
payload);
......
......@@ -132,7 +132,7 @@ public class AuthorizationEndpoint extends AbstractEndpoint {
e.printStackTrace();
}
_logger.debug("authorizationUrl "+authorizationUrl);
_logger.debug("authorizationUrl {}" , authorizationUrl);
return WebContext.redirect(authorizationUrl);
}
......
......@@ -213,19 +213,17 @@ public class UserInfoOIDCEndpoint {
&& !clientDetails.getSignature().equalsIgnoreCase("none")
&& clientDetails.getUserInfoResponse().equalsIgnoreCase("ENCRYPTION")) {
//需要签名 signed ID token
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getSignatureKey()+"]}");
DefaultJwtSigningAndValidationService jwtSignerService = null;
try {
jwtSignerService = new DefaultJwtSigningAndValidationService(jwkSetKeyStore);
jwtSignerService = new DefaultJwtSigningAndValidationService(
clientDetails.getSignatureKey(),
clientDetails.getClientId() + "_sig",
clientDetails.getSignature());
}catch(Exception e) {
_logger.error("Couldn't create Jwt Signing Service",e);
}
jwtSignerService.setDefaultSignerKeyId(clientDetails.getClientId() + "_sig");
jwtSignerService.setDefaultSigningAlgorithmName(clientDetails.getSignature());
JWSAlgorithm signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
_logger.trace(" signingAlg {}" , signingAlg);
userInfoJWTClaims = new JWTClaimsSet
.Builder(userInfoJWTClaims)
.claim("kid", jwtSignerService.getDefaultSignerKeyId())
......@@ -240,30 +238,24 @@ public class UserInfoOIDCEndpoint {
&& !clientDetails.getAlgorithm().equalsIgnoreCase("none")
&& clientDetails.getUserInfoResponse().equalsIgnoreCase("SIGNING")
) {
//TODO: 需要加密
JWKSetKeyStore jwkSetKeyStore_Enc = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getAlgorithmKey()+"]}");
// 需要加密
try {
DefaultJwtEncryptionAndDecryptionService jwtEncryptionService =
new DefaultJwtEncryptionAndDecryptionService(jwkSetKeyStore_Enc);
jwtEncryptionService.setDefaultEncryptionKeyId(clientDetails.getClientId() + "_enc");
jwtEncryptionService.setDefaultAlgorithm(clientDetails.getAlgorithm());
JWEAlgorithm encryptAlgorithm = null;
if(clientDetails.getAlgorithm().startsWith("RSA")) {
encryptAlgorithm = jwtEncryptionService.getDefaultAlgorithm();
}else {
encryptAlgorithm = JWEAlgorithm.DIR;
}
_logger.trace(" encryptAlgorithm {}" , encryptAlgorithm);
EncryptionMethod encryptionMethod =
jwtEncryptionService.parseEncryptionMethod(clientDetails.getEncryptionMethod());
new DefaultJwtEncryptionAndDecryptionService(
clientDetails.getAlgorithmKey(),
clientDetails.getClientId() + "_enc",
clientDetails.getAlgorithm());
Payload payload = userInfoJWTClaims.toPayload();
// Example Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
//JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM);
JWEHeader jweHeader = new JWEHeader(
jwtEncryptionService.getDefaultAlgorithm(clientDetails.getAlgorithm()),
jwtEncryptionService.parseEncryptionMethod(clientDetails.getEncryptionMethod()));
JWEObject jweObject = new JWEObject(
new JWEHeader.Builder(new JWEHeader(encryptAlgorithm,encryptionMethod))
new JWEHeader.Builder(jweHeader)
.contentType("JWT") // required to indicate nested JWT
.build(),
payload);
......
......@@ -37,7 +37,6 @@ import org.maxkey.authz.oauth2.provider.OAuth2Authentication;
import org.maxkey.authz.oauth2.provider.OAuth2Request;
import org.maxkey.authz.oauth2.provider.token.TokenEnhancer;
import org.maxkey.configuration.oidc.OIDCProviderMetadata;
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.maxkey.entity.apps.oauth2.provider.ClientDetails;
......@@ -48,9 +47,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.JWSAlgorithm;
......@@ -71,8 +68,6 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
private OIDCProviderMetadata providerMetadata;
private ClientDetailsService clientDetailsService;
public void setProviderMetadata(OIDCProviderMetadata providerMetadata) {
......@@ -94,12 +89,13 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
JWSAlgorithm signingAlg = null;
try {//jwtSignerService
if (StringUtils.isNotBlank(clientDetails.getSignature()) && !clientDetails.getSignature().equalsIgnoreCase("none")) {
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getSignatureKey()+"]}");
jwtSignerService = new DefaultJwtSigningAndValidationService(jwkSetKeyStore);
jwtSignerService.setDefaultSignerKeyId(clientDetails.getClientId() + "_sig");
jwtSignerService.setDefaultSigningAlgorithmName(clientDetails.getSignature());
jwtSignerService = new DefaultJwtSigningAndValidationService(
clientDetails.getSignatureKey(),
clientDetails.getClientId() + "_sig",
clientDetails.getSignature()
);
signingAlg = jwtSignerService.getDefaultSigningAlgorithm();
_logger.trace(" signingAlg {}" , signingAlg);
}
}catch(Exception e) {
_logger.error("Couldn't create Jwt Signing Service",e);
......@@ -118,7 +114,10 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
* @see http://openid.net/specs/openid-connect-core-1_0.html#SelfIssuedDiscovery
* 7. Self-Issued OpenID Provider
*/
if(providerMetadata.getIssuer().equalsIgnoreCase("https://self-issued.me") && jwtSignerService != null){
if(clientDetails.getIssuer()!=null
&& jwtSignerService != null
&& clientDetails.getIssuer().equalsIgnoreCase("https://self-issued.me")
){
builder.claim("sub_jwk", jwtSignerService.getAllPublicKeys().get(jwtSignerService.getDefaultSignerKeyId()));
}
......@@ -161,30 +160,26 @@ public class OIDCIdTokenEnhancer implements TokenEnhancer {
}
}else if (StringUtils.isNotBlank(clientDetails.getAlgorithm())
&& !clientDetails.getAlgorithm().equalsIgnoreCase("none")) {
JWKSetKeyStore jwkSetKeyStore_Enc = new JWKSetKeyStore("{\"keys\": ["+clientDetails.getAlgorithmKey()+"]}");
try {
DefaultJwtEncryptionAndDecryptionService jwtEncryptionService =
new DefaultJwtEncryptionAndDecryptionService(jwkSetKeyStore_Enc);
jwtEncryptionService.setDefaultEncryptionKeyId(clientDetails.getClientId() + "_enc");
jwtEncryptionService.setDefaultAlgorithm(clientDetails.getAlgorithm());
JWEAlgorithm encryptAlgorithm = null;
if(clientDetails.getAlgorithm().startsWith("RSA")) {
encryptAlgorithm = jwtEncryptionService.getDefaultAlgorithm();
}else {
encryptAlgorithm = JWEAlgorithm.DIR;
}
_logger.trace(" encryptAlgorithm {}" , encryptAlgorithm);
EncryptionMethod encryptionMethod =
jwtEncryptionService.parseEncryptionMethod(clientDetails.getEncryptionMethod());
new DefaultJwtEncryptionAndDecryptionService(
clientDetails.getAlgorithmKey(),
clientDetails.getClientId() + "_enc",
clientDetails.getAlgorithm()
);
Payload payload = builder.build().toPayload();
// Example Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
//JWEHeader jweHeader = new JWEHeader(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM);
JWEHeader jweHeader = new JWEHeader(
jwtEncryptionService.getDefaultAlgorithm(clientDetails.getAlgorithm()),
jwtEncryptionService.parseEncryptionMethod(clientDetails.getEncryptionMethod())
);
JWEObject jweObject = new JWEObject(
new JWEHeader.Builder(new JWEHeader(encryptAlgorithm,encryptionMethod))
new JWEHeader.Builder(jweHeader)
.contentType("JWT") // required to indicate nested JWT
.build(),
payload);
jwtEncryptionService.encryptJwt(jweObject);
idTokenString = jweObject.serialize();
} catch (NoSuchAlgorithmException | InvalidKeySpecException | JOSEException e) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册