stripped out check id endpoint interaction as it deprecated, refactored nonce checking based on spec change, pull user_id as id_token token claim
parent
901d3afff4
commit
f9558f0955
|
@ -63,9 +63,7 @@ import com.google.gson.JsonElement;
|
|||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The OpenID Connect Authentication Filter
|
||||
*
|
||||
* See README.md to to configure
|
||||
* Abstract OpenID Connect Authentication Filter class
|
||||
*
|
||||
* @author nemonik
|
||||
*
|
||||
|
@ -74,10 +72,11 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
AbstractAuthenticationProcessingFilter {
|
||||
|
||||
/**
|
||||
* Used to remove parameters from a Request before passing it down the chain...
|
||||
* Used to remove parameters from a Request before passing it down the
|
||||
* chain...
|
||||
*
|
||||
* @author nemonik
|
||||
*
|
||||
*
|
||||
*/
|
||||
class SanatizedRequest extends HttpServletRequestWrapper {
|
||||
|
||||
|
@ -128,8 +127,8 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
return super.getParameterValues(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected final static int HTTP_SOCKET_TIMEOUT = 30000;
|
||||
protected final static String SCOPE = "openid";
|
||||
protected final static int KEY_SIZE = 1024;
|
||||
|
@ -154,7 +153,7 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
|
||||
List<String> ignore = (ignoreFields != null) ? Arrays
|
||||
.asList(ignoreFields) : null;
|
||||
|
||||
|
||||
boolean isFirst = true;
|
||||
|
||||
StringBuffer sb = request.getRequestURL();
|
||||
|
@ -360,8 +359,10 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
HttpServletResponse response) throws AuthenticationException,
|
||||
IOException, ServletException {
|
||||
|
||||
logger.debug("Request: " + request.getRequestURI() + (StringUtils.isNotBlank(request.getQueryString()) ? "?"
|
||||
+ request.getQueryString() : "") );
|
||||
logger.debug("Request: "
|
||||
+ request.getRequestURI()
|
||||
+ (StringUtils.isNotBlank(request.getQueryString()) ? "?"
|
||||
+ request.getQueryString() : ""));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -399,6 +400,7 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
// ((DefaultHttpClient)
|
||||
// httpClient).getCredentialsProvider().setCredentials(AuthScope.ANY,
|
||||
// credentials);
|
||||
//
|
||||
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClient);
|
||||
|
@ -438,6 +440,8 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
"Unable to obtain Access Token.");
|
||||
}
|
||||
|
||||
logger.debug("from TokenEndpoint jsonString = " + jsonString);
|
||||
|
||||
JsonElement jsonRoot = new JsonParser().parse(jsonString);
|
||||
|
||||
if (jsonRoot.getAsJsonObject().get("error") != null) {
|
||||
|
@ -455,8 +459,7 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
|
||||
} else {
|
||||
|
||||
// Extract the id_token to insert into the
|
||||
// OpenIdConnectAuthenticationToken
|
||||
// Extract the id_token
|
||||
|
||||
IdToken idToken = null;
|
||||
|
||||
|
@ -504,54 +507,22 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
throw new AuthenticationServiceException(
|
||||
"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 aud = jsonRoot.getAsJsonObject().get("aud")
|
||||
// .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.
|
||||
|
||||
// Clients are required to compare nonce claim in ID token to
|
||||
// the nonce sent in the Authorization request. The client
|
||||
// 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"
|
||||
//
|
||||
// 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);
|
||||
|
@ -572,8 +543,7 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
"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 {
|
||||
|
@ -587,16 +557,19 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
|
||||
} else {
|
||||
|
||||
logger.error(NONCE_SIGNATURE_COOKIE_NAME
|
||||
+ " cookie was not found.");
|
||||
logger.error(NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
|
||||
|
||||
throw new AuthenticationServiceException(
|
||||
NONCE_SIGNATURE_COOKIE_NAME + " cookie was not found.");
|
||||
}
|
||||
|
||||
// Create an Authentication object for the token, and
|
||||
// return.
|
||||
}
|
||||
|
||||
// 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/
|
||||
|
||||
OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(
|
||||
userId, idToken);
|
||||
|
||||
|
@ -704,4 +677,4 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,10 +64,7 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
|
|||
|
||||
Assert.notNull(oidcServerConfig.getTokenEndpointURI(),
|
||||
"A Token ID Endpoint URI must be supplied");
|
||||
|
||||
Assert.notNull(oidcServerConfig.getCheckIDEndpointURI(),
|
||||
"A Check ID Endpoint URI must be supplied");
|
||||
|
||||
|
||||
Assert.notNull(oidcServerConfig.getClientId(),
|
||||
"A Client ID must be supplied");
|
||||
|
||||
|
@ -113,10 +110,6 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
|
|||
oidcServerConfig.setAuthorizationEndpointURI(authorizationEndpointURI);
|
||||
}
|
||||
|
||||
public void setCheckIDEndpointURI(String checkIDEndpointURI) {
|
||||
oidcServerConfig.setCheckIDEndpointURI(checkIDEndpointURI);
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
oidcServerConfig.setClientId(clientId);
|
||||
}
|
||||
|
|
|
@ -129,8 +129,7 @@ public class OIDCAuthenticationUsingChooserFilter extends
|
|||
// The Client is configured to support this Issuer
|
||||
// Identifier
|
||||
|
||||
Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME,
|
||||
issuer);
|
||||
Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME, issuer);
|
||||
response.addCookie(issuerCookie);
|
||||
|
||||
handleAuthorizationRequest(new SanatizedRequest(request,
|
||||
|
@ -157,7 +156,7 @@ public class OIDCAuthenticationUsingChooserFilter extends
|
|||
urlVariables.put("redirect_uri",
|
||||
OIDCAuthenticationUsingChooserFilter.buildRedirectURI(
|
||||
request, null));
|
||||
|
||||
|
||||
urlVariables.put("client_id", accountChooserClientID);
|
||||
|
||||
response.sendRedirect(OIDCAuthenticationUsingChooserFilter
|
||||
|
|
|
@ -25,8 +25,6 @@ public class OIDCServerConfiguration {
|
|||
|
||||
private String tokenEndpointURI;
|
||||
|
||||
private String checkIDEndpointURI;
|
||||
|
||||
private String clientSecret;
|
||||
|
||||
private String clientId;
|
||||
|
@ -35,10 +33,6 @@ public class OIDCServerConfiguration {
|
|||
return authorizationEndpointURI;
|
||||
}
|
||||
|
||||
public String getCheckIDEndpointURI() {
|
||||
return checkIDEndpointURI;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
@ -49,16 +43,12 @@ public class OIDCServerConfiguration {
|
|||
|
||||
public String getTokenEndpointURI() {
|
||||
return tokenEndpointURI;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAuthorizationEndpointURI(String authorizationEndpointURI) {
|
||||
this.authorizationEndpointURI = authorizationEndpointURI;
|
||||
}
|
||||
|
||||
public void setCheckIDEndpointURI(String checkIDEndpointURI) {
|
||||
this.checkIDEndpointURI = checkIDEndpointURI;
|
||||
}
|
||||
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
@ -75,9 +65,8 @@ public class OIDCServerConfiguration {
|
|||
public String toString() {
|
||||
return "OIDCServerConfiguration [authorizationEndpointURI="
|
||||
+ authorizationEndpointURI + ", tokenEndpointURI="
|
||||
+ tokenEndpointURI + ", checkIDEndpointURI="
|
||||
+ checkIDEndpointURI + ", clientSecret=" + clientSecret
|
||||
+ tokenEndpointURI + ", clientSecret=" + clientSecret
|
||||
+ ", clientId=" + clientId + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ import org.springframework.util.Assert;
|
|||
|
||||
/**
|
||||
* @author nemonik
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class OpenIdConnectAuthenticationProvider implements
|
||||
AuthenticationProvider, InitializingBean {
|
||||
|
|
|
@ -24,10 +24,9 @@ import org.springframework.security.core.GrantedAuthority;
|
|||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author nemonik
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class OpenIdConnectAuthenticationToken extends
|
||||
AbstractAuthenticationToken {
|
||||
|
@ -37,42 +36,48 @@ public class OpenIdConnectAuthenticationToken extends
|
|||
private final String userId;
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs OpenIdConnectAuthenticationToken provided
|
||||
*
|
||||
* @param principle
|
||||
* @param authorities
|
||||
* @param userId
|
||||
* @param idToken
|
||||
*/
|
||||
public OpenIdConnectAuthenticationToken(Object principle,
|
||||
Collection<? extends GrantedAuthority> authorities,
|
||||
String userId, IdToken idToken) {
|
||||
Collection<? extends GrantedAuthority> authorities, String userId,
|
||||
IdToken idToken) {
|
||||
|
||||
super(authorities);
|
||||
|
||||
|
||||
this.principle = principle;
|
||||
this.userId = userId;
|
||||
this.idToken = idToken;
|
||||
|
||||
setAuthenticated(true);
|
||||
|
||||
setAuthenticated(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs OpenIdConnectAuthenticationToken provided
|
||||
*
|
||||
* @param idToken
|
||||
* @param userId
|
||||
*/
|
||||
public OpenIdConnectAuthenticationToken(String userId, IdToken idToken) {
|
||||
|
||||
|
||||
super(new ArrayList<GrantedAuthority>(0));
|
||||
|
||||
this.principle = userId;
|
||||
this.userId = userId;
|
||||
this.idToken = idToken;
|
||||
|
||||
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.core.Authentication#getCredentials()
|
||||
*/
|
||||
@Override
|
||||
|
@ -84,7 +89,9 @@ public class OpenIdConnectAuthenticationToken extends
|
|||
return idToken;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.core.Authentication#getPrincipal()
|
||||
*/
|
||||
@Override
|
||||
|
@ -96,4 +103,4 @@ public class OpenIdConnectAuthenticationToken extends
|
|||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="openid">
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
<dependent-module archiveName="spring-security-oauth2-1.0.0.BUILD-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/spring-security-oauth2/spring-security-oauth2">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module archiveName="openid-connect-common-0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/openid-connect-common/openid-connect-common">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<property name="java-output-path" value="/openid/target/classes"/>
|
||||
<property name="context-root" value="openid-connect-server"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="openid">
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
<property name="java-output-path" value="/openid/target/classes"/>
|
||||
<property name="context-root" value="openid-connect-server"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
|
|
Loading…
Reference in New Issue