ID Token carried through as parsed JWT instead of string, closes #832
parent
f4a1b27e2e
commit
b4520c170e
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue