|
1 | 1 | import { DurableObject } from "cloudflare:workers" |
2 | 2 | import { randomUUID } from "node:crypto" |
| 3 | +import { jwtVerify, createRemoteJWKSet } from "jose" |
| 4 | +import { createAppAuth } from "@octokit/auth-app" |
| 5 | +import { Resource } from "sst" |
3 | 6 |
|
4 | 7 | type Env = { |
5 | 8 | SYNC_SERVER: DurableObjectNamespace<SyncServer> |
@@ -218,5 +221,42 @@ export default { |
218 | 221 | }, |
219 | 222 | ) |
220 | 223 | } |
| 224 | + |
| 225 | + if (request.method === "POST" && method === "exchange_github_app_token") { |
| 226 | + const EXPECTED_AUDIENCE = "opencode-github-action" |
| 227 | + const GITHUB_ISSUER = "https://token.actions.githubusercontent.com" |
| 228 | + const JWKS_URL = `${GITHUB_ISSUER}/.well-known/jwks` |
| 229 | + |
| 230 | + // get Authorization header |
| 231 | + const authHeader = request.headers.get("Authorization") |
| 232 | + const token = authHeader?.replace(/^Bearer /, "") |
| 233 | + if (!token) return new Response("Error: authorization header is required", { status: 401 }) |
| 234 | + |
| 235 | + // verify token |
| 236 | + const JWKS = createRemoteJWKSet(new URL(JWKS_URL)) |
| 237 | + try { |
| 238 | + await jwtVerify(token, JWKS, { |
| 239 | + issuer: GITHUB_ISSUER, |
| 240 | + audience: EXPECTED_AUDIENCE, |
| 241 | + }) |
| 242 | + } catch (err) { |
| 243 | + console.error("Token verification failed:", err) |
| 244 | + return new Response(JSON.stringify({ error: "Invalid or expired token" }), { |
| 245 | + status: 403, |
| 246 | + headers: { "Content-Type": "application/json" }, |
| 247 | + }) |
| 248 | + } |
| 249 | + |
| 250 | + // Create app token |
| 251 | + const auth = createAppAuth({ |
| 252 | + appId: Resource.GITHUB_APP_ID.value, |
| 253 | + privateKey: Resource.GITHUB_APP_PRIVATE_KEY.value, |
| 254 | + }) |
| 255 | + const appAuthentication = await auth({ type: "app" }) |
| 256 | + |
| 257 | + return new Response(JSON.stringify({ token: appAuthentication.token }), { |
| 258 | + headers: { "Content-Type": "application/json" }, |
| 259 | + }) |
| 260 | + } |
221 | 261 | }, |
222 | 262 | } |
0 commit comments