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

feat(frontend): Parse JWT access token claims #5138

Merged
merged 16 commits into from
Jun 13, 2022

Conversation

chen4119
Copy link
Contributor

@chen4119 chen4119 commented Jun 9, 2022

Checklist

  • The PR conforms to DataHub's Contributing Guideline (particularly Commit Message Format)
  • Links to related issues (if applicable)
  • Tests for the changes have been added/updated (if applicable)
  • Docs related to the changes have been added/updated (if applicable). If a new feature has been added a Usage Guide has been added for the same.
  • For any breaking change/potential downtime/deprecation/big changes an entry has been made in Updating DataHub


for (final Entry<String, Object> entry : jwt.getJWTClaimsSet().getClaims().entrySet()) {
final String claimName = entry.getKey();
if (profile.getAttribute(claimName) == null) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only add claim to profile attribute if it doesn't exist to avoid overriding existing id token claims. Access token and id token will have duplicate standard claim names (see link below) with different values.

https://github.com/pac4j/pac4j/blob/3.2.x/pac4j-core/src/main/java/org/pac4j/core/profile/jwt/JwtClaims.java

With this check in place, maybe we don't need an optional config for a set of claims to filter for? Since access token claims will not override id token claims.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this makes sense! I like checking for existence first. I don't foresee cases where you'll want the same claim from 2 tokens, but I suppose in that case we could add some default prefix.

@github-actions
Copy link

github-actions bot commented Jun 9, 2022

Unit Test Results (build & test)

381 tests  ±0   381 ✔️ ±0   3m 1s ⏱️ -21s
  89 suites ±0       0 💤 ±0 
  89 files   ±0       0 ±0 

Results for commit a4aff93. ± Comparison against base commit e6b66d8c.

♻️ This comment has been updated with latest results.

@Override
public CommonProfile generate(WebContext context, CommonProfile profile) {
try {
final JWT jwt = JWTParser.parse(((OidcProfile) profile).getAccessToken().getValue());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to detect whether the access token is a JWT?

Otherwise, we may be logging tons of warnings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only parsing JWT access token if OIDC_EXTRACT_JWT_ACCESS_TOKEN_CLAIMS = true so shouldn't log any warnings. I guess we can depend on users to only enable this feature if they know they want claims from their access token?

import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;

public class OidcAuthorizationGenerator implements AuthorizationGenerator {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name this class to reflect that its related to Parsing access tokens?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also keep this name, but just pass in the "OidcConfigs" object in the constructor, and then decide whether to parse JWT access tokens inside of here!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed in OidcConfigs in constructor

@@ -25,5 +31,8 @@ protected void clientInit() {
defaultAuthenticator(new CustomOidcAuthenticator(getConfiguration(), this));
defaultProfileCreator(new OidcProfileCreator<>(getConfiguration()));
defaultLogoutActionBuilder(new OidcLogoutActionBuilder<>(getConfiguration()));
if (parseJwtAccessTokenEnabled) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this if here, I'd recommend always using the OidcAuthorizationGenerator but with the oidc configs passed in!

The OidcAuthorizationGenerator can internally decide what to do based on configs

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another benefit is you will not need to change the constructor for this class!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -139,6 +139,7 @@ auth.oidc.responseMode = ${?AUTH_OIDC_RESPONSE_MODE}
auth.oidc.useNonce = ${?AUTH_OIDC_USE_NONCE}
auth.oidc.customParam.resource = ${?AUTH_OIDC_CUSTOM_PARAM_RESOURCE}
auth.oidc.readTimeout = ${?AUTH_OIDC_READ_TIMEOUT}
auth.oidc.parseJwtAccessTokenEnabled = ${?AUTH_OIDC_PARSE_JWT_ACCESS_TOKEN_ENABLED} # Whether to parse claims from JWT access token. Defaults to false.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: we can consider an alternate name here as well:

AUTH_OIDC_EXTRACT_JWT_ACCESS_TOKEN_CLAIMS

But i have no strong preference - up to you!

Copy link
Collaborator

@jjoyce0510 jjoyce0510 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Thank you somuch @chen4119 !

@jjoyce0510 jjoyce0510 merged commit 7bf2733 into datahub-project:master Jun 13, 2022
maggiehays pushed a commit to maggiehays/datahub that referenced this pull request Aug 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants