Skip to content

feat: add PAT identity to JWT claims #1509

Merged
AmanGIT07 merged 2 commits intomainfrom
feat/pat-in-jwt
Apr 6, 2026
Merged

feat: add PAT identity to JWT claims #1509
AmanGIT07 merged 2 commits intomainfrom
feat/pat-in-jwt

Conversation

@AmanGIT07
Copy link
Copy Markdown
Contributor

Summary

Add PAT-specific claims to the JWT minted during AuthToken so that upstream services can identify the PAT owner and Frontier can enforce PAT scope when upstream services call back with the JWT.

What changed

Frontier

  • When a PAT authenticates via AuthToken, the JWT now includes:
    • sub = PAT ID (the authenticating token)
    • sub_type = app/pat
    • user_id = owner's user ID (new claim)
    • org_ids = PAT's org only
  • When Frontier receives this JWT back (from upstream services calling permission check RPCs), it now recognizes app/pat type, loads the full PAT, and enforces scope intersection

Kong plugin

  • Added user_id to DEFAULT_TOKEN_HEADERS so Kong forwards it as X-Frontier-user_id header to upstream services
  • Header is only set for PAT auth (Kong skips claims that aren't in the JWT)

Why

Upstream services need the user ID for "created by" logging. They can't use sub for this when auth is via PAT because sub is the PAT ID. The user_id claim gives them the human identity without an extra RPC call.

Frontier needs to know it's a PAT when the JWT comes back, so it can enforce the PAT's scope (only allow access to resources the PAT is scoped to, not everything the user has access to).

Upstream usage

  • "Created by" → use X-Frontier-user_id if present, else X-Frontier-sub
  • Permission checks → always pass X-Frontier-sub (Frontier handles scope

Test plan

  • Manual: JWT contains user_id claim for PAT sub type
  • Manual: Use PAT JWT for CheckResourcePermission → PAT scope enforced
  • Manual: Use PAT JWT for resource outside PAT scope → denied

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
frontier Ready Ready Preview, Comment Apr 6, 2026 7:13am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 25995757-5c99-4845-871d-de8e1aefa1f1

📥 Commits

Reviewing files that changed from the base of the PR and between 1849638 and bf9845b.

📒 Files selected for processing (1)
  • core/authenticate/authenticators.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added support for Personal Access Token (PAT) authentication with expiry validation using current-time checks.
    • PAT-authenticated requests now associate tokens with their owning users, returning both token and owner identity.
    • Tokens now include an explicit user identifier claim when issued for PAT-backed principals, improving traceability.

Walkthrough

Adds Personal Access Token (PAT) support to access-token authentication: JWT PAT subtype is recognized, PAT is loaded and expiry-checked, the PAT owner user is loaded, and a PATPrincipal is returned. Also adds a user_id token claim and service/repo accessors for PAT retrieval.

Changes

Cohort / File(s) Summary
PAT Authentication Logic
core/authenticate/authenticators.go, core/authenticate/service.go
authenticateWithAccessToken handles schema.PATPrincipal subtype by treating sub as a PAT ID: loads PAT via UserPATService.GetByID, rejects if not found or expired (pat.ExpiresAt vs s.Now()), loads PAT owner via userService.GetByID, and returns a schema.PATPrincipal. Service.BuildToken writes token.UserIDClaimKey = principal.User.ID when building tokens for PAT principals.
Token Infrastructure
core/authenticate/token/service.go
Adds new token-claims constant UserIDClaimKey = "user_id" alongside existing claim keys.
PAT Data Access / Validation
core/userpat/validator.go
Adds GetByID(ctx, id) to Validator, delegating to v.repo.GetByID to retrieve a models.PAT.
Interface Declaration
core/authenticate/service.go
Extends UserPATService interface with GetByID(ctx context.Context, id string) (patModels.PAT, error).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


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
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
core/authenticate/authenticators.go (1)

137-159: Consider using s.Now() for time consistency.

The PAT expiration check uses time.Now() directly, while the rest of the service uses s.Now() (which returns time.Now().UTC()). This inconsistency could cause subtle issues in tests where s.Now is mocked, or if PAT expiration times are stored in UTC.

Suggested fix for consistency
-			if pat.ExpiresAt.Before(time.Now()) {
+			if pat.ExpiresAt.Before(s.Now()) {

Otherwise, the PAT principal resolution logic is correct:

  • Correctly treats JWT sub as PAT ID
  • Validates PAT exists and is not expired
  • Loads the owning user for downstream handlers
  • Returns appropriate Principal with both PAT and User populated

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c955c7ba-80ae-4f4d-8695-d22b2c81a117

📥 Commits

Reviewing files that changed from the base of the PR and between 1b73eaf and 1849638.

📒 Files selected for processing (4)
  • core/authenticate/authenticators.go
  • core/authenticate/service.go
  • core/authenticate/token/service.go
  • core/userpat/validator.go

@AmanGIT07 AmanGIT07 merged commit 5fb8089 into main Apr 6, 2026
8 checks passed
@AmanGIT07 AmanGIT07 deleted the feat/pat-in-jwt branch April 6, 2026 07: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.

2 participants