Skip to content

Conversation

@nexus49
Copy link
Contributor

@nexus49 nexus49 commented Sep 16, 2025

Summary by CodeRabbit

  • New Features

    • Improved extraction of user first/last names from tokens, supporting both first/last and given/family claim variants with prioritized fallbacks and trimming.
    • Email/mail extraction now trims whitespace for more consistent results.
  • Bug Fixes

    • More precise error handling for token parsing and deserialization to avoid leaking token contents.
  • Tests

    • Expanded, table-driven unit tests covering name mapping, audience parsing, and parsing/deserialization error cases.

• Introduces new fields for first_name and last_name in the web token
• Implements fallback logic to prioritize first_name/last_name over given_name/family_name
@nexus49 nexus49 requested review from a team as code owners September 16, 2025 16:08
@coderabbitai
Copy link

coderabbitai bot commented Sep 16, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Populate WebToken.FirstName and WebToken.LastName from raw claims (first_name/last_name with fallbacks to given_name/family_name), add RawGivenName/RawFamilyName and trimming logic, adjust id_token parse error wrapping, and add/rewire tests for success and error scenarios.

Changes

Cohort / File(s) Summary
JWT model mapping
jwt/model.go, jwt/model_test.go
New() now assigns WebToken.FirstName and WebToken.LastName using rawWebToken.getFirstName()/getLastName(). Error wrapping for id_token parse uses the underlying error (%w) and no longer includes the raw token string. Tests replaced with table-driven TestNew_Success and TestNew_Errors covering name precedence and deserialization/parse failures.
JWT raw claim parsing & tests
jwt/raw.go, jwt/raw_test.go
Added RawGivenName and RawFamilyName to rawClaims; rawWebToken embeds rawClaims, IssuerAttributes, and UserAttributes. Implemented getFirstName(), getLastName(), and getMail() with trimming and fallback rules. Expanded tests for audiences, first/last name precedence, trimming, and edge cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • akafazov
  • aaronschweig

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feat(model): add support for first and last name claims" is concise, follows conventional commit style, and directly describes the primary change—adding handling for first and last name JWT claims in the model—so it accurately reflects the changeset and is clear to reviewers.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2fb38e and 9d9dec7.

