diff --git a/openid-connect-client/.settings/org.eclipse.wst.common.component b/openid-connect-client/.settings/org.eclipse.wst.common.component
index fc2629825..7759ecef5 100755
--- a/openid-connect-client/.settings/org.eclipse.wst.common.component
+++ b/openid-connect-client/.settings/org.eclipse.wst.common.component
@@ -1,7 +1,9 @@
-
+
+
+
diff --git a/openid-connect-client/.springBeans b/openid-connect-client/.springBeans
new file mode 100644
index 000000000..707e4bb7c
--- /dev/null
+++ b/openid-connect-client/.springBeans
@@ -0,0 +1,14 @@
+
+
+ 1
+
+
+
+
+
+
+ spring-servlet.xml
+
+
+
+
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java
index bd017a9f3..cecd8bb9c 100644
--- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java
@@ -28,6 +28,7 @@ import java.security.SecureRandom;
import java.security.Signature;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Calendar;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -42,9 +43,16 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.openid.connect.model.IdToken;
+import org.mitre.jwt.model.Jwt;
+import org.mitre.jwt.model.JwtHeader;
+import org.mitre.jwt.model.JwtClaims;
+import org.mitre.jwt.signer.AbstractJwtSigner;
+import org.mitre.jwt.signer.impl.HmacSigner;
+import org.mitre.jwt.signer.service.impl.DynamicJwtSigningAndValidationService;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
@@ -60,6 +68,7 @@ import org.springframework.web.util.WebUtils;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
@@ -78,7 +87,7 @@ public class AbstractOIDCAuthenticationFilter extends
* @author nemonik
*
*/
- class SanatizedRequest extends HttpServletRequestWrapper {
+ protected class SanatizedRequest extends HttpServletRequestWrapper {
private List paramsToBeSanatized;
@@ -109,8 +118,7 @@ public class AbstractOIDCAuthenticationFilter extends
public Enumeration getParameterNames() {
- ArrayList paramNames = Collections.list(super
- .getParameterNames());
+ ArrayList paramNames = Collections.list(super.getParameterNames());
for (String paramToBeSanatized : paramsToBeSanatized) {
paramNames.remove(paramToBeSanatized);
@@ -203,8 +211,7 @@ public class AbstractOIDCAuthenticationFilter extends
* http://server/path/program?query_string from the messaged
* parameters.
*/
- public static String buildURL(String baseURI,
- Map queryStringFields) {
+ public static String buildURL(String baseURI, Map queryStringFields) {
StringBuilder URLBuilder = new StringBuilder(baseURI);
@@ -214,9 +221,10 @@ public class AbstractOIDCAuthenticationFilter extends
try {
- URLBuilder.append(appendChar).append(param.getKey())
- .append('=')
- .append(URLEncoder.encode(param.getValue(), "UTF-8"));
+ URLBuilder.append(appendChar)
+ .append(param.getKey())
+ .append('=')
+ .append(URLEncoder.encode(param.getValue(), "UTF-8"));
} catch (UnsupportedEncodingException uee) {
@@ -241,8 +249,7 @@ public class AbstractOIDCAuthenticationFilter extends
* The data to be signed
* @return The signature text
*/
- public static String sign(Signature signer, PrivateKey privateKey,
- byte[] data) {
+ public static String sign(Signature signer, PrivateKey privateKey, byte[] data) {
String signature;
try {
@@ -323,8 +330,7 @@ public class AbstractOIDCAuthenticationFilter extends
public void afterPropertiesSet() {
super.afterPropertiesSet();
- Assert.notNull(errorRedirectURI,
- "An Error Redirect URI must be supplied");
+ Assert.notNull(errorRedirectURI, "An Error Redirect URI must be supplied");
KeyPairGenerator keyPairGenerator;
@@ -377,19 +383,19 @@ public class AbstractOIDCAuthenticationFilter extends
* authentication
* @return The authenticated user token, or null if authentication is
* incomplete.
+ * @throws Exception
* @throws UnsupportedEncodingException
*/
protected Authentication handleAuthorizationGrantResponse(
String authorizationGrant, HttpServletRequest request,
- OIDCServerConfiguration serverConfig) {
+ OIDCServerConfiguration serverConfig) throws Exception {
final boolean debug = logger.isDebugEnabled();
// Handle Token Endpoint interaction
HttpClient httpClient = new DefaultHttpClient();
- httpClient.getParams().setParameter("http.socket.timeout",
- new Integer(httpSocketTimeout));
+ httpClient.getParams().setParameter("http.socket.timeout", new Integer(httpSocketTimeout));
//
// TODO: basic auth is untested (it wasn't working last I
@@ -402,8 +408,7 @@ public class AbstractOIDCAuthenticationFilter extends
// credentials);
//
- HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
- httpClient);
+ HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
@@ -418,8 +423,7 @@ public class AbstractOIDCAuthenticationFilter extends
form.add("client_secret", serverConfig.getClientSecret());
if (debug) {
- logger.debug("tokenEndpointURI = "
- + serverConfig.getTokenEndpointURI());
+ logger.debug("tokenEndpointURI = " + serverConfig.getTokenEndpointURI());
logger.debug("form = " + form);
}
@@ -459,53 +463,44 @@ public class AbstractOIDCAuthenticationFilter extends
} else {
- // Extract the id_token
-
+ // Extract the id_token to insert into the
+ // OpenIdConnectAuthenticationToken
+
IdToken idToken = null;
-
+ DynamicJwtSigningAndValidationService jwtValidator = new DynamicJwtSigningAndValidationService(serverConfig.getX509SigningUrl(), serverConfig.getJwkSigningUrl(), serverConfig.getClientSecret());
+
if (jsonRoot.getAsJsonObject().get("id_token") != null) {
- try {
- idToken = IdToken.parse(jsonRoot.getAsJsonObject()
- .get("id_token").getAsString());
+ if(jwtValidator.validateSignature(jsonRoot.getAsJsonObject().get("id_token").getAsString())
+ && jwtValidator.validateIssuedJwt(idToken, serverConfig.getIssuer())
+ && jwtValidator.validateAudience(idToken, serverConfig.getClientId())
+ && jwtValidator.isJwtExpired(idToken)
+ && jwtValidator.validateIssuedAt(idToken)){
+
+ try {
+ idToken = IdToken.parse(jsonRoot.getAsJsonObject().get("id_token").getAsString());
+
+ } catch (Exception e) {
- List parts = Lists.newArrayList(Splitter.on(".")
- .split(jsonRoot.getAsJsonObject().get("id_token")
- .getAsString()));
+ // I suspect this could happen
- if (parts.size() != 3) {
- throw new IllegalArgumentException(
- "Invalid JWT format.");
+ logger.error("Problem parsing id_token: " + e);
+ // e.printStackTrace();
+
+ throw new AuthenticationServiceException("Problem parsing id_token return from Token endpoint: " + e);
}
-
- String h64 = parts.get(0);
- String c64 = parts.get(1);
- String s64 = parts.get(2);
-
- logger.debug("h64 = " + h64);
- logger.debug("c64 = " + c64);
- logger.debug("s64 = " + s64);
-
- } catch (Exception e) {
-
- // I suspect this could happen
-
- logger.error("Problem parsing id_token: " + e);
- // e.printStackTrace();
-
- throw new AuthenticationServiceException(
- "Problem parsing id_token return from Token endpoint: "
- + e);
+ }
+ else{
+ throw new AuthenticationServiceException("Problem verifying id_token");
}
} else {
// An error is unlikely, but it good security to check
- logger.error("Token Endpoint did not return a token_id");
+ logger.error("Token Endpoint did not return an id_token");
- throw new AuthenticationServiceException(
- "Token Endpoint did not return a token_id");
+ throw new AuthenticationServiceException("Token Endpoint did not return an id_token");
}
// Clients are required to compare nonce claim in ID token to
@@ -513,68 +508,56 @@ public class AbstractOIDCAuthenticationFilter extends
// stores this value as a signed session cookie to detect a
// replay by third parties.
//
- // See: OpenID Connect Messages
- //
- // Specifically, Section 2.1.1 entitled "ID Token"
+ // See: OpenID Connect Messages Section 2.1.1 entitled "ID Token"
//
// http://openid.net/specs/openid-connect-messages-1_0.html#id_token
//
- // Read the paragraph describing "nonce". Required w/ implicit flow.
- //
String nonce = idToken.getClaims().getNonce();
-
- Cookie nonceSignatureCookie = WebUtils.getCookie(request,
- NONCE_SIGNATURE_COOKIE_NAME);
-
+
+ Cookie nonceSignatureCookie = WebUtils.getCookie(request, NONCE_SIGNATURE_COOKIE_NAME);
+
if (nonceSignatureCookie != null) {
String sigText = nonceSignatureCookie.getValue();
-
+
if (sigText != null && !sigText.isEmpty()) {
-
+
if (!verify(signer, publicKey, nonce, sigText)) {
logger.error("Possible replay attack detected! "
+ "The comparison of the nonce in the returned "
+ "ID Token to the signed session "
+ NONCE_SIGNATURE_COOKIE_NAME + " failed.");
-
+
throw new AuthenticationServiceException(
"Possible replay attack detected! "
+ "The comparison of the nonce in the returned "
+ "ID Token to the signed session "
- + NONCE_SIGNATURE_COOKIE_NAME + " failed.");
+ + NONCE_SIGNATURE_COOKIE_NAME
+ + " failed.");
}
-
} else {
- logger.error(NONCE_SIGNATURE_COOKIE_NAME
- + " was found, but was null or empty.");
-
- throw new AuthenticationServiceException(
- NONCE_SIGNATURE_COOKIE_NAME
- + " was found, but was null or empty.");
+ logger.error(NONCE_SIGNATURE_COOKIE_NAME + " cookie was found but value was null or empty");
+ throw new AuthenticationServiceException(NONCE_SIGNATURE_COOKIE_NAME + " cookie was found but value was null or empty");
}
-
+
} else {
logger.error(NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
- throw new AuthenticationServiceException(
- NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
- }
+ throw new AuthenticationServiceException(NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
+ }
// pull the user_id out as a claim on the id_token
String userId = idToken.getTokenClaims().getUserId();
// construct an OpenIdConnectAuthenticationToken and return
- // a Authentication object w/
+ // a Authentication object w/the userId and the idToken
- OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(
- userId, idToken);
+ OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(userId, idToken);
- Authentication authentication = this.getAuthenticationManager()
- .authenticate(token);
+ Authentication authentication = this.getAuthenticationManager().authenticate(token);
return authentication;
@@ -605,8 +588,7 @@ public class AbstractOIDCAuthenticationFilter extends
urlVariables.put("response_type", "code");
urlVariables.put("client_id", serverConfiguration.getClientId());
urlVariables.put("scope", scope);
- urlVariables.put("redirect_uri", AbstractOIDCAuthenticationFilter
- .buildRedirectURI(request, null));
+ urlVariables.put("redirect_uri", AbstractOIDCAuthenticationFilter.buildRedirectURI(request, null));
// Create a string value used to associate a user agent session
// with an ID Token to mitigate replay attacks. The value is
@@ -616,8 +598,7 @@ public class AbstractOIDCAuthenticationFilter extends
String nonce = new BigInteger(50, new SecureRandom()).toString(16);
- Cookie nonceCookie = new Cookie(NONCE_SIGNATURE_COOKIE_NAME, sign(
- signer, privateKey, nonce.getBytes()));
+ Cookie nonceCookie = new Cookie(NONCE_SIGNATURE_COOKIE_NAME, sign(signer, privateKey, nonce.getBytes()));
response.addCookie(nonceCookie);
@@ -627,9 +608,7 @@ public class AbstractOIDCAuthenticationFilter extends
// TODO: display, prompt, request, request_uri
- String authRequest = AbstractOIDCAuthenticationFilter
- .buildURL(serverConfiguration.getAuthorizationEndpointURI(),
- urlVariables);
+ String authRequest = AbstractOIDCAuthenticationFilter.buildURL(serverConfiguration.getAuthorizationEndpointURI(), urlVariables);
logger.debug("Auth Request: " + authRequest);
@@ -677,4 +656,4 @@ public class AbstractOIDCAuthenticationFilter extends
public void setScope(String scope) {
this.scope = scope;
}
-}
\ No newline at end of file
+}
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java
index 93a362528..d237eb35f 100644
--- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java
@@ -94,9 +94,12 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
} else if (StringUtils.isNotBlank(request.getParameter("code"))) {
- return handleAuthorizationGrantResponse(
- request.getParameter("code"), new SanatizedRequest(request,
- new String[] { "code" }), oidcServerConfig);
+ try {
+ return handleAuthorizationGrantResponse(request.getParameter("code"), new SanatizedRequest(request, new String[] { "code" }), oidcServerConfig);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
} else {
@@ -125,4 +128,20 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
public void setTokenEndpointURI(String tokenEndpointURI) {
oidcServerConfig.setTokenEndpointURI(tokenEndpointURI);
}
+
+ public void setX509EncryptUrl(String x509EncryptUrl) {
+ oidcServerConfig.setX509EncryptUrl(x509EncryptUrl);
+ }
+
+ public void setX509SigningUrl(String x509SigningUrl) {
+ oidcServerConfig.setX509SigningUrl(x509SigningUrl);
+ }
+
+ public void setJwkEncryptUrl(String jwkEncryptUrl) {
+ oidcServerConfig.setJwkEncryptUrl(jwkEncryptUrl);
+ }
+
+ public void setJwkSigningUrl(String jwkSigningUrl) {
+ oidcServerConfig.setJwkSigningUrl(jwkSigningUrl);
+ }
}
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java
index 985f63750..38f4da1a5 100644
--- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java
@@ -108,10 +108,13 @@ public class OIDCAuthenticationUsingChooserFilter extends
Cookie issuerCookie = WebUtils.getCookie(request,
ISSUER_COOKIE_NAME);
- return handleAuthorizationGrantResponse(
- request.getParameter("code"), new SanatizedRequest(request,
- new String[] { "code" }),
- oidcServerConfigs.get(issuerCookie.getValue()));
+ try {
+ return handleAuthorizationGrantResponse(request.getParameter("code"), new SanatizedRequest(request, new String[] { "code" }),
+ oidcServerConfigs.get(issuerCookie.getValue()));
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
} else {
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java
index 02dcbf065..675f54775 100644
--- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCServerConfiguration.java
@@ -15,11 +15,20 @@
******************************************************************************/
package org.mitre.openid.connect.client;
+import java.io.File;
+import java.net.URL;
+import java.security.Key;
+
+import org.mitre.jwt.signer.service.impl.DynamicJwtSigningAndValidationService;
+import org.mitre.util.Utility;
+
/**
* @author nemonik
*
*/
public class OIDCServerConfiguration {
+
+ private DynamicJwtSigningAndValidationService dynamic;
private String authorizationEndpointURI;
@@ -28,6 +37,20 @@ public class OIDCServerConfiguration {
private String clientSecret;
private String clientId;
+
+ private String issuer;
+
+ private String x509EncryptUrl;
+
+ private String x509SigningUrl;
+
+ private String jwkEncryptUrl;
+
+ private String jwkSigningUrl;
+
+ private Key encryptKey;
+
+ private Key signingKey;
public String getAuthorizationEndpointURI() {
return authorizationEndpointURI;
@@ -36,6 +59,10 @@ public class OIDCServerConfiguration {
public String getClientId() {
return clientId;
}
+
+ public String getIssuer() {
+ return issuer;
+ }
public String getClientSecret() {
return clientSecret;
@@ -53,6 +80,10 @@ public class OIDCServerConfiguration {
this.clientId = clientId;
}
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@@ -60,13 +91,95 @@ public class OIDCServerConfiguration {
public void setTokenEndpointURI(String tokenEndpointURI) {
this.tokenEndpointURI = tokenEndpointURI;
}
+
+ public String getX509EncryptUrl() {
+ return x509EncryptUrl;
+ }
+
+ public String getX509SigningUrl() {
+ return x509SigningUrl;
+ }
+
+ public String getJwkEncryptUrl() {
+ return jwkEncryptUrl;
+ }
+
+ public String getJwkSigningUrl() {
+ return jwkSigningUrl;
+ }
+
+ public void setX509EncryptUrl(String x509EncryptUrl) {
+ this.x509EncryptUrl = x509EncryptUrl;
+ }
+
+ public void setX509SigningUrl(String x509SigningUrl) {
+ this.x509SigningUrl = x509SigningUrl;
+ }
+
+ public void setJwkEncryptUrl(String jwkEncryptUrl) {
+ this.jwkEncryptUrl = jwkEncryptUrl;
+ }
+
+ public void setJwkSigningUrl(String jwkSigningUrl) {
+ this.jwkSigningUrl = jwkSigningUrl;
+ }
+
+ public Key getSigningKey() throws Exception {
+ if(signingKey == null){
+ if(x509SigningUrl != null){
+ File file = new File(x509SigningUrl);
+ URL url = file.toURI().toURL();
+ signingKey = Utility.retrieveX509Key(url);
+ }
+ else if (jwkSigningUrl != null){
+ File file = new File(jwkSigningUrl);
+ URL url = file.toURI().toURL();
+ signingKey = Utility.retrieveJwkKey(url);
+ }
+ }
+ return signingKey;
+ }
+
+ public Key getEncryptionKey() throws Exception {
+ if(encryptKey == null){
+ if(x509EncryptUrl != null){
+ File file = new File(x509EncryptUrl);
+ URL url = file.toURI().toURL();
+ encryptKey = Utility.retrieveX509Key(url);
+ }
+ else if (jwkEncryptUrl != null){
+ File file = new File(jwkEncryptUrl);
+ URL url = file.toURI().toURL();
+ encryptKey = Utility.retrieveJwkKey(url);
+ }
+ }
+ return encryptKey;
+ }
+
+ public void checkKeys() throws Exception {
+ encryptKey = null;
+ signingKey = null;
+ getEncryptionKey();
+ getSigningKey();
+ }
@Override
public String toString() {
return "OIDCServerConfiguration [authorizationEndpointURI="
+ authorizationEndpointURI + ", tokenEndpointURI="
+ tokenEndpointURI + ", clientSecret=" + clientSecret
- + ", clientId=" + clientId + "]";
+ + ", clientId=" + clientId + ", issuer=" + issuer
+ +", x509EncryptedUrl="
+ + x509EncryptUrl + ", jwkEncryptedUrl="
+ + jwkEncryptUrl + ", x509SigningUrl="
+ + x509SigningUrl + ", jwkSigningUrl="
+ + jwkSigningUrl + "]";
+ }
+
+ public DynamicJwtSigningAndValidationService getDynamic() throws Exception{
+ dynamic = new DynamicJwtSigningAndValidationService(getX509SigningUrl(), getJwkSigningUrl(), getClientSecret());
+ return dynamic;
}
+
}
\ No newline at end of file
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCUserDetailService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCUserDetailService.java
new file mode 100644
index 000000000..64a0980b1
--- /dev/null
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCUserDetailService.java
@@ -0,0 +1,39 @@
+package org.mitre.openid.connect.client;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import org.mitre.openid.connect.model.IdToken;
+import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+public class OIDCUserDetailService implements UserDetailsService,
+ AuthenticationUserDetailsService {
+
+ public IdToken retrieveToken(URL url) throws IOException{
+ String str = new BufferedReader(new InputStreamReader(url.openStream())).toString();
+ IdToken idToken = IdToken.parse(str);
+ return idToken;
+ }
+
+
+ @Override
+ public UserDetails loadUserDetails(OpenIdConnectAuthenticationToken token)
+ throws UsernameNotFoundException {
+ // TODO Auto-generated method stub
+
+ return null;
+ }
+
+ @Override
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UrlValidator.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UrlValidator.java
new file mode 100644
index 000000000..66c723f0a
--- /dev/null
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UrlValidator.java
@@ -0,0 +1,34 @@
+package org.mitre.openid.connect.client;
+
+import org.springframework.validation.Errors;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+
+public class UrlValidator implements Validator{
+
+
+
+ @Override
+ public boolean supports(Class clzz) {
+ return OIDCServerConfiguration.class.equals(clzz);
+ }
+
+ @Override
+ public void validate(Object obj, Errors e) {
+ ValidationUtils.rejectIfEmpty(e, "x509EncryptUrl", "x509EncryptUrl.empty");
+
+ }
+
+ public void validate1(Object obj, Errors e) {
+ ValidationUtils.rejectIfEmpty(e, "x509SigningUrl", "x509SigningUrl.empty");
+ }
+
+ public void validate2(Object obj, Errors e) {
+ ValidationUtils.rejectIfEmpty(e, "jwkEncryptUrl", "jwkEncryptUrl.empty");
+ }
+
+ public void validate3(Object obj, Errors e) {
+ ValidationUtils.rejectIfEmpty(e, "jwkSigningUrl", "jwkSigningUrl.empty");
+ }
+
+}
\ No newline at end of file
diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java
new file mode 100644
index 000000000..48f44358e
--- /dev/null
+++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/OIDCServerConfigurationTest.java
@@ -0,0 +1,114 @@
+package org.mitre.openid.connect.client;
+
+import java.net.URL;
+import java.security.Key;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mitre.util.Utility;
+
+import junit.framework.TestCase;
+
+public class OIDCServerConfigurationTest extends TestCase {
+
+ private URL jwkUrl = this.getClass().getResource("/jwk/jwk");
+ private URL x509Url = this.getClass().getResource("/x509/x509");
+ private URL jwkEncryptedUrl = this.getClass().getResource("/jwk/jwkEncrypted");
+ private URL x509EncryptedUrl = this.getClass().getResource("/x509/x509Encrypted");
+ private OIDCServerConfiguration oidc;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ oidc = new OIDCServerConfiguration();
+ super.setUp();
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Test method for {@link org.mitre.util.Utility#retrieveJwk(java.lang.String)}.
+ * @throws Exception
+ */
+ @Test
+ public void testGetSigningKeyBoth() throws Exception {
+ oidc.setX509SigningUrl(x509Url.getPath());
+ oidc.setJwkSigningUrl(jwkUrl.getPath());
+ Key key = oidc.getSigningKey();
+ assertEquals(key, Utility.retrieveX509Key(x509Url));
+ }
+
+ @Test
+ public void testGetSigningKeyJwk() throws Exception {
+ oidc.setX509SigningUrl(null);
+ oidc.setJwkSigningUrl(jwkUrl.getPath());
+ Key key1 = oidc.getSigningKey();
+ assertEquals(key1, Utility.retrieveJwkKey(jwkUrl));
+ }
+
+ @Test
+ public void testGetSigningKeyX509() throws Exception {
+ oidc.setX509SigningUrl(x509Url.getPath());
+ oidc.setJwkSigningUrl(null);
+ Key key2 = oidc.getSigningKey();
+ assertEquals(key2, Utility.retrieveX509Key(x509Url));
+ }
+
+ @Test
+ public void testGetSigningKeyNone() throws Exception {
+ oidc.setX509SigningUrl(null);
+ oidc.setJwkSigningUrl(null);
+ Key key3 = oidc.getSigningKey();
+ assertEquals(key3, null);
+ }
+
+ @Test
+ public void testGetEncryptionKeyBoth() throws Exception {
+ oidc.setX509EncryptUrl(x509EncryptedUrl.getPath());
+ oidc.setJwkEncryptUrl(jwkEncryptedUrl.getPath());
+ Key key = oidc.getEncryptionKey();
+ assertEquals(key, Utility.retrieveX509Key(x509EncryptedUrl));
+ }
+
+ @Test
+ public void testGetEncryptionKeyJwk() throws Exception {
+ oidc.setX509EncryptUrl(null);
+ oidc.setJwkEncryptUrl(jwkEncryptedUrl.getPath());
+ Key key1 = oidc.getEncryptionKey();
+ assertEquals(key1, Utility.retrieveJwkKey(jwkEncryptedUrl));
+ }
+
+ @Test
+ public void testGetEncryptionKeyX509() throws Exception {
+ oidc.setX509EncryptUrl(x509EncryptedUrl.getPath());
+ oidc.setJwkEncryptUrl(null);
+ Key key2 = oidc.getEncryptionKey();
+ assertEquals(key2, Utility.retrieveX509Key(x509EncryptedUrl));
+ }
+
+ @Test
+ public void testGetEncryptionKeyNone() throws Exception {
+ oidc.setX509EncryptUrl(null);
+ oidc.setJwkEncryptUrl(null);
+ Key key3 = oidc.getEncryptionKey();
+ assertEquals(key3, null);
+ }
+
+ @Test
+ public void testGetDynamic() throws Exception {
+ oidc.setX509SigningUrl(x509Url.getPath());
+ oidc.setJwkSigningUrl(jwkUrl.getPath());
+ oidc.setClientSecret("foo");
+ assertEquals(oidc.getDynamic().getSigningX509Url(), x509Url.getPath());
+ assertEquals(oidc.getDynamic().getSigningJwkUrl(), jwkUrl.getPath());
+ assertEquals(oidc.getDynamic().getClientSecret(), "foo");
+ }
+}
diff --git a/openid-connect-client/src/test/resources/jwk/jwk b/openid-connect-client/src/test/resources/jwk/jwk
new file mode 100644
index 000000000..a5f42177d
--- /dev/null
+++ b/openid-connect-client/src/test/resources/jwk/jwk
@@ -0,0 +1,8 @@
+ {"jwk":
+ [
+ {"alg":"RSA",
+ "mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+ "exp":"AQAB",
+ "kid":"2011-04-29"}
+ ]
+ }
\ No newline at end of file
diff --git a/openid-connect-client/src/test/resources/jwk/jwkEncrypted b/openid-connect-client/src/test/resources/jwk/jwkEncrypted
new file mode 100644
index 000000000..a5f42177d
--- /dev/null
+++ b/openid-connect-client/src/test/resources/jwk/jwkEncrypted
@@ -0,0 +1,8 @@
+ {"jwk":
+ [
+ {"alg":"RSA",
+ "mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+ "exp":"AQAB",
+ "kid":"2011-04-29"}
+ ]
+ }
\ No newline at end of file
diff --git a/openid-connect-client/src/test/resources/x509/x509 b/openid-connect-client/src/test/resources/x509/x509
new file mode 100644
index 000000000..2d60d2c3e
--- /dev/null
+++ b/openid-connect-client/src/test/resources/x509/x509
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICxDCCAi0CBECcV/wwDQYJKoZIhvcNAQEEBQAwgagxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVU
+ZXhhczEPMA0GA1UEBxMGQXVzdGluMSowKAYDVQQKEyFUaGUgVW5pdmVyc2l0eSBvZiBUZXhhcyBh
+dCBBdXN0aW4xKDAmBgNVBAsTH0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgU2VydmljZXMxIjAgBgNV
+BAMTGXhtbGdhdGV3YXkuaXRzLnV0ZXhhcy5lZHUwHhcNMDQwNTA4MDM0NjA0WhcNMDQwODA2MDM0
+NjA0WjCBqDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xKjAo
+BgNVBAoTIVRoZSBVbml2ZXJzaXR5IG9mIFRleGFzIGF0IEF1c3RpbjEoMCYGA1UECxMfSW5mb3Jt
+YXRpb24gVGVjaG5vbG9neSBTZXJ2aWNlczEiMCAGA1UEAxMZeG1sZ2F0ZXdheS5pdHMudXRleGFz
+LmVkdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsmc+6+NjLmanvh+FvBziYdBwTiz+d/DZ
+Uy2jyvij6f8Xly6zkhHLSsuBzw08wPzr2K+F359bf9T3uiZMuao//FBGtDrTYpvQwkn4PFZwSeY2
+Ynw4edxp1JEWT2zfOY+QJDfNgpsYQ9hrHDwqnpbMVVqjdBq5RgTKGhFBj9kxEq0CAwEAATANBgkq
+hkiG9w0BAQQFAAOBgQCPYGXF6oRbnjti3CPtjfwORoO7ab1QzNS9Z2rLMuPnt6POlm1A3UPEwCS8
+6flTlAqg19Sh47H7+Iq/LuzotKvUE5ugK52QRNMa4c0OSaO5UEM5EfVox1pT9tZV1Z3whYYMhThg
+oC4y/On0NUVMN5xfF/GpSACga/bVjoNvd8HWEg==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/openid-connect-client/src/test/resources/x509/x509Encrypted b/openid-connect-client/src/test/resources/x509/x509Encrypted
new file mode 100644
index 000000000..2d60d2c3e
--- /dev/null
+++ b/openid-connect-client/src/test/resources/x509/x509Encrypted
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICxDCCAi0CBECcV/wwDQYJKoZIhvcNAQEEBQAwgagxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVU
+ZXhhczEPMA0GA1UEBxMGQXVzdGluMSowKAYDVQQKEyFUaGUgVW5pdmVyc2l0eSBvZiBUZXhhcyBh
+dCBBdXN0aW4xKDAmBgNVBAsTH0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgU2VydmljZXMxIjAgBgNV
+BAMTGXhtbGdhdGV3YXkuaXRzLnV0ZXhhcy5lZHUwHhcNMDQwNTA4MDM0NjA0WhcNMDQwODA2MDM0
+NjA0WjCBqDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xKjAo
+BgNVBAoTIVRoZSBVbml2ZXJzaXR5IG9mIFRleGFzIGF0IEF1c3RpbjEoMCYGA1UECxMfSW5mb3Jt
+YXRpb24gVGVjaG5vbG9neSBTZXJ2aWNlczEiMCAGA1UEAxMZeG1sZ2F0ZXdheS5pdHMudXRleGFz
+LmVkdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsmc+6+NjLmanvh+FvBziYdBwTiz+d/DZ
+Uy2jyvij6f8Xly6zkhHLSsuBzw08wPzr2K+F359bf9T3uiZMuao//FBGtDrTYpvQwkn4PFZwSeY2
+Ynw4edxp1JEWT2zfOY+QJDfNgpsYQ9hrHDwqnpbMVVqjdBq5RgTKGhFBj9kxEq0CAwEAATANBgkq
+hkiG9w0BAQQFAAOBgQCPYGXF6oRbnjti3CPtjfwORoO7ab1QzNS9Z2rLMuPnt6POlm1A3UPEwCS8
+6flTlAqg19Sh47H7+Iq/LuzotKvUE5ugK52QRNMa4c0OSaO5UEM5EfVox1pT9tZV1Z3whYYMhThg
+oC4y/On0NUVMN5xfF/GpSACga/bVjoNvd8HWEg==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwk/model/AbstractJwk.java b/openid-connect-common/src/main/java/org/mitre/jwk/model/AbstractJwk.java
new file mode 100644
index 000000000..483dbe170
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwk/model/AbstractJwk.java
@@ -0,0 +1,66 @@
+package org.mitre.jwk.model;
+
+import com.google.gson.JsonObject;
+
+public abstract class AbstractJwk implements Jwk{
+
+ public static final String ALGORITHM = "alg";
+ public static final String USE = "use";
+ public static final String KEY_ID = "kid";
+
+ private String kid;
+ private String alg;
+ private String use;
+
+ public AbstractJwk(JsonObject object){
+ init(object);
+ }
+
+ /* (non-Javadoc)
+ * @see org.mitre.jwk.model.Jwk2#getAlg()
+ */
+ @Override
+ public String getAlg() {
+ return alg;
+ }
+
+ public void setAlg(String alg) {
+ this.alg = alg;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mitre.jwk.model.Jwk2#getKid()
+ */
+ @Override
+ public String getKid() {
+ return kid;
+ }
+
+ public void setKid(String kid) {
+ this.kid = kid;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mitre.jwk.model.Jwk2#getUse()
+ */
+ @Override
+ public String getUse() {
+ return use;
+ }
+
+ public void setUse(String use) {
+ this.use = use;
+ }
+
+ protected void init(JsonObject object){
+ if(object.get(ALGORITHM) != null){
+ setAlg(object.get(ALGORITHM).getAsString());
+ }
+ if(object.get(KEY_ID) != null){
+ setKid(object.get(KEY_ID).getAsString());
+ }
+ if(object.get(USE) != null){
+ setUse(object.get(USE).getAsString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwk/model/EC.java b/openid-connect-common/src/main/java/org/mitre/jwk/model/EC.java
new file mode 100644
index 000000000..c24bdd037
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwk/model/EC.java
@@ -0,0 +1,96 @@
+package org.mitre.jwk.model;
+
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.spec.ECFieldF2m;
+import java.security.spec.EllipticCurve;
+import java.security.spec.InvalidKeySpecException;
+
+import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.JCEECPublicKey;
+import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.bouncycastle.jce.spec.ECPublicKeySpec;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPoint;
+
+import com.google.gson.JsonObject;
+
+public class EC extends AbstractJwk{
+
+ public static final String CURVE = "crv";
+ public static final String X = "x";
+ public static final String Y = "y";
+
+ private String crv;
+ private String x;
+ private String y;
+
+ JsonObject object = new JsonObject();
+
+ public String getCrv() {
+ return crv;
+ }
+
+ public void setCrv(String crv) {
+ this.crv = crv;
+ }
+
+ public String getX() {
+ return x;
+ }
+
+ public void setX(String x) {
+ this.x = x;
+ }
+
+ public String getY() {
+ return y;
+ }
+
+ public void setY(String y) {
+ this.y = y;
+ }
+
+ public EC(JsonObject object) {
+ super(object);
+ }
+
+ public void init(JsonObject object){
+ super.init(object);
+ setCrv(object.get(CURVE).getAsString());
+ setX(object.get(X).getAsString());
+ setY(object.get(Y).getAsString());
+ }
+
+ @Override
+ public PublicKey getKey() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
+ // TODO Auto-generated method stub
+
+ byte[] x_byte = Base64.decodeBase64(x);
+ BigInteger x_int = new BigInteger(x_byte);
+ byte[] y_byte = Base64.decodeBase64(y);
+ BigInteger y_int = new BigInteger(y_byte);
+
+ ECNamedCurveParameterSpec curveSpec = ECNamedCurveTable.getParameterSpec(crv);
+ BigInteger orderOfGen = curveSpec.getH();
+ int cofactor = Math.abs(curveSpec.getN().intValue());
+ ECCurve crv = curveSpec.getCurve();
+ BigInteger a = crv.getA().toBigInteger();
+ BigInteger b = crv.getB().toBigInteger();
+ int fieldSize = crv.getFieldSize();
+ ECFieldF2m field = new ECFieldF2m(fieldSize);
+ EllipticCurve curve = new EllipticCurve(field, a, b);
+ //ECPoint.Fp point = new ECPoint.Fp(curve, arg1, arg2);
+ return null;
+
+ //ECParameterSpec paramSpec = new ECParameterSpec(curve, point, orderOfGen, cofactor);
+ //ECPublicKeySpec spec = new ECPublicKeySpec(point, paramSpec);
+ //PublicKey key = new JCEECPublicKey("ECDCA", spec);
+
+ //return key;
+ }
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwk/model/Jwk.java b/openid-connect-common/src/main/java/org/mitre/jwk/model/Jwk.java
new file mode 100644
index 000000000..67edc2b15
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwk/model/Jwk.java
@@ -0,0 +1,18 @@
+package org.mitre.jwk.model;
+
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.spec.InvalidKeySpecException;
+
+public interface Jwk {
+
+ public abstract String getAlg();
+
+ public abstract String getKid();
+
+ public abstract String getUse();
+
+ public abstract Key getKey() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException;
+
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwk/model/Rsa.java b/openid-connect-common/src/main/java/org/mitre/jwk/model/Rsa.java
new file mode 100644
index 000000000..dc1c795f7
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwk/model/Rsa.java
@@ -0,0 +1,67 @@
+package org.mitre.jwk.model;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPublicKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+import com.google.gson.JsonObject;
+
+public class Rsa extends AbstractJwk{
+
+ public static final String MODULUS = "mod";
+ public static final String EXPONENT = "exp";
+
+ private String mod;
+ private String exp;
+
+ JsonObject object = new JsonObject();
+
+ public String getMod() {
+ return mod;
+ }
+
+ public void setMod(String mod) {
+ this.mod = mod;
+ }
+
+ public String getExp() {
+ return exp;
+ }
+
+ public void setExp(String exp) {
+ this.exp = exp;
+ }
+
+ public Rsa(JsonObject object){
+ super(object);
+ }
+
+ public void init(JsonObject object){
+ super.init(object);
+ setMod(object.get(MODULUS).getAsString());
+ setExp(object.get(EXPONENT).getAsString());
+ }
+
+ @Override
+ public PublicKey getKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ // TODO Auto-generated method stub
+ byte[] modulusByte = Base64.decodeBase64(mod);
+ BigInteger modulus = new BigInteger(modulusByte);
+ byte[] exponentByte = Base64.decodeBase64(exp);
+ BigInteger exponent = new BigInteger(exponentByte);
+
+ RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
+ KeyFactory factory = KeyFactory.getInstance("RSA");
+ PublicKey pub = factory.generatePublic(spec);
+
+ return pub;
+ }
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/model/Jwt.java b/openid-connect-common/src/main/java/org/mitre/jwt/model/Jwt.java
index 39d609bf3..ca0474b88 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/model/Jwt.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/model/Jwt.java
@@ -133,7 +133,7 @@ public class Jwt {
return h64 + "." + c64;
}
-
+
/**
* Parse a wire-encoded JWT
*/
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/model/JwtClaims.java b/openid-connect-common/src/main/java/org/mitre/jwt/model/JwtClaims.java
index 0c4807baf..bc6bc9aca 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/model/JwtClaims.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/model/JwtClaims.java
@@ -15,17 +15,11 @@
******************************************************************************/
package org.mitre.jwt.model;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Map.Entry;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
public class JwtClaims extends ClaimSet {
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java
index 7aeeb4cb3..5b5e427a2 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/AbstractJwtSigner.java
@@ -15,6 +15,7 @@
******************************************************************************/
package org.mitre.jwt.signer;
+import java.security.NoSuchAlgorithmException;
import java.util.List;
import org.mitre.jwt.model.Jwt;
@@ -52,9 +53,10 @@ public abstract class AbstractJwtSigner implements JwtSigner {
*
* @param jwt the jwt to sign
* @return the signed jwt
+ * @throws NoSuchAlgorithmException
*/
@Override
- public Jwt sign(Jwt jwt) {
+ public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException {
if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) {
// algorithm type doesn't match
// TODO: should this be an error or should we just fix it in the incoming jwt?
@@ -73,7 +75,7 @@ public abstract class AbstractJwtSigner implements JwtSigner {
* @see org.mitre.jwt.JwtSigner#verify(java.lang.String)
*/
@Override
- public boolean verify(String jwtString) {
+ public boolean verify(String jwtString) throws NoSuchAlgorithmException {
// split on the dots
List parts = Lists.newArrayList(Splitter.on(".").split(jwtString));
@@ -92,5 +94,5 @@ public abstract class AbstractJwtSigner implements JwtSigner {
}
- protected abstract String generateSignature(String signatureBase);
+ protected abstract String generateSignature(String signatureBase) throws NoSuchAlgorithmException;
}
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/JwtSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/JwtSigner.java
index a43314659..e2ab061b3 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/JwtSigner.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/JwtSigner.java
@@ -15,12 +15,14 @@
******************************************************************************/
package org.mitre.jwt.signer;
+import java.security.NoSuchAlgorithmException;
+
import org.mitre.jwt.model.Jwt;
public interface JwtSigner {
- public Jwt sign(Jwt jwt);
+ public Jwt sign(Jwt jwt) throws NoSuchAlgorithmException;
- public boolean verify(String jwtString);
+ public boolean verify(String jwtString) throws NoSuchAlgorithmException;
}
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java
index 974ed43f1..5f93ff13a 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/HmacSigner.java
@@ -134,23 +134,24 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean {
* )
*/
@Override
- public String generateSignature(String signatureBase) {
+ public String generateSignature(String signatureBase) throws NoSuchAlgorithmException {
+ Mac _mac = getMac();
if (passphrase == null) {
throw new IllegalArgumentException("Passphrase cannot be null");
}
try {
- mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac
+ _mac.init(new SecretKeySpec(getPassphrase().getBytes(), mac
.getAlgorithm()));
- mac.update(signatureBase.getBytes("UTF-8"));
+ _mac.update(signatureBase.getBytes("UTF-8"));
} catch (GeneralSecurityException e) {
logger.error(e);
} catch (UnsupportedEncodingException e) {
logger.error(e);
}
- byte[] sigBytes = mac.doFinal();
+ byte[] sigBytes = _mac.doFinal();
String sig = new String(Base64.encodeBase64URLSafe(sigBytes));
@@ -171,6 +172,14 @@ public class HmacSigner extends AbstractJwtSigner implements InitializingBean {
public void setPassphrase(String passphrase) {
this.passphrase = passphrase;
}
+
+ private Mac getMac() throws NoSuchAlgorithmException {
+ if(mac == null){
+ mac = Mac.getInstance(JwsAlgorithm.getByName(super.getAlgorithm())
+ .getStandardName());
+ }
+ return mac;
+ }
/*
* (non-Javadoc)
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java
index d12869259..4b261a15e 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/impl/RsaSigner.java
@@ -18,6 +18,7 @@ package org.mitre.jwt.signer.impl;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
@@ -173,15 +174,16 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
* )
*/
@Override
- public String generateSignature(String signatureBase) {
+ public String generateSignature(String signatureBase) throws NoSuchAlgorithmException {
String sig = null;
+ Signature _signer = getSigner();
try {
- signer.initSign(privateKey);
- signer.update(signatureBase.getBytes("UTF-8"));
+ _signer.initSign(privateKey);
+ _signer.update(signatureBase.getBytes("UTF-8"));
- byte[] sigBytes = signer.sign();
+ byte[] sigBytes = _signer.sign();
sig = (new String(Base64.encodeBase64URLSafe(sigBytes))).replace("=", "");
} catch (GeneralSecurityException e) {
@@ -228,6 +230,13 @@ public class RsaSigner extends AbstractJwtSigner implements InitializingBean {
public void setPrivateKey(RSAPrivateKey privateKey) {
this.privateKey = privateKey;
}
+
+ private Signature getSigner() throws NoSuchAlgorithmException{
+ if(signer == null){
+ signer = Signature.getInstance(JwsAlgorithm.getByName(super.getAlgorithm()).getStandardName());
+ }
+ return signer;
+ }
/*
* (non-Javadoc)
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
index 44c956302..0cb60026f 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
@@ -15,8 +15,8 @@
******************************************************************************/
package org.mitre.jwt.signer.service;
+import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
-import java.util.List;
import java.util.Map;
import org.mitre.jwt.model.Jwt;
@@ -59,8 +59,9 @@ public interface JwtSigningAndValidationService {
* @param jwtString
* the string representation of the JWT as sent on the wire
* @return true if the signature is valid, false if not
+ * @throws NoSuchAlgorithmException
*/
- public boolean validateSignature(String jwtString);
+ public boolean validateSignature(String jwtString) throws NoSuchAlgorithmException;
/**
* Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm.
@@ -68,8 +69,42 @@ public interface JwtSigningAndValidationService {
*
* @param jwt the jwt to sign
* @return the signed jwt
+ * @throws NoSuchAlgorithmException
*/
- public void signJwt(Jwt jwt);
+ public boolean validateIssuedAt(Jwt jwt);
+
+ /**
+ * Checks to see when this JWT was issued
+ *
+ * @param jwt
+ * the JWT to check
+ * @return true if the issued at is valid, false if not
+ * @throws NoSuchAlgorithmException
+ */
+ public boolean validateAudience(Jwt jwt, String clientId);
+
+ /**
+ * Checks the audience that the given JWT against the client_id of the Client
+ *
+ * @param jwt
+ * @param clientId
+ * the string representation of the client_id
+ * @return true if the audience matches the clinet_id, false if otherwise
+ * @throws NoSuchAlgorithmException
+ */
+ public boolean validateNonce(Jwt jwt, String nonce);
+
+ /**
+ * Checks to see if the nonce parameter sent in the Authorization Request
+ * is equal to the nonce parameter in the id token
+ *
+ * @param jwt
+ * @param nonce
+ * the string representation of the Nonce
+ * @return true if both nonce parameters are equal, false if otherwise
+ * @throws NoSuchAlgorithmException
+ */
+ public void signJwt(Jwt jwt) throws NoSuchAlgorithmException;
/**
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java
new file mode 100644
index 000000000..8d3a8d437
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/AbstractJwtSigningAndValidationService.java
@@ -0,0 +1,85 @@
+package org.mitre.jwt.signer.service.impl;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.Map;
+
+import org.mitre.jwt.model.Jwt;
+import org.mitre.jwt.signer.JwtSigner;
+import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
+
+public abstract class AbstractJwtSigningAndValidationService implements JwtSigningAndValidationService{
+
+ /**
+ * Return the JwtSigners associated with this service
+ *
+ * @return
+ */
+ public abstract Map getSigners();
+
+ @Override
+ public boolean isJwtExpired(Jwt jwt) {
+
+ Date expiration = jwt.getClaims().getExpiration();
+
+ if (expiration != null)
+ return new Date().after(expiration);
+ else
+ return false;
+
+ }
+
+ @Override
+ public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) {
+
+ String iss = jwt.getClaims().getIssuer();
+
+ if (iss.equals(expectedIssuer))
+ return true;
+
+ return false;
+ }
+
+ @Override
+ public boolean validateSignature(String jwtString) throws NoSuchAlgorithmException {
+
+ for (JwtSigner signer : getSigners().values()) {
+ if (signer.verify(jwtString))
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean validateIssuedAt(Jwt jwt) {
+ Date issuedAt = jwt.getClaims().getIssuedAt();
+
+ if (issuedAt != null)
+ return new Date().before(issuedAt);
+ else
+ return false;
+ }
+
+ @Override
+ public boolean validateAudience(Jwt jwt, String clientId) {
+
+ if(jwt.getClaims().getAudience().equals(clientId)){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ @Override
+ public boolean validateNonce(Jwt jwt, String nonce) {
+ if(jwt.getClaims().getNonce().equals(nonce)){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java
new file mode 100644
index 000000000..b475bd266
--- /dev/null
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationService.java
@@ -0,0 +1,175 @@
+package org.mitre.jwt.signer.service.impl;
+
+import java.io.File;
+import java.net.URL;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.mitre.jwt.model.Jwt;
+import org.mitre.jwt.model.JwtHeader;
+import org.mitre.jwt.signer.JwtSigner;
+import org.mitre.jwt.signer.impl.HmacSigner;
+import org.mitre.jwt.signer.impl.PlaintextSigner;
+import org.mitre.jwt.signer.impl.RsaSigner;
+import org.mitre.util.Utility;
+
+
+public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAndValidationService{
+
+ private String x509SigningUrl;
+
+ private String jwkSigningUrl;
+
+ private String clientSecret;
+
+ private Key signingKey;
+
+ private Map map;
+
+ private PublicKey publicKey;
+
+ private Map signers;
+
+ public DynamicJwtSigningAndValidationService(String x509SigningUrl, String jwkSigningUrl, String clientSecret) throws Exception {
+ setX509SigningUrl(x509SigningUrl);
+ setJwkSigningUrl(jwkSigningUrl);
+ setClientSecret(clientSecret);
+ }
+
+ public Key getSigningKey() throws Exception {
+ if(signingKey == null){
+ if(x509SigningUrl != null){
+ File file = new File(x509SigningUrl);
+ URL url = file.toURI().toURL();
+ signingKey = Utility.retrieveX509Key(url);
+ }
+ else if (jwkSigningUrl != null){
+ File file = new File(jwkSigningUrl);
+ URL url = file.toURI().toURL();
+ signingKey = Utility.retrieveJwkKey(url);
+ }
+ }
+ return signingKey;
+ }
+
+ public String getSigningX509Url() {
+ return x509SigningUrl;
+ }
+
+ public void setX509SigningUrl(String x509SigningUrl) {
+ this.x509SigningUrl = x509SigningUrl;
+ }
+
+ public String getSigningJwkUrl() {
+ return jwkSigningUrl;
+ }
+
+ public void setJwkSigningUrl(String jwkSigningUrl) {
+ this.jwkSigningUrl = jwkSigningUrl;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ @Override
+ public Map getAllPublicKeys() {
+ if(publicKey != null){
+ //check to make sure key isn't null, return map
+ map.put(((RSAPublicKey) publicKey).getModulus()
+ .toString(16).toUpperCase()
+ + ((RSAPublicKey) publicKey).getPublicExponent()
+ .toString(16).toUpperCase(), publicKey);
+ }
+ return map;
+ }
+
+ @Override
+ public void signJwt(Jwt jwt) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Map getSigners() {
+ // TODO Auto-generated method stub
+ signers = new HashMap();
+ return signers;
+ }
+
+ @Override
+ public boolean validateSignature(String jwtString) {
+
+ try {
+ JwtSigner signer = getSigner(jwtString);
+ return signer.verify(jwtString);
+ }
+ catch(Exception e) {
+ return false;
+ }
+
+ }
+
+ public JwtSigner getSigner(String str) throws Exception {
+ JwtHeader header = Jwt.parse(str).getHeader();
+ String alg = header.getAlgorithm();
+ JwtSigner signer = null;
+
+ if(alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){
+ signer = new HmacSigner(alg, clientSecret); // TODO: huh? no, we're not signing with the client secret
+ }
+
+ else if (alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")){
+ signer = new RsaSigner(alg, (PublicKey) getSigningKey(), null);
+ }
+
+ else if (alg.equals("none")){
+ signer = new PlaintextSigner();
+ }
+
+ else{
+ throw new IllegalArgumentException("Not an existing algorithm type");
+ }
+
+ return signer;
+ }
+
+ @Override
+ public boolean validateIssuedAt(Jwt jwt) {
+ Date issuedAt = jwt.getClaims().getIssuedAt();
+
+ if (issuedAt != null)
+ return new Date().before(issuedAt);
+ else
+ return false;
+ }
+
+ @Override
+ public boolean validateAudience(Jwt jwt, String clientId) {
+
+ if(jwt.getClaims().getAudience().equals(clientId)){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ @Override
+ public boolean validateNonce(Jwt jwt, String nonce) {
+ if(jwt.getClaims().getNonce().equals(nonce)){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java
index 3120b605a..77eb8cd83 100644
--- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java
+++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JwtSigningAndValidationServiceDefault.java
@@ -15,8 +15,8 @@
******************************************************************************/
package org.mitre.jwt.signer.service.impl;
+import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
-import java.security.interfaces.RSAPublicKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -31,14 +31,13 @@ import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
-public class JwtSigningAndValidationServiceDefault implements
+public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAndValidationService implements
JwtSigningAndValidationService, InitializingBean {
- @Autowired
- private ConfigurationPropertiesBean configBean;
+ @Autowired ConfigurationPropertiesBean configBean;
// map of identifier to signer
- private Map signers = new HashMap();
+ Map signers = new HashMap();
private static Log logger = LogFactory
.getLog(JwtSigningAndValidationServiceDefault.class);
@@ -109,34 +108,6 @@ public class JwtSigningAndValidationServiceDefault implements
return map;
}
- /**
- * Return the JwtSigners associated with this service
- *
- * @return
- */
- public Map getSigners() {
- return signers;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.mitre.jwt.signer.service.JwtSigningAndValidationService#isJwtExpired
- * (org.mitre.jwt.model.Jwt)
- */
- @Override
- public boolean isJwtExpired(Jwt jwt) {
-
- Date expiration = jwt.getClaims().getExpiration();
-
- if (expiration != null)
- return new Date().after(expiration);
- else
- return false;
-
- }
-
/**
* Set the JwtSigners associated with this service
*
@@ -156,55 +127,6 @@ public class JwtSigningAndValidationServiceDefault implements
+ "]";
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.mitre.jwt.signer.service.JwtSigningAndValidationService#validateIssuedJwt
- * (org.mitre.jwt.model.Jwt)
- */
- @Override
- public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) {
-
- String iss = jwt.getClaims().getIssuer();
-
- if (iss.equals(expectedIssuer))
- return true;
-
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.mitre.jwt.signer.service.JwtSigningAndValidationService#validateSignature
- * (java.lang.String)
- */
- @Override
- public boolean validateSignature(String jwtString) {
-
- for (JwtSigner signer : signers.values()) {
- if (signer.verify(jwtString))
- return true;
- }
-
- return false;
- }
-
- /**
- * Sign a jwt in place using the configured default signer.
- */
- @Override
- public void signJwt(Jwt jwt) {
- String signerId = configBean.getDefaultJwtSigner();
-
- JwtSigner signer = signers.get(signerId);
-
- signer.sign(jwt);
-
- }
-
/**
* @return the configBean
*/
@@ -218,4 +140,58 @@ public class JwtSigningAndValidationServiceDefault implements
public void setConfigBean(ConfigurationPropertiesBean configBean) {
this.configBean = configBean;
}
+
+ /**
+ * Sign a jwt in place using the configured default signer.
+ * @throws NoSuchAlgorithmException
+ */
+ @Override
+ public void signJwt(Jwt jwt) throws NoSuchAlgorithmException {
+ String signerId = configBean.getDefaultJwtSigner();
+
+ JwtSigner signer = getSigners().get(signerId);
+
+ signer.sign(jwt);
+
+ }
+
+ /**
+ * Return the JwtSigners associated with this service
+ *
+ * @return
+ */
+ public Map getSigners() {
+ return signers;
+ }
+
+ @Override
+ public boolean validateIssuedAt(Jwt jwt) {
+ Date issuedAt = jwt.getClaims().getIssuedAt();
+
+ if (issuedAt != null)
+ return new Date().before(issuedAt);
+ else
+ return false;
+ }
+
+ @Override
+ public boolean validateAudience(Jwt jwt, String clientId) {
+
+ if(clientId.equals(jwt.getClaims().getAudience())){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ @Override
+ public boolean validateNonce(Jwt jwt, String nonce) {
+ if(nonce.equals(jwt.getClaims().getNonce())){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
}
diff --git a/openid-connect-common/src/main/java/org/mitre/util/Utility.java b/openid-connect-common/src/main/java/org/mitre/util/Utility.java
index d6655286a..5bc809bd5 100644
--- a/openid-connect-common/src/main/java/org/mitre/util/Utility.java
+++ b/openid-connect-common/src/main/java/org/mitre/util/Utility.java
@@ -15,8 +15,34 @@
******************************************************************************/
package org.mitre.util;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.RSAPublicKeySpec;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.codec.binary.Base64;
+import org.mitre.jwk.model.AbstractJwk;
+import org.mitre.jwk.model.EC;
+import org.mitre.jwk.model.Jwk;
+import org.mitre.jwk.model.Rsa;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
/**
* A collection of utility methods.
*
@@ -43,4 +69,57 @@ public class Utility {
}
return issuer;
}
+
+ public static List retrieveJwk(URL path) throws Exception {
+ List keys = new ArrayList();
+
+ JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(path.openStream()))).getAsJsonObject();
+ JsonArray getArray = json.getAsJsonArray("jwk");
+
+ for(int i = 0; i < getArray.size(); i++){
+
+ JsonObject object = getArray.get(i).getAsJsonObject();
+ String algorithm = object.get("alg").getAsString();
+
+ if(algorithm.equals("RSA")){
+ Rsa rsa = new Rsa(object);
+ keys.add(rsa);
+ }
+
+ else{
+ EC ec = new EC(object);
+ keys.add(ec);
+ }
+ }
+ return keys;
+ }
+
+ public static Key retrieveX509Key(URL url) throws Exception {
+
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) factory.generateCertificate(url.openStream());
+ Key key = cert.getPublicKey();
+
+ return key;
+ }
+
+ public static Key retrieveJwkKey(URL url) throws Exception {
+
+ JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ JsonArray getArray = json.getAsJsonArray("jwk");
+ JsonObject object = getArray.get(0).getAsJsonObject();
+
+ byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString());
+ BigInteger modulus = new BigInteger(modulusByte);
+ byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString());
+ BigInteger exponent = new BigInteger(exponentByte);
+
+ RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
+ KeyFactory factory = KeyFactory.getInstance("RSA");
+ PublicKey pub = factory.generatePublic(spec);
+
+ return pub;
+ }
}
diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/HmacSignerTest.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/HmacSignerTest.java
new file mode 100644
index 000000000..ddac6e860
--- /dev/null
+++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/HmacSignerTest.java
@@ -0,0 +1,73 @@
+package org.mitre.jwt.signer.impl;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mitre.jwt.model.Jwt;
+import org.mitre.jwt.model.JwtClaims;
+import org.mitre.jwt.model.JwtHeader;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+public class HmacSignerTest extends TestCase {
+
+ URL claimsUrl = this.getClass().getResource("/jwt/claims");
+ URL hs256Url = this.getClass().getResource("/jwt/hs256");
+ URL hs384Url = this.getClass().getResource("/jwt/hs384");
+ URL hs512Url = this.getClass().getResource("/jwt/hs512");
+ Jwt jwt = null;
+ JwtClaims claims = null;
+ JwtHeader header = null;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp(URL url) throws Exception {
+ JsonParser parser = new JsonParser();
+ JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject();
+ JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ claims = new JwtClaims(claimsObject);
+ header = new JwtHeader(headerObject);
+ jwt = new Jwt(header, claims, null);
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testHmacSigner256() throws Exception {
+ setUp(hs256Url);
+ HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret");
+ jwt = hmac.sign(jwt);
+ assertEquals(hmac.verify(jwt.toString()), true);
+ }
+
+ @Test
+ public void testHmacSigner384() throws Exception {
+ setUp(hs384Url);
+ HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret");
+ jwt = hmac.sign(jwt);
+ assertEquals(hmac.verify(jwt.toString()), true);
+ }
+
+ @Test
+ public void testHmacSigner512() throws Exception {
+ setUp(hs512Url);
+ HmacSigner hmac = new HmacSigner(header.getAlgorithm(), "secret");
+ jwt = hmac.sign(jwt);
+ assertEquals(hmac.verify(jwt.toString()), true);
+ }
+
+}
diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java
new file mode 100644
index 000000000..446212872
--- /dev/null
+++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/PlaintextSignerTest.java
@@ -0,0 +1,55 @@
+package org.mitre.jwt.signer.impl;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mitre.jwt.model.Jwt;
+import org.mitre.jwt.model.JwtClaims;
+import org.mitre.jwt.model.JwtHeader;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import junit.framework.TestCase;
+
+public class PlaintextSignerTest extends TestCase {
+
+ URL claimsUrl = this.getClass().getResource("/jwt/claims");
+ URL plaintextUrl = this.getClass().getResource("/jwt/plaintext");
+ Jwt jwt = null;
+ JwtClaims claims = null;
+ JwtHeader header = null;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp(URL url) throws Exception {
+ JsonParser parser = new JsonParser();
+ JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject();
+ JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ claims = new JwtClaims(claimsObject);
+ header = new JwtHeader(headerObject);
+ jwt = new Jwt(header, claims, null);
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testPlaintextSigner() throws Exception {
+ setUp(plaintextUrl);
+ PlaintextSigner plaintext = new PlaintextSigner();
+ jwt = plaintext.sign(jwt);
+ assertEquals(plaintext.verify(jwt.toString()), true);
+ }
+
+}
diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/RsaSignerTest.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/RsaSignerTest.java
new file mode 100644
index 000000000..cd74c577a
--- /dev/null
+++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/impl/RsaSignerTest.java
@@ -0,0 +1,99 @@
+package org.mitre.jwt.signer.impl;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mitre.jwt.model.Jwt;
+import org.mitre.jwt.model.JwtClaims;
+import org.mitre.jwt.model.JwtHeader;
+import org.mitre.jwt.signer.JwsAlgorithm;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+public class RsaSignerTest extends TestCase {
+
+
+ URL claimsUrl = this.getClass().getResource("/jwt/claims");
+ URL rs256Url = this.getClass().getResource("/jwt/rs256");
+ URL rs384Url = this.getClass().getResource("/jwt/rs384");
+ URL rs512Url = this.getClass().getResource("/jwt/rs512");
+ Jwt jwt = null;
+ JwtClaims claims = null;
+ JwtHeader header = null;
+ KeyPairGenerator keyGen;
+ KeyPair keyPair;
+ PublicKey publicKey;
+ PrivateKey privateKey;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp(URL url) throws Exception {
+ JsonParser parser = new JsonParser();
+ JsonObject claimsObject = parser.parse(new BufferedReader(new InputStreamReader(claimsUrl.openStream()))).getAsJsonObject();
+ JsonObject headerObject = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ claims = new JwtClaims(claimsObject);
+ header = new JwtHeader(headerObject);
+ jwt = new Jwt(header, claims, null);
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testRsaSigner256() throws Exception {
+ setUp(rs256Url);
+ keyGen = KeyPairGenerator.getInstance("RSA");
+ keyPair = keyGen.generateKeyPair();
+ publicKey = keyPair.getPublic();
+ privateKey = keyPair.getPrivate();
+ RsaSigner rsa = new RsaSigner(JwsAlgorithm.RS256.toString(), publicKey, privateKey);
+ jwt = rsa.sign(jwt);
+ assertEquals(rsa.verify(jwt.toString()), true);
+
+ }
+
+ @Test
+ public void testRsaSigner384() throws Exception{
+ setUp(rs384Url);
+ keyGen = KeyPairGenerator.getInstance("RSA");
+ keyPair = keyGen.generateKeyPair();
+ publicKey = keyPair.getPublic();
+ privateKey = keyPair.getPrivate();
+ RsaSigner rsa = new RsaSigner(JwsAlgorithm.RS384.toString(), publicKey, privateKey);
+ jwt = rsa.sign(jwt);
+ assertEquals(rsa.verify(jwt.toString()), true);
+
+ }
+
+ @Test
+ public void testRsaSigner512() throws Exception{
+ setUp(rs512Url);
+ keyGen = KeyPairGenerator.getInstance("RSA");
+ keyPair = keyGen.generateKeyPair();
+ publicKey = keyPair.getPublic();
+ privateKey = keyPair.getPrivate();
+ RsaSigner rsa = new RsaSigner(JwsAlgorithm.RS512.toString(), publicKey, privateKey);
+ jwt = rsa.sign(jwt);
+ assertEquals(rsa.verify(jwt.toString()), true);
+
+ }
+
+
+}
diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java b/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java
new file mode 100644
index 000000000..95391cea0
--- /dev/null
+++ b/openid-connect-common/src/test/java/org/mitre/jwt/signer/service/impl/DynamicJwtSigningAndValidationServiceTest.java
@@ -0,0 +1,64 @@
+package org.mitre.jwt.signer.service.impl;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.security.Key;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mitre.jwt.signer.JwtSigner;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+public class DynamicJwtSigningAndValidationServiceTest extends TestCase {
+
+ URL x509Url = this.getClass().getResource("/x509/x509Cert");
+ URL jwkUrl = this.getClass().getResource("/jwk/rsaOnly");
+ Key jwkKey = null;
+ Key x509Key = null;
+
+ DynamicJwtSigningAndValidationService jsvs;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Test method for {@link org.mitre.util.Utility#retrieveJwk(java.lang.String)}.
+ * @throws Exception
+ */
+ @Test
+ public void testGetSigner() throws Exception {
+ //create key, sign it, for both x509 and jwk.
+ /* jsvs.setX509SigningUrl(x509Url.getPath());
+ x509Key = jsvs.getSigningKey();
+ jsvs.setJwkSigningUrl(jwkUrl.getPath());
+ jwkKey = jsvs.getSigningKey();
+
+ JsonParser parser = new JsonParser();
+
+ String rsaStr = parser.parse(new BufferedReader(new InputStreamReader(jwkUrl.openStream()))).getAsString();
+ JwtSigner rsaSigner = jsvs.getSigner(rsaStr);
+
+ String x509Str = parser.parse(new BufferedReader(new InputStreamReader(x509Url.openStream()))).getAsString();
+ JwtSigner x509Signer = jsvs.getSigner(x509Str);*/
+ assertEquals("yo", "yo");
+ }
+
+}
diff --git a/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java b/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java
new file mode 100644
index 000000000..674e2306a
--- /dev/null
+++ b/openid-connect-common/src/test/java/org/mitre/util/UtilityTest.java
@@ -0,0 +1,206 @@
+/**
+ *
+ */
+package org.mitre.util;
+
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.List;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mitre.jwk.model.Jwk;
+import org.mitre.jwk.model.Rsa;
+import org.mitre.jwk.model.EC;
+import org.mitre.util.Utility;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import org.apache.commons.codec.binary.*;
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.jce.provider.JCEECPublicKey;
+
+/**
+ * @author DERRYBERRY
+ *
+ */
+public class UtilityTest extends TestCase{
+
+ URL url = this.getClass().getResource("/jwk/jwkSuccess");
+ URL certUrl = this.getClass().getResource("/x509/x509Cert");
+ URL rsaUrl = this.getClass().getResource("/jwk/rsaOnly");
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Test method for {@link org.mitre.util.Utility#retrieveJwk(java.lang.String)}.
+ * @throws Exception
+ */
+ @Test
+ public void testRetrieveJwk() throws Exception {
+
+ JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ JsonArray getArray = json.getAsJsonArray("jwk");
+
+ List list = Utility.retrieveJwk(url);
+
+ for(int i = 0; i < list.size(); i++){
+
+ Jwk jwk = list.get(i);
+ JsonObject object = getArray.get(i).getAsJsonObject();
+
+ assertEquals(object.get("alg").getAsString(), jwk.getAlg());
+ if(object.get("kid") != null){
+ assertEquals(object.get("kid").getAsString(), jwk.getKid());
+ }
+ if(object.get("use") != null){
+ assertEquals(object.get("use").getAsString(), jwk.getUse());
+ }
+
+ if(jwk instanceof Rsa){
+ assertEquals(object.get("mod").getAsString(), ((Rsa) jwk).getMod());
+ assertEquals(object.get("exp").getAsString(), ((Rsa) jwk).getExp());
+ }
+ else {
+ assertEquals(object.get("crv").getAsString(), ((EC) jwk).getCrv());
+ assertEquals(object.get("x").getAsString(), ((EC) jwk).getX());
+ assertEquals(object.get("y").getAsString(), ((EC) jwk).getY());
+ }
+ }
+ }
+
+ @Test
+ public void testMakeRsa() throws Exception{
+
+ JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ JsonArray getArray = json.getAsJsonArray("jwk");
+
+ List list = Utility.retrieveJwk(url);
+
+ for(int i = 0; i < list.size(); i++){
+ Jwk jwk = list.get(i);
+ JsonObject object = getArray.get(i).getAsJsonObject();
+
+ if(jwk instanceof Rsa){
+
+ RSAPublicKey key = ((RSAPublicKey) ((Rsa) jwk).getKey());
+
+ byte[] mod = Base64.decodeBase64(object.get("mod").getAsString());
+ BigInteger modInt = new BigInteger(mod);
+ assertEquals(modInt, key.getModulus());
+
+ byte[] exp = Base64.decodeBase64(object.get("exp").getAsString());
+ BigInteger expInt = new BigInteger(exp);
+ assertEquals(expInt, key.getPublicExponent());
+ }
+ }
+ }
+
+ @Test
+ public void testRetriveX509Key() throws Exception {
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ X509Certificate x509 = (X509Certificate) factory.generateCertificate(certUrl.openStream());
+ Key key = Utility.retrieveX509Key(certUrl);
+ assertEquals(x509.getPublicKey(), key);
+ assertEquals("RSA", key.getAlgorithm());
+ assertEquals("X.509", key.getFormat());
+ }
+
+ public void testRetriveJwkKey() throws Exception {
+ Key key = Utility.retrieveJwkKey(rsaUrl);
+
+ JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(rsaUrl.openStream()))).getAsJsonObject();
+ JsonArray getArray = json.getAsJsonArray("jwk");
+ JsonObject object = getArray.get(0).getAsJsonObject();
+
+ byte[] modulusByte = Base64.decodeBase64(object.get("mod").getAsString());
+ BigInteger modulus = new BigInteger(modulusByte);
+ byte[] exponentByte = Base64.decodeBase64(object.get("exp").getAsString());
+ BigInteger exponent = new BigInteger(exponentByte);
+
+ RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
+ KeyFactory factory = KeyFactory.getInstance("RSA");
+ PublicKey pub = factory.generatePublic(spec);
+
+ assertEquals(pub, key);
+ }
+
+ //@Test
+ //public void testMakeEC() throws Exception{
+
+ /*JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(new BufferedReader(new InputStreamReader(url.openStream()))).getAsJsonObject();
+ JsonArray getArray = json.getAsJsonArray("jwk");
+
+ List list = Utility.retrieveJwk(url);
+
+ for(int i = 0; i < list.size(); i++){
+ Jwk jwk = list.get(i);
+ JsonObject object = getArray.get(i).getAsJsonObject();
+
+ if(jwk instanceof EC){
+
+ ECPublicKey key = ((ECPublicKey) ((EC) jwk).getKey());
+
+ byte[] xArray = Base64.decodeBase64(object.get("x").getAsString());
+ BigInteger xInt = new BigInteger(xArray);
+ byte[] yArray = Base64.decodeBase64(object.get("y").getAsString());
+ BigInteger yInt = new BigInteger(yArray);
+
+ String curveName = object.get("crv").getAsString();
+ ECNamedCurveParameterSpec curveSpec = ECNamedCurveTable.getParameterSpec(curveName);
+ ECCurve crv = curveSpec.getCurve();
+ BigInteger a = crv.getA().toBigInteger();
+ BigInteger b = crv.getB().toBigInteger();
+ int fieldSize = crv.getFieldSize();
+ BigInteger orderOfGen = curveSpec.getH();
+ int cofactor = Math.abs(curveSpec.getN().intValue());
+
+ assertEquals(a, key.getParams().getCurve().getA());
+ assertEquals(b, key.getParams().getCurve().getB());
+ assertEquals(fieldSize, key.getParams().getCurve().getField());
+ assertEquals(orderOfGen, key.getParams().getOrder());
+ assertEquals(cofactor, key.getParams().getCofactor());
+ assertEquals(xInt, key.getW().getAffineX());
+ assertEquals(yInt, key.getW().getAffineY());
+ }
+ }*/
+ //fail("method not implemented");
+ //}
+
+
+}
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwk/jwkFail b/openid-connect-common/src/test/resources/jwk/jwkFail
new file mode 100644
index 000000000..4a208df47
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwk/jwkFail
@@ -0,0 +1,15 @@
+ {"jwk":
+ [
+ {"alg":"never",
+ "crv":"gonna",
+ "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
+ "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
+ "use":"give",
+ "kid":"1"},
+
+ {"alg":"you",
+ "mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+ "exp":"up",
+ "kid":"rick astley"}
+ ]
+ }
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwk/jwkSuccess b/openid-connect-common/src/test/resources/jwk/jwkSuccess
new file mode 100644
index 000000000..1ad6f5d5f
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwk/jwkSuccess
@@ -0,0 +1,15 @@
+ {"jwk":
+ [
+ {"alg":"EC",
+ "crv":"P-256",
+ "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
+ "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
+ "use":"enc",
+ "kid":"1"},
+
+ {"alg":"RSA",
+ "mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+ "exp":"AQAB",
+ "kid":"2011-04-29"}
+ ]
+ }
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwk/rsaOnly b/openid-connect-common/src/test/resources/jwk/rsaOnly
new file mode 100644
index 000000000..a5f42177d
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwk/rsaOnly
@@ -0,0 +1,8 @@
+ {"jwk":
+ [
+ {"alg":"RSA",
+ "mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
+ "exp":"AQAB",
+ "kid":"2011-04-29"}
+ ]
+ }
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwt/claims b/openid-connect-common/src/test/resources/jwt/claims
new file mode 100644
index 000000000..11f69c7e2
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/claims
@@ -0,0 +1,6 @@
+{"iss":"joe",
+ "user_id":34252452623,
+ "aud":"yolo",
+ "exp":35324583457247,
+ "iat":43215325235,
+ "nonce":"howdy"}
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwt/hs256 b/openid-connect-common/src/test/resources/jwt/hs256
new file mode 100644
index 000000000..a4cdd0b17
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/hs256
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"HS256"}
diff --git a/openid-connect-common/src/test/resources/jwt/hs384 b/openid-connect-common/src/test/resources/jwt/hs384
new file mode 100644
index 000000000..68f175c1a
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/hs384
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"HS384"}
diff --git a/openid-connect-common/src/test/resources/jwt/hs512 b/openid-connect-common/src/test/resources/jwt/hs512
new file mode 100644
index 000000000..42c727e09
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/hs512
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"HS512"}
diff --git a/openid-connect-common/src/test/resources/jwt/plaintext b/openid-connect-common/src/test/resources/jwt/plaintext
new file mode 100644
index 000000000..e16befde3
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/plaintext
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"none"}
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwt/rs256 b/openid-connect-common/src/test/resources/jwt/rs256
new file mode 100644
index 000000000..1d069af3f
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/rs256
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"RS256"}
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/jwt/rs384 b/openid-connect-common/src/test/resources/jwt/rs384
new file mode 100644
index 000000000..21ceb32e6
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/rs384
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"RS384"}
diff --git a/openid-connect-common/src/test/resources/jwt/rs512 b/openid-connect-common/src/test/resources/jwt/rs512
new file mode 100644
index 000000000..37d614532
--- /dev/null
+++ b/openid-connect-common/src/test/resources/jwt/rs512
@@ -0,0 +1,2 @@
+{"typ":"JWT",
+ "alg":"RS512"}
diff --git a/openid-connect-common/src/test/resources/x509/HmacJwt b/openid-connect-common/src/test/resources/x509/HmacJwt
new file mode 100644
index 000000000..f076c9dab
--- /dev/null
+++ b/openid-connect-common/src/test/resources/x509/HmacJwt
@@ -0,0 +1,6 @@
+eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
+.
+eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
+cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
+.
+dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
\ No newline at end of file
diff --git a/openid-connect-common/src/test/resources/x509/x509Cert b/openid-connect-common/src/test/resources/x509/x509Cert
new file mode 100644
index 000000000..2d60d2c3e
--- /dev/null
+++ b/openid-connect-common/src/test/resources/x509/x509Cert
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICxDCCAi0CBECcV/wwDQYJKoZIhvcNAQEEBQAwgagxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVU
+ZXhhczEPMA0GA1UEBxMGQXVzdGluMSowKAYDVQQKEyFUaGUgVW5pdmVyc2l0eSBvZiBUZXhhcyBh
+dCBBdXN0aW4xKDAmBgNVBAsTH0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgU2VydmljZXMxIjAgBgNV
+BAMTGXhtbGdhdGV3YXkuaXRzLnV0ZXhhcy5lZHUwHhcNMDQwNTA4MDM0NjA0WhcNMDQwODA2MDM0
+NjA0WjCBqDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xKjAo
+BgNVBAoTIVRoZSBVbml2ZXJzaXR5IG9mIFRleGFzIGF0IEF1c3RpbjEoMCYGA1UECxMfSW5mb3Jt
+YXRpb24gVGVjaG5vbG9neSBTZXJ2aWNlczEiMCAGA1UEAxMZeG1sZ2F0ZXdheS5pdHMudXRleGFz
+LmVkdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsmc+6+NjLmanvh+FvBziYdBwTiz+d/DZ
+Uy2jyvij6f8Xly6zkhHLSsuBzw08wPzr2K+F359bf9T3uiZMuao//FBGtDrTYpvQwkn4PFZwSeY2
+Ynw4edxp1JEWT2zfOY+QJDfNgpsYQ9hrHDwqnpbMVVqjdBq5RgTKGhFBj9kxEq0CAwEAATANBgkq
+hkiG9w0BAQQFAAOBgQCPYGXF6oRbnjti3CPtjfwORoO7ab1QzNS9Z2rLMuPnt6POlm1A3UPEwCS8
+6flTlAqg19Sh47H7+Iq/LuzotKvUE5ugK52QRNMa4c0OSaO5UEM5EfVox1pT9tZV1Z3whYYMhThg
+oC4y/On0NUVMN5xfF/GpSACga/bVjoNvd8HWEg==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/openid-connect-server/.settings/org.eclipse.wst.common.component b/openid-connect-server/.settings/org.eclipse.wst.common.component
index 90211ce26..7becf4b04 100644
--- a/openid-connect-server/.settings/org.eclipse.wst.common.component
+++ b/openid-connect-server/.settings/org.eclipse.wst.common.component
@@ -5,6 +5,12 @@
+
+ uses
+
+
+ uses
+
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
index 544ddcde5..1665941b9 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
@@ -15,12 +15,16 @@
******************************************************************************/
package org.mitre.openid.connect.token;
+import java.security.NoSuchAlgorithmException;
import java.util.Date;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.mitre.openid.connect.model.IdToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.spi.LoggerFactoryBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
@@ -32,6 +36,8 @@ import com.google.common.base.Strings;
@Service
public class ConnectTokenEnhancer implements TokenEnhancer {
+ Logger logger = LoggerFactory.getLogger(ConnectTokenEnhancer.class);
+
@Autowired
private ConfigurationPropertiesBean configBean;
@@ -57,7 +63,12 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
token.getJwt().getClaims().setExpiration(token.getExpiration());
//TODO: check for client's preferred signer alg and use that
- jwtService.signJwt(token.getJwt());
+ try {
+ jwtService.signJwt(token.getJwt());
+ } catch (NoSuchAlgorithmException e) {
+ // couldn't sign token
+ logger.warn("Couldn't sign access token", e);
+ }
/**
* Authorization request scope MUST include "openid", but access token request
@@ -80,7 +91,11 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
// TODO: expiration? other fields?
//TODO: check for client's preferred signer alg and use that
- jwtService.signJwt(idToken);
+ try {
+ jwtService.signJwt(idToken);
+ } catch (NoSuchAlgorithmException e) {
+ logger.warn("Couldn't sign id token", e);
+ }
token.setIdToken(idToken);
}
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java
index aa859b3cc..346626ccd 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java
@@ -15,6 +15,8 @@
******************************************************************************/
package org.mitre.openid.connect.web;
+import java.security.NoSuchAlgorithmException;
+
import javax.servlet.http.HttpServletRequest;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
@@ -48,10 +50,14 @@ public class CheckIDEndpoint {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- if (!jwtSignerService.validateSignature(tokenString)) {
- // can't validate
- throw new InvalidJwtSignatureException("The Signature could not be validated.");
- }
+ try {
+ if (!jwtSignerService.validateSignature(tokenString)) {
+ // can't validate
+ throw new InvalidJwtSignatureException("The Signature could not be validated.");
+ }
+ } catch (NoSuchAlgorithmException e) {
+ throw new InvalidJwtSignatureException("The Signature could not be validated: no such algorithm.");
+ }
// it's a valid signature, parse the token
IdToken token = IdToken.parse(tokenString);
diff --git a/openid-connect-server/src/test/java/org/mitre/jwt/JwtTest.java b/openid-connect-server/src/test/java/org/mitre/jwt/JwtTest.java
index f565fbd33..caefa4104 100644
--- a/openid-connect-server/src/test/java/org/mitre/jwt/JwtTest.java
+++ b/openid-connect-server/src/test/java/org/mitre/jwt/JwtTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertThat;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
@@ -198,7 +199,7 @@ public class JwtTest {
}
@Test
- public void testToStringPlaintext() {
+ public void testToStringPlaintext() throws NoSuchAlgorithmException {
Jwt jwt = new Jwt();
jwt.getHeader().setAlgorithm("none");
jwt.getClaims().setExpiration(new Date(1300819380L * 1000L));