From 941c56e69eb87d51466e93a72d52a422811a4e5f Mon Sep 17 00:00:00 2001 From: Justin Judd Date: Fri, 1 Aug 2025 19:34:11 -0700 Subject: [PATCH] feat(jwt): Enable using User Properties as custom claims (#3571) --- object/token_jwt.go | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/object/token_jwt.go b/object/token_jwt.go index 28ac3e0b..5ece9a5a 100644 --- a/object/token_jwt.go +++ b/object/token_jwt.go @@ -342,10 +342,31 @@ func getClaimsCustom(claims Claims, tokenField []string) jwt.MapClaims { res["provider"] = claims.Provider for _, field := range tokenField { - userField := userValue.FieldByName(field) - if userField.IsValid() { - newfield := util.SnakeToCamel(util.CamelToSnakeCase(field)) - res[newfield] = userField.Interface() + if strings.HasPrefix(field, "Properties") { + /* + Use selected properties fields as custom claims. + Converts `Properties.my_field` to custom claim with name `my_field`. + */ + parts := strings.Split(field, ".") + if len(parts) != 2 || parts[0] != "Properties" { // Either too many segments, or not properly scoped to `Properties`, so skip. + continue + } + base, fieldName := parts[0], parts[1] + mField := userValue.FieldByName(base) + if !mField.IsValid() { // Can't find `Properties` field, so skip. + continue + } + finalField := mField.MapIndex(reflect.ValueOf(fieldName)) + if finalField.IsValid() { // // Provided field within `Properties` exists, add claim. + res[fieldName] = finalField.Interface() + } + + } else { // Use selected user field as claims. + userField := userValue.FieldByName(field) + if userField.IsValid() { + newfield := util.SnakeToCamel(util.CamelToSnakeCase(field)) + res[newfield] = userField.Interface() + } } }