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

JWT: Find login and email claims with JMESPATH #85305

Merged
merged 10 commits into from Mar 28, 2024

Conversation

linoman
Copy link
Contributor

@linoman linoman commented Mar 27, 2024

What is this feature?

This feature will resolve login/username and email claims using JMESPath. This will allow us to use rootClaim.subClaim.listOfEmails[0].

Why do we need this feature?

This has been requested in the past. However, this won't solve the issue for Google's JWT subclaim gcip since that needs to be parsed again.

#75856

Who is this feature for?

IAM

Which issue(s) does this PR fix?:

Fixes #69451

Special notes for your reviewer:

Please check that:

  • It works as expected from a user's perspective.
  • If this is a pre-GA feature, it is behind a feature toggle.
  • The docs are updated, and if this is a notable improvement, it's added to our What's New doc.

@linoman linoman added no-backport Skip backport of PR no-changelog Skip including change in changelog/release notes labels Mar 27, 2024
@linoman linoman added this to the 11.1.x milestone Mar 27, 2024
@linoman linoman requested a review from mgyongyosi March 27, 2024 17:51
@linoman linoman self-assigned this Mar 27, 2024
@@ -75,13 +76,24 @@ func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identi
SyncTeams: s.cfg.JWTAuth.GroupsAttributePath != "",
}}

serializedClaims, _ := json.Marshal(&claims)
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of marshaling/unmarshaling you can use map[string]any(claims) in the code.
Example:

id.Email, _ = util.SearchJSONForStringAttr(s.cfg.JWTAuth.EmailAttributePath, map[string]any(claims))

Because claims's type is JWTClaims which is a "redefinition of DynMap -> map[string]any, so because of this the underlying jmespath lib cannot work without the type conversion to map[string]any, because it checks for map[string]any, but it receives JWTClaims.

I don't think the custom type definitions (without any functions attached to those) provides any benefit here. So we could remove JWTClaims and use map[string]any instead to make the code simpler. @kalleep wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I think it makes sense, either solution would work but I think I would prefer to remove the custom definition JwtClaims and just return map[string]any for the reasons @mgyongyosi stated

Copy link
Contributor Author

@linoman linoman Mar 28, 2024

Choose a reason for hiding this comment

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

As suggested, I have replaced JWTClaims with map[string]any and removed the conversions of claims to map. Looks much cleaner!

@linoman linoman marked this pull request as ready for review March 28, 2024 11:14
@linoman linoman requested review from torkelo, a team and chri2547 as code owners March 28, 2024 11:14
@linoman linoman requested review from papagian, zserge and mildwonkey and removed request for a team March 28, 2024 11:14
@@ -78,10 +78,17 @@ func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identi
if key := s.cfg.JWTAuth.UsernameClaim; key != "" {
id.Login, _ = claims[key].(string)
id.ClientParams.LookUpParams.Login = &id.Login
} else if key := s.cfg.JWTAuth.UsernameAttributePath; key != "" {
id.Login, _ = util.SearchJSONForStringAttr(s.cfg.JWTAuth.UsernameAttributePath, claims)
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to handle potential errors for both of these

Copy link
Contributor Author

@linoman linoman Mar 28, 2024

Choose a reason for hiding this comment

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

I intentionally didn't handle the errors similar to what was already being done 3 lines before.

id.Login, _ = claims[key].(string)

They don't handle the errors because the identity validation expects username and email to be set.

If we handle errors for these 2, we might as well handle the missing elements for the other 2. WDYT @kalleep? How would you like them 4 to be handled?

Copy link
Contributor

Choose a reason for hiding this comment

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

@linoman The emptiness of id.Login and id.Email is checked at the end of this function:

if id.Login == "" && id.Email == "" {
s.log.FromContext(ctx).Debug("Failed to get an authentication claim from JWT",
"login", id.Login, "email", id.Email)
return nil, errJWTMissingClaim.Errorf("missing login and email claim in JWT")

However, I think we should still check, log and return the errors of util.SearchJSONForStringAttr as Kalle said.

@linoman linoman merged commit e4250a7 into main Mar 28, 2024
13 checks passed
@linoman linoman deleted the linoman/jwt_user_jmespath_to_find_in_claims branch March 28, 2024 16:25
@ashharrison90 ashharrison90 modified the milestones: 11.1.x, 11.0.0-preview Apr 16, 2024
@ashharrison90 ashharrison90 added product-approved Pull requests that are approved by product/managers and are allowed to be backported backport v11.0.x Mark PR for automatic backport to v11.0.x and removed no-backport Skip backport of PR labels Apr 16, 2024
grafana-delivery-bot bot pushed a commit that referenced this pull request Apr 16, 2024
* add function to static function to static service

* find email and login claims with jmespath

* rename configuration files

* Replace JWTClaims struct for map

* check for subclaims error

(cherry picked from commit e4250a7)
ashharrison90 pushed a commit that referenced this pull request Apr 16, 2024
JWT: Find login and email claims with JMESPATH (#85305)

* add function to static function to static service

* find email and login claims with jmespath

* rename configuration files

* Replace JWTClaims struct for map

* check for subclaims error

(cherry picked from commit e4250a7)

Co-authored-by: linoman <2051016+linoman@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/backend backport v11.0.x Mark PR for automatic backport to v11.0.x no-changelog Skip including change in changelog/release notes product-approved Pull requests that are approved by product/managers and are allowed to be backported type/docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Auth - JWT]: username/email_claim don't support array values
4 participants