refactored signing and validation, added jwk-based cache, removed keyfetcher, refactored client side class structure

pull/306/merge
Justin Richer 2013-03-01 16:48:27 -05:00
parent 7e64c4bffc
commit 385853fa1f
17 changed files with 231 additions and 302 deletions

View File

@ -1,4 +1,4 @@
package org.mitre.oauth2.filter;
package org.mitre.oauth2.introspectingfilter;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

View File

@ -1,4 +1,4 @@
package org.mitre.oauth2.filter;
package org.mitre.oauth2.introspectingfilter;
import com.google.common.collect.Sets;
import com.google.gson.JsonElement;

View File

@ -1,4 +1,4 @@
package org.mitre.oauth2.filter;
package org.mitre.oauth2.introspectingfilter;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

View File

@ -43,8 +43,10 @@ import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCache;
import org.mitre.key.fetch.KeyFetcher;
import org.mitre.openid.connect.config.OIDCServerConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
@ -86,8 +88,9 @@ public class AbstractOIDCAuthenticationFilter extends
// Allow for time sync issues by having a window of X seconds.
private int timeSkewAllowance = 300;
private Map<OIDCServerConfiguration, JwtSigningAndValidationService> validationServices = new HashMap<OIDCServerConfiguration, JwtSigningAndValidationService>();
@Autowired
JWKSetSigningAndValidationServiceCache validationServices;
/**
* Builds the redirect_uri that will be sent to the Authorization Endpoint.
@ -352,7 +355,7 @@ public class AbstractOIDCAuthenticationFilter extends
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
// check the signature
JwtSigningAndValidationService jwtValidator = getValidatorForServer(serverConfig);
JwtSigningAndValidationService jwtValidator = validationServices.get(serverConfig.getJwkSigningUrl());
if (jwtValidator != null) {
if(!jwtValidator.validateSignature(idToken)) {
throw new AuthenticationServiceException("Signature validation failed");
@ -607,57 +610,6 @@ public class AbstractOIDCAuthenticationFilter extends
return getStoredSessionString(session, REDIRECT_URI_SESION_VARIABLE);
}
protected JwtSigningAndValidationService getValidatorForServer(OIDCServerConfiguration serverConfig) {
if(getValidationServices().containsKey(serverConfig)){
return validationServices.get(serverConfig);
} else {
KeyFetcher keyFetch = new KeyFetcher();
PublicKey signingKey = null;
if (serverConfig.getJwkSigningUrl() != null) {
// prefer the JWK
signingKey = keyFetch.retrieveJwkKey(serverConfig.getJwkSigningUrl());
} else if (serverConfig.getX509SigningUrl() != null) {
// use the x509 only if JWK isn't configured
signingKey = keyFetch.retrieveX509Key(serverConfig.getX509SigningUrl());
} else {
// no keys configured
logger.warn("No server key URLs configured for " + serverConfig.getIssuer());
}
if (signingKey != null) {
// TODO: this assumes RSA
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) signingKey);
Map<String, JWSVerifier> verifiers = ImmutableMap.of(serverConfig.getIssuer(), verifier);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(new HashMap<String, JWSSigner>(), verifiers);
validationServices.put(serverConfig, service);
return service;
} else {
// there were either no keys returned or no URLs configured to fetch them, assume no checking on key signatures
return null;
}
}
}
public Map<OIDCServerConfiguration, JwtSigningAndValidationService> getValidationServices() {
return validationServices;
}
public void setValidationServices(
Map<OIDCServerConfiguration, JwtSigningAndValidationService> validationServices) {
this.validationServices = validationServices;
}
public int getTimeSkewAllowance() {
return timeSkewAllowance;
}

View File

@ -1,7 +1,7 @@
/**
*
*/
package org.mitre.openid.connect.client;
package org.mitre.openid.connect.client.keypublisher;
import java.security.PublicKey;
import java.util.Map;

View File

@ -1,7 +1,7 @@
/**
*
*/
package org.mitre.openid.connect.client;
package org.mitre.openid.connect.client.keypublisher;
import java.lang.reflect.Method;

