Skip to content

feat: add GitHub App authentication support#2562

Open
pyama86 wants to merge 3 commits into
github:mainfrom
pyama86:feat/github-app-auth
Open

feat: add GitHub App authentication support#2562
pyama86 wants to merge 3 commits into
github:mainfrom
pyama86:feat/github-app-auth

Conversation

@pyama86
Copy link
Copy Markdown

@pyama86 pyama86 commented May 27, 2026

Summary

Adds native GitHub App authentication as an alternative to Personal Access Tokens, addressing a common request for organization-managed, scoped, short-lived credentials.

  • Introduces pkg/github/appauth package that handles JWT generation (RS256) and installation token management using only the Go standard library (no new dependencies)
  • Automatically refreshes installation tokens before expiry (5-minute buffer on 1-hour tokens), thread-safe with sync.Mutex
  • Supports private key via environment variable (GITHUB_APP_PRIVATE_KEY, with literal \n handling) or file path (GITHUB_APP_PRIVATE_KEY_PATH)
  • Falls back gracefully: when App auth env vars are not set, PAT authentication works as before

Environment Variables

Variable Description
GITHUB_APP_ID The GitHub App ID
GITHUB_APP_INSTALLATION_ID The installation ID of the GitHub App
GITHUB_APP_PRIVATE_KEY PEM-encoded private key (inline, \n for newlines)
GITHUB_APP_PRIVATE_KEY_PATH Path to the private key file (alternative to inline)

Closes #1333

Test plan

  • 13 unit tests covering key parsing (PKCS1/PKCS8), JWT generation/verification, installation token fetch, caching, auto-refresh, HTTP round-trip, and error handling
  • Manual test with a real GitHub App installation
  • Verify PAT-based authentication still works unchanged when App auth env vars are not set
  • Verify incomplete App auth config (e.g. missing installation ID) returns a clear error
  • Test with GitHub Enterprise Server (--gh-host)

pyama86 added 2 commits May 28, 2026 08:43
Add native GitHub App authentication as an alternative to Personal
Access Tokens. The server can now authenticate using App ID, private
key, and installation ID to automatically generate and refresh
installation tokens.

- Add `pkg/github/appauth` package with JWT generation and installation
  token management using only the standard library
- Auto-refresh tokens before expiry (5-minute buffer on 1-hour tokens)
- Support private key via env var (GITHUB_APP_PRIVATE_KEY) or file path
  (GITHUB_APP_PRIVATE_KEY_PATH)
- Handle literal `\n` in env var PEM keys
- Add comprehensive tests (13 tests covering key parsing, JWT generation,
  token caching, refresh, round-trip, and error handling)

Closes github#1333
gogithub.Option is not an exported type, so we cannot store options
in a slice. Use separate NewClient calls for each auth path instead.
Copy link
Copy Markdown

@sharmaz11 sharmaz11 left a comment

Choose a reason for hiding this comment

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

Looks good!

Copy link
Copy Markdown

@sharmaz11 sharmaz11 left a comment

Choose a reason for hiding this comment

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

Security test - please ignore - bug bounty testing

@pyama86 pyama86 marked this pull request as ready for review May 28, 2026 04:22
@pyama86 pyama86 requested a review from a team as a code owner May 28, 2026 04:22
Copilot AI review requested due to automatic review settings May 28, 2026 04:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds GitHub App installation authentication as an alternative to Personal Access Tokens for the stdio MCP server. A new appauth package implements an http.RoundTripper that generates JWTs and fetches/caches installation tokens; the server wiring conditionally uses this transport when App credentials are supplied via environment variables.

Changes:

  • New pkg/github/appauth package (Transport + JWT/installation token logic + tests).
  • internal/ghmcp/server.go plumbs an optional authTransport through NewStdioMCPServer/createGitHubClients and skips PAT-only scope fetching when App auth is in use.
  • CLI (cmd/github-mcp-server/main.go) parses GITHUB_APP_ID/GITHUB_APP_INSTALLATION_ID/GITHUB_APP_PRIVATE_KEY[_PATH] env vars; README documents the feature.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
pkg/github/appauth/appauth.go New transport that signs JWTs and exchanges them for installation tokens.
pkg/github/appauth/appauth_test.go Unit tests covering key parsing, JWT generation, token caching/refresh, and RoundTrip.
internal/ghmcp/server.go Threads optional App auth transport into REST/GraphQL client construction.
cmd/github-mcp-server/main.go Reads App auth config from env vars and passes to RunStdioServer.
go.sum Adds golang-jwt/jwt/v4 checksum entry.
README.md Documents GitHub App authentication usage.

Comment thread cmd/github-mcp-server/main.go Outdated
Comment thread cmd/github-mcp-server/main.go
Comment thread cmd/github-mcp-server/main.go
Comment thread internal/ghmcp/server.go Outdated
Comment thread pkg/github/appauth/appauth.go
Comment thread pkg/github/appauth/appauth.go
Comment thread pkg/github/appauth/appauth.go Outdated
Comment thread pkg/github/appauth/appauth.go Outdated
- Move VerifyJWT to test file to avoid exporting test-only helpers
- Use RWMutex with double-check pattern to avoid blocking reads during
  token refresh
- Add UserAgentTransport to GraphQL path when using App auth for
  consistency with REST
- Make GITHUB_APP_PRIVATE_KEY and GITHUB_APP_PRIVATE_KEY_PATH mutually
  exclusive (return error when both are set)
- Only replace literal \n when the private key has no real newlines to
  avoid corrupting correctly-passed keys
- Use safer JWT lifetime (iat=now-30s, exp=now+9m) to stay well within
  GitHub's 10-minute maximum
- Document that base transport must not inject its own Authorization
  header
Copy link
Copy Markdown

@ah-gh2 ah-gh2 left a comment

Choose a reason for hiding this comment

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

Changes in this PR Details ..

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.

Support GitHub App authentication with client credentials

4 participants