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
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);

View File

@ -62,30 +62,23 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider {
OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication;
try {
// get the ID Token value out
String idTokenString = token.getIdTokenValue();
JWT idToken = JWTParser.parse(idTokenString);
// load the user info if we can
UserInfo userInfo = userInfoFetcher.loadUserInfo(token);
if (userInfo == null) {
// user info not found -- could be an error, could be fine
} else {
// if we found userinfo, double check it
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());
}
// get the ID Token value out
JWT idToken = token.getIdToken();
// load the user info if we can
UserInfo userInfo = userInfoFetcher.loadUserInfo(token);
if (userInfo == null) {
// user info not found -- could be an error, could be fine
} else {
// if we found userinfo, double check it
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;
@ -104,7 +97,7 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider {
return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(),
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;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Convert;
@ -32,6 +36,7 @@ import javax.persistence.Table;
import org.mitre.openid.connect.model.convert.JsonObjectStringConverter;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@Entity
@Table(name="user_info")
@ -70,7 +75,7 @@ public class DefaultUserInfo implements UserInfo {
private Address address;
private String updatedTime;
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;
}
/*
* 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;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
@ -24,6 +28,8 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
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 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 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 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 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.
@ -57,7 +63,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
*/
public OIDCAuthenticationToken(String subject, String issuer,
UserInfo userInfo, Collection<? extends GrantedAuthority> authorities,
String idTokenValue, String accessTokenValue, String refreshTokenValue) {
JWT idToken, String accessTokenValue, String refreshTokenValue) {
super(authorities);
@ -65,7 +71,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
this.userInfo = userInfo;
this.sub = subject;
this.issuer = issuer;
this.idTokenValue = idTokenValue;
this.idToken = idToken;
this.accessTokenValue = accessTokenValue;
this.refreshTokenValue = refreshTokenValue;
@ -85,14 +91,14 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
*/
public OIDCAuthenticationToken(String subject, String issuer,
ServerConfiguration serverConfiguration,
String idTokenValue, String accessTokenValue, String refreshTokenValue) {
JWT idToken, String accessTokenValue, String refreshTokenValue) {
super(new ArrayList<GrantedAuthority>(0));
this.principal = ImmutableMap.of("sub", subject, "iss", issuer);
this.sub = subject;
this.issuer = issuer;
this.idTokenValue = idTokenValue;
this.idToken = idToken;
this.accessTokenValue = accessTokenValue;
this.refreshTokenValue = refreshTokenValue;
@ -129,8 +135,8 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
/**
* @return the idTokenValue
*/
public String getIdTokenValue() {
return idTokenValue;
public JWT getIdToken() {
return idToken;
}
/**
@ -168,5 +174,23 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
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);
}
}
}