View File

@ -1,7 +1,7 @@
/**
*
*/
package org.mitre.openid.connect.client;
package org.mitre.openid.connect.client.keypublisher;
import java.util.Locale;

View File

@ -19,6 +19,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.util.Map;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jwt.SignedJWT;
public interface JwtSigningAndValidationService {
@ -49,6 +50,12 @@ public interface JwtSigningAndValidationService {
*/
public void signJwt(SignedJWT jwt) throws NoSuchAlgorithmException;
/**
* Get the default signing algorithm for use when nothing else has been specified.
* @return
*/
JWSAlgorithm getDefaultSigningAlgorithm();
/**
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
* in the JWT spec, section 6. I.E., "HS256" means HMAC with SHA-256 and corresponds to our HmacSigner class.

View File

@ -28,7 +28,9 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.collect.ImmutableMap;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
@ -36,9 +38,6 @@ import com.nimbusds.jwt.SignedJWT;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService, InitializingBean {
@Autowired
private ConfigurationPropertiesBean configBean;
// map of identifier to signer
private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
// map of identifier to verifier
@ -46,24 +45,37 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
private static Logger logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
private String defaultSignerId;
private JWSAlgorithm defaultAlgorithm;
/**
* default constructor
*/
public DefaultJwtSigningAndValidationService() {
}
public DefaultJwtSigningAndValidationService(Map<String, JWSSigner> signers, Map<String, JWSVerifier> verifiers) {
this.signers = signers;
this.verifiers = verifiers;
}
public DefaultJwtSigningAndValidationService(Map<String, RSASSASignerVerifierBuilder> builders) {
/**
* Create a new validation service from the given set of verifiers (no signing)
*/
public DefaultJwtSigningAndValidationService(Map<String, JWSVerifier> verifiers) {
this.verifiers = verifiers;
}
/**
* Load this signing and validation service from the given builders (which load keys from keystores)
* @param builders
*/
public void setBuilders(Map<String, RSASSASignerVerifierBuilder> builders) {
for (Entry<String, RSASSASignerVerifierBuilder> e : builders.entrySet()) {
JWSSigner signer = e.getValue().buildSigner();
signers.put(e.getKey(), signer);
if (e.getValue().isDefault()) {
defaultSignerId = e.getKey();
}
JWSVerifier verifier = e.getValue().buildVerifier();
verifiers.put(e.getKey(), verifier);
@ -72,6 +84,39 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
}
/**
* @return the defaultSignerId
*/
public String getDefaultSignerId() {
return defaultSignerId;
}
/**
* @param defaultSignerId the defaultSignerId to set
*/
public void setDefaultSignerId(String defaultSignerId) {
this.defaultSignerId = defaultSignerId;
}
/**
* @return
*/
@Override
public JWSAlgorithm getDefaultSigningAlgorithm() {
return defaultAlgorithm;
}
public void setDefaultSigningAlgorithmName(String algName) {
defaultAlgorithm = JWSAlgorithm.parse(algName);
}
public String getDefaultSigningAlgorithmName() {
if (defaultAlgorithm != null) {
return defaultAlgorithm.getName();
} else {
return null;
}
}
/*
* (non-Javadoc)
*
@ -80,41 +125,20 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
*/
@Override
public void afterPropertiesSet(){
// used for debugging...
if (!signers.isEmpty()) {
logger.info(this.toString());
}
logger.info("DefaultJwtSigningAndValidationService is open for business");
logger.info("DefaultJwtSigningAndValidationService is ready: " + this.toString());
}
/**
* @return the configBean
*/
public ConfigurationPropertiesBean getConfigBean() {
return configBean;
}
/**
* @param configBean the configBean to set
*/
public void setConfigBean(ConfigurationPropertiesBean configBean) {
this.configBean = configBean;
}
/**
* Sign a jwt in place using the configured default signer.
* @throws JOSEException
* @throws NoSuchAlgorithmException
*/
@Override
public void signJwt(SignedJWT jwt) {
String signerId = configBean.getDefaultJwtSigner();
JWSSigner signer = signers.get(signerId);
if (getDefaultSignerId() == null) {
throw new IllegalStateException("Tried to call default signing with no default signer ID set");
}
JWSSigner signer = signers.get(getDefaultSignerId());
try {
jwt.sign(signer);
} catch (JOSEException e) {

View File

@ -0,0 +1,117 @@
/**
*
*/
package org.mitre.jwt.signer.service.impl;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableMap;
import com.nimbusds.jose.JWK;
import com.nimbusds.jose.JWKSet;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.KeyType;
import com.nimbusds.jose.RSAKey;
import com.nimbusds.jose.crypto.RSASSAVerifier;
/**
*
* Creates a
*
* @author jricher
*
*/
public class JWKSetSigningAndValidationServiceCache {
private Cache<String, JwtSigningAndValidationService> cache;
public JWKSetSigningAndValidationServiceCache() {
this.cache = CacheBuilder.newBuilder()
.maximumSize(100)
.build(new JWKSetFetcher());
}
/**
* @param key
* @return
* @throws ExecutionException
* @see com.google.common.cache.Cache#get(java.lang.Object)
*/
public JwtSigningAndValidationService get(String key) {
try {
return cache.get(key);
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/**
* @author jricher
*
*/
private class JWKSetFetcher extends CacheLoader<String, JwtSigningAndValidationService> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
/**
* Load the JWK Set and build the appropriate signing service.
*/
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
Map<String, JWSVerifier> verifiers = new HashMap<String, JWSVerifier>();
for (JWK jwk : jwkSet.getKeys()) {
if (jwk.getKeyType().equals(KeyType.RSA)) {
// we can handle RSA
RSAKey rsa = (RSAKey)jwk;
byte[] modulusByte = rsa.getModulus().decode();
BigInteger modulus = new BigInteger(1, modulusByte);
byte[] exponentByte = rsa.getExponent().decode();
BigInteger exponent = new BigInteger(1, exponentByte);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
RSAPublicKey pub = (RSAPublicKey) factory.generatePublic(spec);
JWSVerifier verifier = new RSASSAVerifier(pub);
verifiers.put(jwk.getKeyID(), verifier);
}
}
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(verifiers);
return service;
}
}
}

View File

@ -28,6 +28,8 @@ public class RSASSASignerVerifierBuilder {
private String alias;
private String password;
private KeyStore keystore;
private boolean defaultSigner = false;
/**
* @return the alias
*/
@ -65,6 +67,18 @@ public class RSASSASignerVerifierBuilder {
this.keystore = keystore;
}
/**
* @return the defaultSigner
*/
public boolean isDefault() {
return defaultSigner;
}
/**
* @param defaultSigner the defaultSigner to set
*/
public void setDefault(boolean defaultSigner) {
this.defaultSigner = defaultSigner;
}
/**
* Build the signer as configured from the given keystore, null if it can't be built for some reason
* @return

View File

@ -1,109 +0,0 @@
package org.mitre.key.fetch;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.openid.connect.config.OIDCServerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class KeyFetcher {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
private static Logger logger = LoggerFactory.getLogger(KeyFetcher.class);
public JsonArray retrieveJwk(OIDCServerConfiguration serverConfig){
String jsonString = null;
try {
jsonString = restTemplate.getForObject(
serverConfig.getTokenEndpointUrl(), String.class);
} catch (HttpClientErrorException httpClientErrorException) {
throw new AuthenticationServiceException(
"Unable to obtain Access Token.");
}
JsonObject json = (JsonObject) new JsonParser().parse(jsonString);
JsonArray getArray = json.getAsJsonArray("jwk");
return getArray;
}
public PublicKey retrieveX509Key(String x509url) {
PublicKey key = null;
try {
InputStream x509Stream = restTemplate.getForObject(x509url, InputStream.class);
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) factory.generateCertificate(x509Stream);
key = cert.getPublicKey();
} catch (HttpClientErrorException e) {
logger.error("HttpClientErrorException in KeyFetcher.java: ", e);
} catch (CertificateException e) {
logger.error("CertificateException in KeyFetcher.java: ", e);
}
return key;
}
public PublicKey retrieveJwkKey(String jwkUrl) {
RSAPublicKey pub = null;
try {
String jwkString = restTemplate.getForObject(jwkUrl, String.class);
JsonObject json = (JsonObject) new JsonParser().parse(jwkString);
JsonArray getArray = json.getAsJsonArray("keys");
for(int i = 0; i < getArray.size(); i++) {
JsonObject object = getArray.get(i).getAsJsonObject();
String algorithm = object.get("alg").getAsString();
if(algorithm.equals("RSA")){
byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString());
BigInteger modulus = new BigInteger(1, modulusByte);
byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString());
BigInteger exponent = new BigInteger(1, exponentByte);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
pub = (RSAPublicKey) factory.generatePublic(spec);
}
}
} catch (HttpClientErrorException e) {
logger.error("HttpClientErrorException in KeyFetcher.java: ", e);
} catch (NoSuchAlgorithmException e) {
logger.error("NoSuchAlgorithmException in KeyFetcher.java: ", e);
} catch (InvalidKeySpecException e) {
logger.error("InvalidKeySpecException in KeyFetcher.java: ", e);
}
return pub;
}
}

View File

@ -15,7 +15,6 @@
******************************************************************************/
package org.mitre.openid.connect.config;
import com.nimbusds.jose.JWSAlgorithm;
/**
@ -30,10 +29,6 @@ public class ConfigurationPropertiesBean {
private String issuer;
private String defaultJwtSigner;
private JWSAlgorithm defaultAlgorithm;
private String adminConsoleTopbarTitle;
private String logoImageUrl;
@ -46,17 +41,6 @@ public class ConfigurationPropertiesBean {
public ConfigurationPropertiesBean() {
}
/**
* @return the defaultJwtSigner
*/
public String getDefaultJwtSigner() {
return defaultJwtSigner;
}
public void setDefaultJwtSigner(String signer) {
defaultJwtSigner = signer;
}
/**
* @return the baseUrl
*/
@ -71,25 +55,6 @@ public class ConfigurationPropertiesBean {
issuer = iss;
}
/**
* @return
*/
public JWSAlgorithm getDefaultSigningAlgorithm() {
return defaultAlgorithm;
}
public void setDefaultSigningAlgorithmName(String algName) {
defaultAlgorithm = JWSAlgorithm.parse(algName);
}
public String getDefaultSigningAlgorithmName() {
if (defaultAlgorithm != null) {
return defaultAlgorithm.getName();
} else {
return null;
}
}
public String getAdminConsoleTopbarTitle() {
return adminConsoleTopbarTitle;
}

View File

@ -3,14 +3,11 @@
*/
package org.mitre.openid.connect.assertion;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.mitre.key.fetch.KeyFetcher;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCache;
import org.mitre.oauth2.exception.ClientNotFoundException;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.service.ClientDetailsEntityService;
@ -24,12 +21,9 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
/**
* @author jricher
@ -40,7 +34,8 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = LoggerFactory.getLogger(JwtBearerAuthenticationProvider.class);
// map of verifiers, load keys for clients
private Map<ClientDetailsEntity, JWSVerifier> verifiers = new HashMap<ClientDetailsEntity, JWSVerifier>();
@Autowired
private JWKSetSigningAndValidationServiceCache validators;
// Allow for time sync issues by having a window of X seconds.
private int timeSkewAllowance = 300;
@ -69,10 +64,12 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
ReadOnlyJWTClaimsSet jwtClaims = jwt.getJWTClaimsSet();
// check the signature with nimbus
JWSVerifier verifier = getVerifierForClient(client);
JWSObject jws = JWSObject.parse(jwtAuth.getJwt().toString());
if (verifier == null && !jws.verify(verifier)) {
throw new AuthenticationServiceException("Invalid signature");
if (jwt instanceof SignedJWT) {
SignedJWT jws = (SignedJWT)jwt;
JwtSigningAndValidationService validator = validators.get(client.getJwkUrl());
if (validator == null || !validator.validateSignature(jws)) {
throw new AuthenticationServiceException("Invalid signature");
}
}
// check the issuer
@ -125,12 +122,7 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
} catch (ParseException e) {
// TODO Auto-generated catch block
throw new AuthenticationServiceException("Invalid JWT format");
} catch (JOSEException e) {
// TODO Auto-generated catch block
throw new AuthenticationServiceException("JOSE Error");
}
}
/**
@ -141,39 +133,5 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
return (JwtBearerAssertionAuthenticationToken.class.isAssignableFrom(authentication));
}
protected JWSVerifier getVerifierForClient(ClientDetailsEntity client) {
if(verifiers.containsKey(client)){
return verifiers.get(client);
} else {
KeyFetcher keyFetch = new KeyFetcher();
PublicKey signingKey = null;
if (client.getJwkUrl() != null) {
// prefer the JWK
signingKey = keyFetch.retrieveJwkKey(client.getJwkUrl());
} else if (client.getX509Url() != null) {
// use the x509 only if JWK isn't configured
signingKey = keyFetch.retrieveX509Key(client.getX509Url());
} else {
// no keys configured
logger.warn("No server key URLs configured for " + client.getClientId());
}
if (signingKey != null) {
// TODO: this assumes RSA
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) signingKey);
verifiers.put(client, verifier);
return verifier;
} else {
// there were either no keys returned or no URLs configured to fetch them, assume no checking on key signatures
return null;
}
}
}
}

View File

@ -60,6 +60,7 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
OAuth2AccessTokenEntity token = (OAuth2AccessTokenEntity) accessToken;
String clientId = authentication.getAuthorizationRequest().getClientId();
ClientDetailsEntity client = clientService.loadClientByClientId(clientId);
JWTClaimsSet claims = new JWTClaimsSet();
@ -73,7 +74,9 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it
SignedJWT signed = new SignedJWT(new JWSHeader(configBean.getDefaultSigningAlgorithm()), claims);
// TODO: use client's default signing algorithm
SignedJWT signed = new SignedJWT(new JWSHeader(jwtService.getDefaultSigningAlgorithm()), claims);
try {
jwtService.signJwt(signed);
@ -106,8 +109,6 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
idClaims.setIssueTime(new Date());
ClientDetailsEntity client = clientService.loadClientByClientId(clientId);
if (client.getIdTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getIdTokenValiditySeconds() * 1000L));
idClaims.setExpirationTime(expiration);
@ -124,7 +125,7 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
idClaims.setCustomClaim("nonce", nonce);
}
SignedJWT idToken = new SignedJWT(new JWSHeader(configBean.getDefaultSigningAlgorithm()), idClaims);
SignedJWT idToken = new SignedJWT(new JWSHeader(jwtService.getDefaultSigningAlgorithm()), idClaims);
//TODO: check for client's preferred signer alg and use that

View File

@ -10,17 +10,19 @@
<bean id="defaultsignerService"
class="org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService">
<constructor-arg name="builders">
<property name="builders">
<map>
<entry key="rsa1">
<bean id="rsaSignerBuilder" class="org.mitre.jwt.signer.service.impl.RSASSASignerVerifierBuilder">
<property name="keystore" ref="defaultKeystore" />
<property name="alias" value="rsa" />
<property name="password" value="changeit" />
<property name="default" value="true" />
</bean>
</entry>
</map>
</constructor-arg>
</property>
<property name="defaultSigningAlgorithmName" value="RS256" />
</bean>
</beans>

View File

@ -14,8 +14,6 @@
<bean id="configBean" class="org.mitre.openid.connect.config.ConfigurationPropertiesBean">
<property name="issuer" value="http://localhost/" />
<property name="defaultJwtSigner" value="rsa1"/>
<property name="defaultSigningAlgorithmName" value="RS256" />
<property name="adminConsoleCopyrightFooter" value="The MTIRE Corporation" />
<property name="logoImageUrl" value="https://id.mitre.org/connect/resources/images/openid_connect_small.png" />
<property name="adminConsoleTopbarTitle" value="MITREid Connect" />