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 7bc2868c4..4521922b2 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 @@ -67,6 +67,7 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.util.WebUtils; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** @@ -311,12 +312,17 @@ public class AbstractOIDCAuthenticationFilter extends logger.debug("from TokenEndpoint jsonString = " + jsonString); JsonElement jsonRoot = new JsonParser().parse(jsonString); + if (!jsonRoot.isJsonObject()) { + throw new AuthenticationServiceException("Token Endpoint did not return a JSON object: " + jsonRoot); + } - if (jsonRoot.getAsJsonObject().get("error") != null) { + JsonObject tokenResponse = jsonRoot.getAsJsonObject(); + + if (tokenResponse.get("error") != null) { // Handle error - String error = jsonRoot.getAsJsonObject().get("error") + String error = tokenResponse.get("error") .getAsString(); logger.error("Token Endpoint returned: " + error); @@ -328,49 +334,66 @@ public class AbstractOIDCAuthenticationFilter extends // Extract the id_token to insert into the // OpenIdConnectAuthenticationToken - IdToken idToken = null; - JwtSigningAndValidationService jwtValidator = getValidatorForServer(serverConfig); + // get out all the token strings + String accessTokenValue = null; + String idTokenValue = null; + String refreshTokenValue = null; - if (jsonRoot.getAsJsonObject().get("id_token") != null) { - - try { - idToken = IdToken.parse(jsonRoot.getAsJsonObject().get("id_token").getAsString()); - - } catch (AuthenticationServiceException 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); - } - - if(jwtValidator.validateSignature(jsonRoot.getAsJsonObject().get("id_token").getAsString()) == false) { - throw new AuthenticationServiceException("Signature not validated"); - } - if(idToken.getClaims().getIssuer() == null) { - throw new AuthenticationServiceException("Issuer is null"); - } - if(!idToken.getClaims().getIssuer().equals(serverConfig.getIssuer())){ - throw new AuthenticationServiceException("Issuers do not match"); - } - if(jwtValidator.isJwtExpired(idToken)) { - throw new AuthenticationServiceException("Id Token is expired"); - } - if(jwtValidator.validateIssuedAt(idToken) == false) { - throw new AuthenticationServiceException("Id Token issuedAt failed"); - } - + if (tokenResponse.has("access_token")) { + accessTokenValue = tokenResponse.get("access_token").getAsString(); + } else { + throw new AuthenticationServiceException("Token Endpoint did not return an access_token: " + jsonString); + } + + if (tokenResponse.has("id_token")) { + idTokenValue = tokenResponse.get("id_token").getAsString(); } else { - - // An error is unlikely, but it good security to check - logger.error("Token Endpoint did not return an id_token"); - throw new AuthenticationServiceException("Token Endpoint did not return an id_token"); } + if (tokenResponse.has("refresh_token")) { + refreshTokenValue = tokenResponse.get("refresh_token").getAsString(); + } + + JwtSigningAndValidationService jwtValidator = getValidatorForServer(serverConfig); + IdToken idToken = null; + + try { + idToken = IdToken.parse(idTokenValue); + + } catch (AuthenticationServiceException 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); + } + + // validate our ID Token over a number of tests + + if(!jwtValidator.validateSignature(idToken.toString())) { + throw new AuthenticationServiceException("Signature not validated"); + } + + if(idToken.getClaims().getIssuer() == null) { + throw new AuthenticationServiceException("Issuer is null"); + } + + if(!idToken.getClaims().getIssuer().equals(serverConfig.getIssuer())){ + throw new AuthenticationServiceException("Issuers do not match"); + } + + if(jwtValidator.isJwtExpired(idToken)) { + throw new AuthenticationServiceException("Id Token is expired"); + } + + if(!jwtValidator.validateIssuedAt(idToken)) { + throw new AuthenticationServiceException("Id Token issuedAt failed"); + } + // 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 @@ -409,12 +432,14 @@ public class AbstractOIDCAuthenticationFilter extends // construct an OpenIdConnectAuthenticationToken and return // a Authentication object w/the userId and the idToken - OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(userId, idToken); + OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(userId, idTokenValue, accessTokenValue, refreshTokenValue); Authentication authentication = this.getAuthenticationManager().authenticate(token); return authentication; + + } } diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationProvider.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationProvider.java index ee1543956..ecbcc3cf3 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationProvider.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationProvider.java @@ -68,9 +68,8 @@ public class OpenIdConnectAuthenticationProvider implements UserDetails userDetails = userDetailsService.loadUserDetails(token); return new OpenIdConnectAuthenticationToken(userDetails, - authoritiesMapper.mapAuthorities(userDetails - .getAuthorities()), token.getUserId(), - token.getIdToken()); + authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), token.getUserId(), + token.getIdTokenValue(), token.getAccessTokenValue(), token.getRefreshTokenValue()); } return null; diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationToken.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationToken.java index 63b53c5be..d43f0d444 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationToken.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationToken.java @@ -25,17 +25,18 @@ import org.springframework.security.core.SpringSecurityCoreVersion; /** * - * @author nemonik + * @author Michael Walsh, Justin Richer * */ -public class OpenIdConnectAuthenticationToken extends - AbstractAuthenticationToken { +public class OpenIdConnectAuthenticationToken extends AbstractAuthenticationToken { + private static final long serialVersionUID = 22100073066377804L; + private final Object principle; - private final IdToken idToken; - private final String userId; - - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final String idTokenValue; // string representation of the id token + private final String accessTokenValue; // string representation of the access token + private final String refreshTokenValue; // string representation of the refresh token + private final String userId; // user id (parsed from the id token) /** * Constructs OpenIdConnectAuthenticationToken provided @@ -47,13 +48,15 @@ public class OpenIdConnectAuthenticationToken extends */ public OpenIdConnectAuthenticationToken(Object principle, Collection authorities, String userId, - IdToken idToken) { + String idTokenValue, String accessTokenValue, String refreshTokenValue) { super(authorities); this.principle = principle; this.userId = userId; - this.idToken = idToken; + this.idTokenValue = idTokenValue; + this.accessTokenValue = accessTokenValue; + this.refreshTokenValue = refreshTokenValue; setAuthenticated(true); } @@ -64,13 +67,15 @@ public class OpenIdConnectAuthenticationToken extends * @param idToken * @param userId */ - public OpenIdConnectAuthenticationToken(String userId, IdToken idToken) { + public OpenIdConnectAuthenticationToken(String userId, String idTokenValue, String accessTokenValue, String refreshTokenValue) { super(new ArrayList(0)); this.principle = userId; this.userId = userId; - this.idToken = idToken; + this.idTokenValue = idTokenValue; + this.accessTokenValue = accessTokenValue; + this.refreshTokenValue = refreshTokenValue; setAuthenticated(false); } @@ -82,11 +87,7 @@ public class OpenIdConnectAuthenticationToken extends */ @Override public Object getCredentials() { - return null; - } - - public IdToken getIdToken() { - return idToken; + return accessTokenValue; } /* @@ -103,4 +104,27 @@ public class OpenIdConnectAuthenticationToken extends public String getUserId() { return userId; } + + /** + * @return the idTokenValue + */ + public String getIdTokenValue() { + return idTokenValue; + } + + /** + * @return the accessTokenValue + */ + public String getAccessTokenValue() { + return accessTokenValue; + } + + /** + * @return the refreshTokenValue + */ + public String getRefreshTokenValue() { + return refreshTokenValue; + } + + } \ No newline at end of file