📒 Files selected for processing (3)
  • jwt/model_test.go (1 hunks)
  • jwt/raw.go (2 hunks)
  • jwt/raw_test.go (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
jwt/model.go (1)

40-41: Do not include the raw id_token in errors/logs (PII leak).

Leaking tokens can expose PII and credentials in logs. Remove the token string from the error.

Apply this diff:

-		err = fmt.Errorf("unable to parse id_token: [%s], %w", idToken, parseErr)
+		err = fmt.Errorf("unable to parse id_token: %w", parseErr)

Optionally add structured logging of safe metadata (e.g., error type) if needed.

🧹 Nitpick comments (3)
jwt/raw.go (1)

25-31: Treat whitespace-only names as empty to trigger fallback.

If an IdP emits " " or "\t" for first/last name, current logic won’t fallback. Trim before checks.

Apply these diffs:

 func (r rawWebToken) getLastName() (lastName string) {
-	lastName = r.LastName
-	if lastName == "" {
-		lastName = r.RawFamilyName
+	lastName = strings.TrimSpace(r.LastName)
+	if lastName == "" {
+		lastName = strings.TrimSpace(r.RawFamilyName)
 	}
 	return
 }
 
 func (r rawWebToken) getFirstName() (firstName string) {
-	firstName = r.FirstName
-	if firstName == "" {
-		firstName = r.RawGivenName
+	firstName = strings.TrimSpace(r.FirstName)
+	if firstName == "" {
+		firstName = strings.TrimSpace(r.RawGivenName)
 	}
 	return
 }

Add import (outside this hunk):

import "strings"

Also applies to: 33-39

jwt/raw_test.go (1)

41-129: Good coverage; consider table-driven tests and a whitespace case.

  • Consolidate the six near-identical tests into table-driven subtests to reduce duplication.
  • Add a case where first_name/last_name are " " to ensure trim-based fallback works if adopted.

If you want, I can draft the table-driven variant including a whitespace case.

jwt/model_test.go (1)

53-150: Tests clearly validate priority and fallbacks.

Nice coverage across presence, preference, and partial fallback scenarios.

Add one more test with whitespace-only first_name/last_name to lock in the trimming behavior if implemented.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbdeb77 and a00c8fa.

📒 Files selected for processing (4)
  • jwt/model.go (1 hunks)
  • jwt/model_test.go (1 hunks)
  • jwt/raw.go (2 hunks)
  • jwt/raw_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
jwt/raw_test.go (1)
jwt/model.go (1)
  • UserAttributes (16-19)
jwt/model_test.go (1)
jwt/model.go (1)
  • New (37-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: pipe / lint / lint
  • GitHub Check: Analyze (go)
🔇 Additional comments (2)
jwt/raw.go (1)

4-8: Additions align with OIDC standard claims.

Introducing RawGivenName/RawFamilyName with given_name/family_name tags is correct and non-breaking.

jwt/model.go (1)

55-56: LGTM: correctly maps normalized names onto WebToken.

Assignments are after copying UserAttributes, so they properly override with preferred/fallback values.

Please confirm no callers relied on empty FirstName/LastName when given_name/family_name were present.

• Ensures that name fields are clean and consistent
• Prevents potential issues with empty or malformed names
@github-actions github-actions bot added the fix label Sep 16, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
jwt/raw.go (5)

6-10: Support []string in audiences to match the struct comment.

Comment says aud can be []string or string, but getAudiences only handles string and []interface{}. Add a []string branch.

Apply:

 func (r rawWebToken) getAudiences() (audiences []string) {
   switch audienceList := r.RawAudiences.(type) {
   case string:
     audiences = []string{audienceList}
+  case []string:
+    audiences = append(audiences, audienceList...)
   case []interface{}:
     for _, val := range audienceList {
       aud, ok := val.(string)
       if ok {
         audiences = append(audiences, aud)
       }
     }
   }
   return
 }

19-25: Trim fallback email too.

Fallback assigns RawEmail without trimming; whitespace-only RawEmail would leak through.

Apply:

 func (r rawWebToken) getMail() (mail string) {
-  mail = strings.TrimSpace(r.RawMail)
+  mail = strings.TrimSpace(r.RawMail)
   if mail == "" {
-    mail = r.RawEmail
+    mail = strings.TrimSpace(r.RawEmail)
   }
   return
 }

27-33: Trim fallback family_name.

Aligns with first pass trimming and avoids whitespace results.

Apply:

 func (r rawWebToken) getLastName() (lastName string) {
   lastName = strings.TrimSpace(r.LastName)
   if lastName == "" {
-    lastName = r.RawFamilyName
+    lastName = strings.TrimSpace(r.RawFamilyName)
   }
   return
 }

35-41: Trim fallback given_name.

Same rationale as last name.

Apply:

 func (r rawWebToken) getFirstName() (firstName string) {
   firstName = strings.TrimSpace(r.FirstName)
   if firstName == "" {
-    firstName = r.RawGivenName
+    firstName = strings.TrimSpace(r.RawGivenName)
   }
   return
 }

20-20: DRY: helper for “first non-empty trimmed” selection.

Reduces duplication across mail/first/last name getters.

Apply:

+// firstNonEmptyTrim returns the first non-empty trimmed string from vals.
+func firstNonEmptyTrim(vals ...string) string {
+  for _, v := range vals {
+    if s := strings.TrimSpace(v); s != "" {
+      return s
+    }
+  }
+  return ""
+}
+
-func (r rawWebToken) getMail() (mail string) {
-  mail = strings.TrimSpace(r.RawMail)
-  if mail == "" {
-    mail = strings.TrimSpace(r.RawEmail)
-  }
-  return
-}
+func (r rawWebToken) getMail() (mail string) { return firstNonEmptyTrim(r.RawMail, r.RawEmail) }
 
-func (r rawWebToken) getLastName() (lastName string) {
-  lastName = strings.TrimSpace(r.LastName)
-  if lastName == "" {
-    lastName = strings.TrimSpace(r.RawFamilyName)
-  }
-  return
-}
+func (r rawWebToken) getLastName() (lastName string) { return firstNonEmptyTrim(r.LastName, r.RawFamilyName) }
 
-func (r rawWebToken) getFirstName() (firstName string) {
-  firstName = strings.TrimSpace(r.FirstName)
-  if firstName == "" {
-    firstName = strings.TrimSpace(r.RawGivenName)
-  }
-  return
-}
+func (r rawWebToken) getFirstName() (firstName string) { return firstNonEmptyTrim(r.FirstName, r.RawGivenName) }

Also applies to: 28-31, 36-39

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a00c8fa and e2fb38e.

📒 Files selected for processing (2)
  • jwt/model.go (2 hunks)
  • jwt/raw.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • jwt/model.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (go)
  • GitHub Check: pipe / lint / lint
🔇 Additional comments (1)
jwt/raw.go (1)

3-3: Import looks correct.

Needed for TrimSpace; no issues.

• Refactor tests to use table-driven approach for better readability
• Add comprehensive cases for first name, last name, and error handling
• Ensures consistent handling of user input for email and name fields
@nexus49 nexus49 enabled auto-merge (squash) September 16, 2025 16:55
@nexus49 nexus49 merged commit fdf7cf4 into main Sep 16, 2025
9 of 10 checks passed
@nexus49 nexus49 deleted the feat/add-support-for-additional-claims branch September 16, 2025 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants