smart client
parent
3e810cb5dc
commit
65dc3daaf8
|
@ -1,8 +1,8 @@
|
|||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="openid-connect-client">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/test/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/test/resources"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[2.9.1.201203220057-RELEASE]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
<enableImports><![CDATA[false]]></enableImports>
|
||||
<configs>
|
||||
<config>spring-servlet.xml</config>
|
||||
</configs>
|
||||
<configSets>
|
||||
</configSets>
|
||||
</beansProjectDescription>
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -376,11 +385,12 @@ 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();
|
||||
|
||||
|
@ -457,42 +467,45 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
|
||||
// Extract the id_token to insert into the
|
||||
// OpenIdConnectAuthenticationToken
|
||||
|
||||
|
||||
Cookie nonceSignatureCookie = WebUtils.getCookie(request,
|
||||
NONCE_SIGNATURE_COOKIE_NAME);
|
||||
|
||||
IdToken idToken = null;
|
||||
|
||||
DynamicJwtSigningAndValidationService dynamic = new DynamicJwtSigningAndValidationService(null, null, null);
|
||||
OIDCServerConfiguration oidc = new OIDCServerConfiguration();
|
||||
|
||||
if (jsonRoot.getAsJsonObject().get("id_token") != null) {
|
||||
|
||||
try {
|
||||
idToken = IdToken.parse(jsonRoot.getAsJsonObject()
|
||||
.get("id_token").getAsString());
|
||||
if(dynamic.validateSignature(jsonRoot.getAsJsonObject().get("id_token").getAsString())
|
||||
&&
|
||||
dynamic.validateIssuedJwt(idToken, oidc.getIssuer())
|
||||
&&
|
||||
dynamic.validateAudience(idToken, oidc.getClientId())
|
||||
&&
|
||||
dynamic.isJwtExpired(idToken)
|
||||
&&
|
||||
dynamic.validateIssuedAt(idToken)
|
||||
&&
|
||||
dynamic.validateNonce(idToken, nonceSignatureCookie.getValue())){
|
||||
|
||||
try {
|
||||
idToken = IdToken.parse(jsonRoot.getAsJsonObject().get("id_token").getAsString());
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
List<String> 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 {
|
||||
|
@ -505,100 +518,58 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
"Token Endpoint did not return a token_id");
|
||||
}
|
||||
|
||||
// Handle Check ID Endpoint interaction
|
||||
|
||||
|
||||
httpClient = new DefaultHttpClient();
|
||||
|
||||
httpClient.getParams().setParameter("http.socket.timeout",
|
||||
new Integer(httpSocketTimeout));
|
||||
|
||||
factory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
restTemplate = new RestTemplate(factory);
|
||||
|
||||
form = new LinkedMultiValueMap<String, String>();
|
||||
|
||||
form.add("access_token", jsonRoot.getAsJsonObject().get("id_token")
|
||||
.getAsString());
|
||||
|
||||
jsonString = null;
|
||||
|
||||
try {
|
||||
jsonString = restTemplate.postForObject(
|
||||
serverConfig.getCheckIDEndpointURI(), form,
|
||||
String.class);
|
||||
} catch (HttpClientErrorException httpClientErrorException) {
|
||||
|
||||
// Handle error
|
||||
|
||||
logger.error("Check ID Endpoint error response: "
|
||||
+ httpClientErrorException.getStatusText() + " : "
|
||||
+ httpClientErrorException.getMessage());
|
||||
|
||||
throw new AuthenticationServiceException("Unable check token.");
|
||||
}
|
||||
|
||||
jsonRoot = new JsonParser().parse(jsonString);
|
||||
|
||||
// String iss = jsonRoot.getAsJsonObject().get("iss")
|
||||
// .getAsString();
|
||||
String userId = jsonRoot.getAsJsonObject().get("user_id")
|
||||
.getAsString();
|
||||
//String userId = jsonRoot.getAsJsonObject().get("user_id")
|
||||
// .getAsString();
|
||||
// String aud = jsonRoot.getAsJsonObject().get("aud")
|
||||
// .getAsString();
|
||||
String nonce = jsonRoot.getAsJsonObject().get("nonce")
|
||||
.getAsString();
|
||||
//String nonce = jsonRoot.getAsJsonObject().get("nonce")
|
||||
// .getAsString();
|
||||
// String exp = jsonRoot.getAsJsonObject().get("exp")
|
||||
// .getAsString();
|
||||
|
||||
// Compare returned ID Token to signed session cookie
|
||||
// to detect ID Token replay by third parties.
|
||||
|
||||
Cookie nonceSignatureCookie = WebUtils.getCookie(request,
|
||||
NONCE_SIGNATURE_COOKIE_NAME);
|
||||
|
||||
if (nonceSignatureCookie != null) {
|
||||
|
||||
String sigText = nonceSignatureCookie.getValue();
|
||||
String sigText = nonceSignatureCookie.getValue();
|
||||
|
||||
if (sigText != null && !sigText.isEmpty()) {
|
||||
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.");
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.error(NONCE_SIGNATURE_COOKIE_NAME
|
||||
+ " was found, but was null or empty.");
|
||||
if (!verify(signer, publicKey, idToken.getClaims().getNonce(), 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(
|
||||
NONCE_SIGNATURE_COOKIE_NAME
|
||||
+ " was found, but was null or empty.");
|
||||
"Possible replay attack detected! "
|
||||
+ "The comparison of the nonce in the returned "
|
||||
+ "ID Token to the signed session "
|
||||
+ NONCE_SIGNATURE_COOKIE_NAME
|
||||
+ " failed.");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
logger.error(NONCE_SIGNATURE_COOKIE_NAME
|
||||
+ " cookie was not found.");
|
||||
+ " was found, but was null or empty.");
|
||||
|
||||
throw new AuthenticationServiceException(
|
||||
NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
|
||||
NONCE_SIGNATURE_COOKIE_NAME
|
||||
+ " was found, but was null or empty.");
|
||||
}
|
||||
|
||||
// Create an Authentication object for the token, and
|
||||
// return.
|
||||
|
||||
OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(
|
||||
userId, idToken);
|
||||
idToken.getTokenClaims().getUserId(), idToken);
|
||||
|
||||
Authentication authentication = this.getAuthenticationManager()
|
||||
.authenticate(token);
|
||||
|
|
|
@ -97,9 +97,14 @@ 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 {
|
||||
|
||||
|
|
|
@ -108,10 +108,15 @@ 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 {
|
||||
|
||||
|
|
|
@ -16,19 +16,19 @@
|
|||
package org.mitre.openid.connect.client;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.Key;
|
||||
|
||||
import org.mitre.jwt.signer.service.impl.DynamicJwtSigningAndValidationService;
|
||||
import org.mitre.util.Utility;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* @author nemonik
|
||||
*
|
||||
*/
|
||||
public class OIDCServerConfiguration {
|
||||
|
||||
DynamicJwtSigningAndValidationService dynamic;
|
||||
|
||||
private String authorizationEndpointURI;
|
||||
|
||||
|
@ -40,6 +40,8 @@ public class OIDCServerConfiguration {
|
|||
|
||||
private String clientId;
|
||||
|
||||
private String issuer;
|
||||
|
||||
private String x509EncryptUrl;
|
||||
|
||||
private String x509SigningUrl;
|
||||
|
@ -63,6 +65,10 @@ public class OIDCServerConfiguration {
|
|||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public String getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
|
@ -84,6 +90,10 @@ public class OIDCServerConfiguration {
|
|||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public void setIssuer(String issuer) {
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
@ -169,11 +179,18 @@ public class OIDCServerConfiguration {
|
|||
+ authorizationEndpointURI + ", tokenEndpointURI="
|
||||
+ tokenEndpointURI + ", checkIDEndpointURI="
|
||||
+ checkIDEndpointURI + ", clientSecret=" + clientSecret
|
||||
+ ", clientId=" + clientId + ", x509EncryptedUrl="
|
||||
+ ", 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<OpenIdConnectAuthenticationToken> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -101,4 +101,14 @@ public class OIDCServerConfigurationTest extends TestCase {
|
|||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"}
|
||||
]
|
||||
}
|
|
@ -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"}
|
||||
]
|
||||
}
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
|
@ -11,4 +11,3 @@
|
|||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
|
|
|
@ -2,6 +2,5 @@
|
|||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="openid-connect-common">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/test/java"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
|
|
|
@ -15,12 +15,7 @@
|
|||
******************************************************************************/
|
||||
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;
|
||||
|
|
|
@ -17,7 +17,6 @@ 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;
|
||||
|
@ -72,6 +71,39 @@ public interface JwtSigningAndValidationService {
|
|||
* @return the signed jwt
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,5 +50,36 @@ public abstract class AbstractJwtSigningAndValidationService implements JwtSigni
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ 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;
|
||||
|
||||
|
@ -33,9 +34,6 @@ public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAnd
|
|||
|
||||
private Map<String, ? extends JwtSigner> signers;
|
||||
|
||||
private String signingAlgorithm;
|
||||
|
||||
|
||||
public DynamicJwtSigningAndValidationService(String x509SigningUrl, String jwkSigningUrl, String clientSecret) throws Exception {
|
||||
setX509SigningUrl(x509SigningUrl);
|
||||
setJwkSigningUrl(jwkSigningUrl);
|
||||
|
@ -143,4 +141,35 @@ public class DynamicJwtSigningAndValidationService extends AbstractJwtSigningAnd
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ 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;
|
||||
|
||||
|
@ -163,4 +163,35 @@ public class JwtSigningAndValidationServiceDefault extends AbstractJwtSigningAnd
|
|||
public Map<String, ? extends JwtSigner> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.mitre.openid.connect.token;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -30,6 +31,7 @@ import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
|||
import org.mitre.openid.connect.model.IdToken;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
|
@ -112,10 +114,13 @@ public class ConnectAuthCodeTokenGranter implements TokenGranter {
|
|||
* @param parameters
|
||||
* @param clientId
|
||||
* @param scope
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws AuthenticationException
|
||||
* @throws InvalidGrantException
|
||||
*/
|
||||
@Override
|
||||
public OAuth2AccessToken grant(String grantType,
|
||||
Map<String, String> parameters, String clientId, Set<String> scope) {
|
||||
Map<String, String> parameters, String clientId, Set<String> scope) throws NoSuchAlgorithmException, InvalidGrantException, AuthenticationException {
|
||||
|
||||
if (!GRANT_TYPE.equals(grantType)) {
|
||||
return null;
|
||||
|
|
|
@ -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;
|
||||
|
@ -44,7 +46,7 @@ public class CheckIDEndpoint {
|
|||
|
||||
@PreAuthorize("hasRole('ROLE_USER')")
|
||||
@RequestMapping("/checkid")
|
||||
public ModelAndView checkID(@RequestParam("access_token") String tokenString, ModelAndView mav, HttpServletRequest request) {
|
||||
public ModelAndView checkID(@RequestParam("access_token") String tokenString, ModelAndView mav, HttpServletRequest request) throws NoSuchAlgorithmException {
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue