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
Conversation
pkg/services/authn/clients/jwt.go
Outdated
@@ -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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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!
pkg/services/authn/clients/jwt.go
Outdated
@@ -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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
grafana/pkg/services/authn/clients/jwt.go
Lines 120 to 123 in 29c76b9
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.
* 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)
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>
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: