JWSUtils uses JWSAlgorithm to match bit length; ConnectTokenEnhancer calls the util method now
parent
3a591dc1f4
commit
37580cc21e
|
@ -16,17 +16,10 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.openid.connect.token;
|
package org.mitre.openid.connect.token;
|
||||||
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||||
|
@ -35,6 +28,7 @@ import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||||
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
import org.mitre.openid.connect.service.ApprovedSiteService;
|
import org.mitre.openid.connect.service.ApprovedSiteService;
|
||||||
|
import org.mitre.openid.connect.util.JWSUtils;
|
||||||
import org.mitre.openid.connect.web.AuthenticationTimeStamper;
|
import org.mitre.openid.connect.web.AuthenticationTimeStamper;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -42,7 +36,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
|
||||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
@ -163,39 +156,11 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
|
||||||
Set<String> responseTypes = OAuth2Utils.parseParameterList(responseType);
|
Set<String> responseTypes = OAuth2Utils.parseParameterList(responseType);
|
||||||
if (responseTypes.contains("token")) {
|
if (responseTypes.contains("token")) {
|
||||||
// calculate the token hash
|
// calculate the token hash
|
||||||
|
Base64URL at_hash = JWSUtils.getAccessTokenHash(signingAlg, token.getJwt().serialize().getBytes());
|
||||||
// get the right algorithm size
|
//TODO: What should happen if the hash cannot be calculated?
|
||||||
// TODO: all this string parsing feels like a bad hack
|
|
||||||
String algName = signingAlg.getName();
|
|
||||||
Pattern re = Pattern.compile("^[HRE]S(\\d+)$");
|
|
||||||
Matcher match = re.matcher(algName);
|
|
||||||
if (match.matches()) {
|
|
||||||
String bits = match.group(1);
|
|
||||||
String hmacAlg = "HMACSHA" + bits;
|
|
||||||
try {
|
|
||||||
Mac mac = Mac.getInstance(hmacAlg);
|
|
||||||
mac.init(new SecretKeySpec(token.getJwt().serialize().getBytes(), hmacAlg));
|
|
||||||
|
|
||||||
byte[] at_hash_bytes = mac.doFinal();
|
|
||||||
byte[] at_hash_bytes_left = Arrays.copyOf(at_hash_bytes, at_hash_bytes.length / 2);
|
|
||||||
Base64URL at_hash = Base64URL.encode(at_hash_bytes_left);
|
|
||||||
|
|
||||||
idClaims.setClaim("at_hash", at_hash);
|
idClaims.setClaim("at_hash", at_hash);
|
||||||
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
|
|
||||||
logger.error("No such algorithm error: ", e);
|
|
||||||
|
|
||||||
} catch (InvalidKeyException e) {
|
|
||||||
|
|
||||||
logger.error("Invalid key error: ", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SignedJWT idToken = new SignedJWT(new JWSHeader(signingAlg), idClaims);
|
SignedJWT idToken = new SignedJWT(new JWSHeader(signingAlg), idClaims);
|
||||||
|
|
||||||
//TODO: check for client's preferred signer alg and use that
|
//TODO: check for client's preferred signer alg and use that
|
||||||
|
|
|
@ -3,8 +3,6 @@ package org.mitre.openid.connect.util;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
@ -27,22 +25,28 @@ public class JWSUtils {
|
||||||
|
|
||||||
public static Base64URL getAccessTokenHash(JWSAlgorithm signingAlg, byte[] tokenBytes) {
|
public static Base64URL getAccessTokenHash(JWSAlgorithm signingAlg, byte[] tokenBytes) {
|
||||||
|
|
||||||
//Switch based on the given signing algorithm
|
//Switch based on the given signing algorithm - use HMAC with the same bitnumber
|
||||||
|
//as the JWSAlgorithm to hash the token.
|
||||||
|
|
||||||
String algName = signingAlg.getName();
|
String hashAlg = null;
|
||||||
|
|
||||||
if (algName.equals(JWSAlgorithm.HS256)) {
|
|
||||||
|
|
||||||
|
if (signingAlg.equals(JWSAlgorithm.HS256) || signingAlg.equals(JWSAlgorithm.ES256) || signingAlg.equals(JWSAlgorithm.RS256)) {
|
||||||
|
hashAlg = "HMACSHA256";
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern re = Pattern.compile("^[HRE]S(\\d+)$");
|
else if (signingAlg.equals(JWSAlgorithm.ES384) || signingAlg.equals(JWSAlgorithm.HS384) || signingAlg.equals(JWSAlgorithm.RS384)) {
|
||||||
Matcher match = re.matcher(algName);
|
hashAlg = "HMACSHA384";
|
||||||
if (match.matches()) {
|
}
|
||||||
String bits = match.group(1);
|
|
||||||
String hmacAlg = "HMACSHA" + bits;
|
else if (signingAlg.equals(JWSAlgorithm.ES512) || signingAlg.equals(JWSAlgorithm.HS512) || signingAlg.equals(JWSAlgorithm.RS512)) {
|
||||||
|
hashAlg = "HMACSHA512";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashAlg != null) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mac mac = Mac.getInstance(hmacAlg);
|
Mac mac = Mac.getInstance(hashAlg);
|
||||||
mac.init(new SecretKeySpec(tokenBytes, hmacAlg));
|
mac.init(new SecretKeySpec(tokenBytes, hashAlg));
|
||||||
|
|
||||||
byte[] at_hash_bytes = mac.doFinal();
|
byte[] at_hash_bytes = mac.doFinal();
|
||||||
byte[] at_hash_bytes_left = Arrays.copyOf(at_hash_bytes, at_hash_bytes.length / 2);
|
byte[] at_hash_bytes_left = Arrays.copyOf(at_hash_bytes, at_hash_bytes.length / 2);
|
||||||
|
|
Loading…
Reference in New Issue