Ver código fonte

Jwt Service optimize

MaxKey 3 anos atrás
pai
commit
ade641922c

+ 32 - 5
maxkey-common/src/main/java/org/maxkey/crypto/jwt/encryption/service/impl/DefaultJwtEncryptionAndDecryptionService.java

@@ -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);
 			}
 
 		}

+ 35 - 2
maxkey-common/src/main/java/org/maxkey/crypto/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java

@@ -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
 	 */

+ 21 - 27
maxkey-protocols/maxkey-protocol-jwt/src/main/java/org/maxkey/authz/jwt/endpoint/adapter/JwtAdapter.java

@@ -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);

+ 1 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/AuthorizationEndpoint.java

@@ -132,7 +132,7 @@ public class AuthorizationEndpoint extends AbstractEndpoint {
             e.printStackTrace();
         }
         
-        _logger.debug("authorizationUrl "+authorizationUrl);
+        _logger.debug("authorizationUrl {}" , authorizationUrl);
         
         return WebContext.redirect(authorizationUrl);
     }

+ 13 - 21
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/userinfo/endpoint/UserInfoOIDCEndpoint.java

@@ -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);

+ 21 - 26
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oidc/idtoken/OIDCIdTokenEnhancer.java

@@ -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) {