Skip to content

Fix UserInfo: use real email_verified, gate claims by scope#50

Merged
eswan18 merged 3 commits into
mainfrom
fix/userinfo-email-scope-gating
Mar 30, 2026
Merged

Fix UserInfo: use real email_verified, gate claims by scope#50
eswan18 merged 3 commits into
mainfrom
fix/userinfo-email-scope-gating

Conversation

@eswan18
Copy link
Copy Markdown
Owner

@eswan18 eswan18 commented Mar 30, 2026

Summary

  • Bug fix: /oauth/userinfo was hardcoding email_verified: true instead of using the actual value from the JWT (which correctly reflects the DB). Unverified users were reported as verified.
  • Spec compliance: email and email_verified are now only returned when the email scope is requested, and username is only returned when profile scope is requested, per OIDC Core Section 5.4.
  • Test fix: TestUserInfoEndpoint now correctly asserts email_verified=false for new unverified users (previously passed only because of the hardcoded bug).
  • New test: TestUserInfoScopeGating verifies that claims are absent when their corresponding scope is not requested.

Test plan

  • go build ./... passes
  • go vet ./... passes
  • Unit tests pass
  • Integration tests pass (require Docker)
  • Verify existing OAuth clients still receive expected claims (they all request openid profile email)

🤖 Generated with Claude Code

eswan18 and others added 3 commits March 29, 2026 21:56
Two OIDC Core spec violations in the /oauth/userinfo endpoint:

1. email_verified was hardcoded to true instead of using the actual value
   from the JWT claims (which correctly reflects the DB state). New users
   with unverified emails were incorrectly reported as verified.

2. email and email_verified were returned unconditionally regardless of
   requested scopes. Per OIDC Core Section 5.4, these require the "email"
   scope. Similarly, username is now gated by the "profile" scope.

Also fixes TestUserInfoEndpoint which was masking bug #1 by asserting
email_verified=true (which only passed due to the hardcoded value), and
adds TestUserInfoScopeGating to verify claims are properly gated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace strings.Contains with slices.Contains for scope membership
checks in UserInfo to avoid substring false positives (e.g. a
hypothetical "noemail" scope matching "email").

Add TestUserInfoEmailScopeOnly to verify that requesting "openid email"
returns email claims but not profile claims.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- UserInfo endpoint description now documents scope-gated claims
- Token endpoint description no longer mentions id_token (not yet implemented, tracked in #52)
- Regenerated swagger docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@eswan18 eswan18 merged commit 37569f6 into main Mar 30, 2026
1 check passed
@eswan18 eswan18 deleted the fix/userinfo-email-scope-gating branch March 30, 2026 03:19
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.

1 participant