Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OIDC: extract claims from JWT access token #2276

Merged
merged 3 commits into from Jul 14, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -3,8 +3,13 @@
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.proc.BadJOSEException;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.JWTParser;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.openid.connect.sdk.*;
import com.nimbusds.openid.connect.sdk.Nonce;
import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
import com.nimbusds.openid.connect.sdk.UserInfoRequest;
import com.nimbusds.openid.connect.sdk.UserInfoResponse;
import com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.credentials.Credentials;
Expand Down Expand Up @@ -69,6 +74,7 @@ public Optional<UserProfile> create(final Credentials cred, final WebContext con
profile.setAccessToken(accessToken);
final var idToken = credentials.getIdToken();
profile.setIdTokenString(idToken.getParsedString());
profile.setAccessToken(accessToken);
mmoayyed marked this conversation as resolved.
Show resolved Hide resolved
// Check if there is a refresh token
final var refreshToken = credentials.getRefreshToken();
if (refreshToken != null && !refreshToken.getValue().isEmpty()) {
Expand Down Expand Up @@ -96,12 +102,12 @@ public Optional<UserProfile> create(final Credentials cred, final WebContext con
configuration.configureHttpRequest(userInfoHttpRequest);
final var httpResponse = userInfoHttpRequest.send();
logger.debug("User info response: status={}, content={}", httpResponse.getStatusCode(),
httpResponse.getContent());
httpResponse.getContent());

final var userInfoResponse = UserInfoResponse.parse(httpResponse);
if (userInfoResponse instanceof UserInfoErrorResponse) {
logger.error("Bad User Info response, error={}",
((UserInfoErrorResponse) userInfoResponse).getErrorObject());
((UserInfoErrorResponse) userInfoResponse).getErrorObject());
} else {
final var userInfoSuccessResponse = (UserInfoSuccessResponse) userInfoResponse;
final JWTClaimsSet userInfoClaimsSet;
Expand All @@ -128,6 +134,8 @@ public Optional<UserProfile> create(final Credentials cred, final WebContext con
}
}

collectClaimsFromAccessTokenIfAny(credentials, nonce, profile);

// session expiration with token behavior
profile.setTokenExpirationAdvance(configuration.getTokenExpirationAdvance());

Expand All @@ -143,4 +151,25 @@ public Optional<UserProfile> create(final Credentials cred, final WebContext con
throw new TechnicalException(e);
}
}

private void collectClaimsFromAccessTokenIfAny(final OidcCredentials credentials,
final Nonce nonce, OidcProfile profile) {
try {
var accessTokenJwt = JWTParser.parse(credentials.getAccessToken().getValue());
var accessTokenClaims = configuration.findTokenValidator().validate(accessTokenJwt, nonce);

// add attributes of the access token if they don't already exist
for (final var entry : accessTokenClaims.toJWTClaimsSet().getClaims().entrySet()) {
final var key = entry.getKey();
final var value = entry.getValue();
if (!JwtClaims.SUBJECT.equals(key) && profile.getAttribute(key) == null) {
getProfileDefinition().convertAndAdd(profile, PROFILE_ATTRIBUTE, key, value);
}
}
} catch (final ParseException | JOSEException | BadJOSEException e) {
logger.debug(e.getMessage(), e);
} catch (final Exception e) {
throw new TechnicalException(e);
}
}
}