Commit caad379
GitHub OIDC token exchange endpoint (#1569)
* init
* [US-001] Create token exchange route structure
- Add POST endpoint at /api/github/token-exchange
- Accept JSON body with oidc_token field
- Return JSON response with token, expires_at, repository, installation_id
- Route is unauthenticated (OIDC token is the authentication)
- Add RFC 7807 problem details schema for error responses
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-002] Configure GitHub App credentials from environment
- Create config module to load GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY
- Add startup validation with warning log if credentials not configured
- Update token exchange route to return 500 if credentials missing
- Document environment variables in .env.example
- Private key is never logged or exposed in error messages
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-003] Fetch and cache GitHub OIDC JWKS
Implement JWKS fetch and caching module for GitHub OIDC token verification:
- Fetch JWKS from https://token.actions.githubusercontent.com/.well-known/jwks
- Cache JWKS with 1 hour TTL to avoid fetching on every request
- Handle JWKS fetch failures gracefully with clear error messages
- Refresh cache when key ID (kid) doesn't match cached keys
- Add jose dependency for JWT/JWK operations
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-004] Validate OIDC token signature and claims
Add oidcToken.ts module that validates GitHub Actions OIDC tokens:
- Verify JWT signature using GitHub's JWKS (RS256)
- Validate issuer claim equals https://token.actions.githubusercontent.com
- Validate audience claim equals inkeep-agents-action
- Validate token expiration
- Extract claims: repository, repository_owner, repository_id, workflow, actor, ref
- Return 401 Unauthorized with clear message for invalid/expired tokens
Update tokenExchange route to use validation and return proper error responses.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-005] Look up GitHub App installation for repository
Add installation lookup module that:
- Creates RS256-signed JWT for GitHub App authentication
- Calls GitHub API /repos/{owner}/{repo}/installation endpoint
- Returns 403 Forbidden if App not installed on repository
- Returns 500 on API errors or JWT creation failures
- Exports types for installation info and result types
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-006] Generate GitHub App installation access token
Add generateInstallationAccessToken function that creates short-lived
installation tokens for GitHub Actions to access repository data.
- Create RS256-signed JWT for GitHub App authentication (10 min expiry)
- Call POST /app/installations/{id}/access_tokens GitHub API endpoint
- Return token and expiration timestamp on success
- Return 500 error with RFC 7807 format on API or JWT failures
- Update tokenExchange route to generate real tokens instead of placeholder
- Export new types from github domain index
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-007] Handle all error cases with proper HTTP status codes
- Added defaultHook to tokenExchange route for RFC 7807 formatted validation errors
with 'error' field as required by OpenAPI schema
- Return 400 Bad Request for malformed oidc_token (JWT format issues)
- Return 401 Unauthorized for authentication failures (invalid signature, expired,
wrong issuer, wrong audience)
- All error responses now include 'error' field with human-readable message
- All error responses use application/problem+json content type
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-008] Create test utilities for JWT generation
Add testJwt.ts module providing helpers for testing the GitHub OIDC token exchange endpoint. Includes RS256 key pair generation with caching, configurable JWT creation with custom claims, helpers for expired tokens and wrong issuer/audience, malformed token generators, and JWKS mock response helpers.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* [US-009] Create route tests for token exchange endpoint
Comprehensive tests for the GitHub OIDC token exchange endpoint covering success case (200), validation errors (400), authentication failures (401), forbidden errors (403), and internal server errors (500). Uses vi.hoisted pattern for mocking GitHub JWKS fetch and App API calls. Utilizes test JWT utilities from US-008 for generating valid, expired, wrong-issuer, and malformed tokens.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* bug fixes
* lints
* remove from openapi spec
* changeset
---------
Co-authored-by: Claude Opus 4.5 <[email protected]>1 parent 67418c5 commit caad379
File tree
16 files changed
+1639
-28
lines changed- .ai-dev
- .changeset
- agents-api
- src
- __tests__
- github/routes
- utils
- domains
- github
- routes
16 files changed
+1639
-28
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | | - | |
11 | | - | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
12 | 14 | | |
13 | | - | |
14 | | - | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
16 | 24 | | |
17 | 25 | | |
18 | | - | |
| 26 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
| |||
48 | 51 | | |
49 | 52 | | |
50 | 53 | | |
| 54 | + | |
51 | 55 | | |
52 | 56 | | |
53 | 57 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
| 88 | + | |
88 | 89 | | |
89 | 90 | | |
90 | 91 | | |
| |||
0 commit comments