ID Token carried through as parsed JWT instead of string, closes #832

pull/820/merge
Justin Richer 2015-06-24 15:36:55 -04:00
parent f4a1b27e2e
commit b4520c170e
4 changed files with 76 additions and 33 deletions

View File

@ -584,7 +584,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken // construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken
OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idTokenValue, accessTokenValue, refreshTokenValue); OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idToken, accessTokenValue, refreshTokenValue);
Authentication authentication = this.getAuthenticationManager().authenticate(token); Authentication authentication = this.getAuthenticationManager().authenticate(token);

View File

@ -62,30 +62,23 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider {
OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication; OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication;
try { // get the ID Token value out
JWT idToken = token.getIdToken();
// get the ID Token value out
String idTokenString = token.getIdTokenValue(); // load the user info if we can
JWT idToken = JWTParser.parse(idTokenString); UserInfo userInfo = userInfoFetcher.loadUserInfo(token);
// load the user info if we can if (userInfo == null) {
UserInfo userInfo = userInfoFetcher.loadUserInfo(token); // user info not found -- could be an error, could be fine
} else {
if (userInfo == null) { // if we found userinfo, double check it
// user info not found -- could be an error, could be fine if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getSub())) {
} else { // the userinfo came back and the user_id fields don't match what was in the id_token
// if we found userinfo, double check it throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + token.getSub() + " / " + userInfo.getSub());
if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getSub())) {
// the userinfo came back and the user_id fields don't match what was in the id_token
throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + token.getSub() + " / " + userInfo.getSub());
}
} }
return createAuthenticationToken(token, authoritiesMapper.mapAuthorities(idToken, userInfo), userInfo);
} catch (ParseException e) {
logger.error("Unable to parse ID token in the token");
return null;
} }
return createAuthenticationToken(token, authoritiesMapper.mapAuthorities(idToken, userInfo), userInfo);
} }
return null; return null;
@ -104,7 +97,7 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider {
return new OIDCAuthenticationToken(token.getSub(), return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(), token.getIssuer(),
userInfo, authorities, userInfo, authorities,
token.getIdTokenValue(), token.getAccessTokenValue(), token.getRefreshTokenValue()); token.getIdToken(), token.getAccessTokenValue(), token.getRefreshTokenValue());
} }
/** /**

View File

@ -16,6 +16,10 @@
*******************************************************************************/ *******************************************************************************/
package org.mitre.openid.connect.model; package org.mitre.openid.connect.model;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.persistence.Basic; import javax.persistence.Basic;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Convert; import javax.persistence.Convert;
@ -32,6 +36,7 @@ import javax.persistence.Table;
import org.mitre.openid.connect.model.convert.JsonObjectStringConverter; import org.mitre.openid.connect.model.convert.JsonObjectStringConverter;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@Entity @Entity
@Table(name="user_info") @Table(name="user_info")
@ -70,7 +75,7 @@ public class DefaultUserInfo implements UserInfo {
private Address address; private Address address;
private String updatedTime; private String updatedTime;
private String birthdate; private String birthdate;
private JsonObject src; // source JSON if this is loaded remotely private transient JsonObject src; // source JSON if this is loaded remotely
/** /**
@ -727,5 +732,26 @@ public class DefaultUserInfo implements UserInfo {
} }
return true; return true;
} }
/*
* Custom serialization to handle the JSON object
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
if (src == null) {
out.writeObject(null);
} else {
out.writeObject(src.toString());
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Object o = in.readObject();
if (o != null) {
JsonParser parser = new JsonParser();
src = parser.parse((String)o).getAsJsonObject();
}
}
} }

View File

@ -16,6 +16,10 @@
*******************************************************************************/ *******************************************************************************/
package org.mitre.openid.connect.model; package org.mitre.openid.connect.model;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -24,6 +28,8 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
/** /**
* *
@ -35,14 +41,14 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 22100073066377804L; private static final long serialVersionUID = 22100073066377804L;
private final ImmutableMap<String, String> principal; private final ImmutableMap<String, String> principal;
private final String idTokenValue; // string representation of the id token
private final String accessTokenValue; // string representation of the access token private final String accessTokenValue; // string representation of the access token
private final String refreshTokenValue; // string representation of the refresh token private final String refreshTokenValue; // string representation of the refresh token
private transient JWT idToken; // this needs a custom serializer
private final String issuer; // issuer URL (parsed from the id token) private final String issuer; // issuer URL (parsed from the id token)
private final String sub; // user id (parsed from the id token) private final String sub; // user id (parsed from the id token)
private final transient ServerConfiguration serverConfiguration; // server configuration used to fulfill this token, don't serialize it private final transient ServerConfiguration serverConfiguration; // server configuration used to fulfill this token, don't serialize it
private final UserInfo userInfo; // user info container, don't serialize it b/c it might be huge and can be re-fetched private final UserInfo userInfo; // user info container
/** /**
* Constructs OIDCAuthenticationToken with a full set of authorities, marking this as authenticated. * Constructs OIDCAuthenticationToken with a full set of authorities, marking this as authenticated.
@ -57,7 +63,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
*/ */
public OIDCAuthenticationToken(String subject, String issuer, public OIDCAuthenticationToken(String subject, String issuer,
UserInfo userInfo, Collection<? extends GrantedAuthority> authorities, UserInfo userInfo, Collection<? extends GrantedAuthority> authorities,
String idTokenValue, String accessTokenValue, String refreshTokenValue) { JWT idToken, String accessTokenValue, String refreshTokenValue) {
super(authorities); super(authorities);
@ -65,7 +71,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
this.userInfo = userInfo; this.userInfo = userInfo;
this.sub = subject; this.sub = subject;
this.issuer = issuer; this.issuer = issuer;
this.idTokenValue = idTokenValue; this.idToken = idToken;
this.accessTokenValue = accessTokenValue; this.accessTokenValue = accessTokenValue;
this.refreshTokenValue = refreshTokenValue; this.refreshTokenValue = refreshTokenValue;
@ -85,14 +91,14 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
*/ */
public OIDCAuthenticationToken(String subject, String issuer, public OIDCAuthenticationToken(String subject, String issuer,
ServerConfiguration serverConfiguration, ServerConfiguration serverConfiguration,
String idTokenValue, String accessTokenValue, String refreshTokenValue) { JWT idToken, String accessTokenValue, String refreshTokenValue) {
super(new ArrayList<GrantedAuthority>(0)); super(new ArrayList<GrantedAuthority>(0));
this.principal = ImmutableMap.of("sub", subject, "iss", issuer); this.principal = ImmutableMap.of("sub", subject, "iss", issuer);
this.sub = subject; this.sub = subject;
this.issuer = issuer; this.issuer = issuer;
this.idTokenValue = idTokenValue; this.idToken = idToken;
this.accessTokenValue = accessTokenValue; this.accessTokenValue = accessTokenValue;
this.refreshTokenValue = refreshTokenValue; this.refreshTokenValue = refreshTokenValue;
@ -129,8 +135,8 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
/** /**
* @return the idTokenValue * @return the idTokenValue
*/ */
public String getIdTokenValue() { public JWT getIdToken() {
return idTokenValue; return idToken;
} }
/** /**
@ -168,5 +174,23 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
return userInfo; return userInfo;
} }
/*
* Custom serialization to handle the JSON object
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
if (idToken == null) {
out.writeObject(null);
} else {
out.writeObject(idToken.serialize());
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException, ParseException {
in.defaultReadObject();
Object o = in.readObject();
if (o != null) {
idToken = JWTParser.parse((String)o);
}
}
} }