Skip to content

Comments

Add Cloudflare Worker backend for secure GitHub App authentication#21

Merged
yaito3014 merged 11 commits intomainfrom
claude/cloudflare-worker-backend-vNnEm
Feb 18, 2026
Merged

Add Cloudflare Worker backend for secure GitHub App authentication#21
yaito3014 merged 11 commits intomainfrom
claude/cloudflare-worker-backend-vNnEm

Conversation

@yaito3014
Copy link
Member

Summary

This PR introduces a new Cloudflare Worker backend that enables secure GitHub App authentication using GitHub Actions OIDC tokens, while maintaining backward compatibility with direct private key authentication.

Key Changes

  • New Cloudflare Worker (worker/src/index.ts):

    • Implements a /token endpoint that exchanges GitHub Actions OIDC tokens for GitHub App installation access tokens
    • Verifies OIDC tokens using GitHub's public JWKS
    • Creates short-lived GitHub App JWTs to authenticate API calls
    • Looks up app installations and creates installation access tokens
    • Includes comprehensive error handling and validation
  • Updated GitHub Action (src/index.ts):

    • Added support for two authentication methods:
      • Option A (Recommended): Use WORKER_URL to exchange OIDC tokens via the Cloudflare Worker (requires id-token: write permission)
      • Option B (Legacy): Use PRIVATE_KEY to authenticate directly as the GitHub App
    • Implements getInstallationTokenFromWorker() helper to request OIDC tokens and exchange them with the worker
    • Automatically selects the appropriate authentication method based on provided inputs
  • Configuration Updates:

    • action.yml: Made PRIVATE_KEY optional, added new WORKER_URL input
    • Added worker configuration files: wrangler.toml, tsconfig.json, package.json

Implementation Details

  • The worker uses the jose library for JWT verification and creation
  • OIDC token verification includes issuer and audience validation
  • GitHub App JWT is created with 10-minute expiry (GitHub's maximum)
  • Installation access tokens are returned with their expiration time
  • Comprehensive error messages guide users when the app is not installed or authentication fails
  • Fixed typo in action.yml: requirdrequired

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F

The worker runs at POST /token and accepts a GitHub Actions OIDC JWT
(audience = worker URL) in the Authorization header. It verifies the
token against GitHub's public JWKS, then issues a GitHub App
installation access token for the repository claimed in the OIDC payload.
This eliminates the need for users to store the App private key in their
repository secrets.

Action changes:
- PRIVATE_KEY is now optional (backward compatible)
- New optional WORKER_URL input: when set, the action uses GitHub OIDC
  to authenticate via the worker instead of a private key
- Job must have `permissions: id-token: write` when using WORKER_URL

Worker (worker/):
- wrangler.toml: Cloudflare Worker config; GITHUB_APP_PRIVATE_KEY is
  set as a wrangler secret, GITHUB_APP_ID as a var
- src/index.ts: verifies GitHub OIDC JWT (jose), creates App JWT,
  looks up installation, and returns an installation access token

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F
Replace PRIVATE_KEY with WORKER_URL pointing to the deployed worker.
Add explicit permissions for OIDC (id-token: write), PR comments
(pull-requests: write), and log access (actions: read). Remove the
CppWarningNotifier environment since no secrets are needed.

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F
@cppwarningnotifier

This comment has been minimized.

WORKER_URL is now the only authentication method. Removes the App
import, PRIVATE_KEY input, and the dual-path auth logic.

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F
@cppwarningnotifier

This comment has been minimized.

…code

- Replace heavy `octokit` package with `@octokit/rest` + `@octokit/graphql`
  (bundle: 8,828 -> 4,007 lines)
- Fix GraphQL injection: use parameterized variables instead of string
  interpolation for minimizeComment mutation
- Remove dead `body` null-coalescing logic (`let body = null; body ??= ...`
  simplified to `const body = ...`)
- Hoist warningRegex/errorRegex out of the loop
- Replace hand-rolled CompositeKeyMap/groupBy with Map and Map.groupBy
- Normalize all variable names to camelCase
- Remove no-op runnerEnvironment check in worker

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F
@cppwarningnotifier

This comment has been minimized.

- action/: GitHub Action source, build config, and bundled output
- worker/: Cloudflare Worker backend (already in place)
- test/: sample C++ project used by the CI workflow
- Root keeps only action.yml (GHA requirement) and repo-level config

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F
@cppwarningnotifier

This comment has been minimized.

@cppwarningnotifier

This comment has been minimized.

@cppwarningnotifier

This comment has been minimized.

@yaito3014 yaito3014 added the github_actions Pull requests that update GitHub Actions code label Feb 18, 2026
@yaito3014 yaito3014 self-assigned this Feb 18, 2026
action/:
  @rollup/plugin-commonjs    28 -> 29
  @rollup/plugin-node-resolve 16.0.1 -> 16.0.3
  @rollup/plugin-typescript  12.1.2 -> 12.3.0
  @types/node                22 -> 25
  rollup                     4.40.0 -> 4.57.1
  typescript                 5.8.3 -> 5.9.3

worker/:
  jose                       5.9.6 -> 6.1.3
  @cloudflare/workers-types  4.20241022.0 -> 4.20260218.0
  typescript                 5.8.3 -> 5.9.3
  wrangler                   3.99.0 -> 4.66.0

https://claude.ai/code/session_01NpiSv9DJeWXyK77tjPGt8F
@cppwarningnotifier
Copy link

@yaito3014 yaito3014 merged commit 78330a2 into main Feb 18, 2026
13 checks passed
@yaito3014 yaito3014 deleted the claude/cloudflare-worker-backend-vNnEm branch February 18, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

github_actions Pull requests that update GitHub Actions code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants