|
9 | 9 | * 3. This route forwards to Steward `POST /auth/oauth/exchange`, which |
10 | 10 | * consumes the code and returns `{ token, refreshToken, expiresAt }`. |
11 | 11 | * 4. We verify the JWT (same path as `/api/auth/steward-session`), sync the |
12 | | - * user, set the HttpOnly cookies, and return `{ ok, userId }`. |
| 12 | + * user, set the HttpOnly cookies, and return `{ ok, userId }`. The |
| 13 | + * elizaos.ai hardware checkout origin also receives the access token so |
| 14 | + * its cross-site Stripe checkout POST can use Bearer auth; refresh stays |
| 15 | + * cookie-only. |
13 | 16 | * |
14 | | - * The access and refresh tokens never enter the browser process at any point. |
| 17 | + * The refresh token never enters the browser process; the access token is |
| 18 | + * returned only to the hardware checkout origin that still has to authenticate |
| 19 | + * a cross-site Stripe checkout request with Bearer auth. |
15 | 20 | * |
16 | 21 | * Origin/Referer CSRF check mirrors `/api/auth/steward-session` exactly — the |
17 | 22 | * route is callable from `*.elizacloud.ai` and `elizaos.ai` only (plus |
@@ -99,6 +104,16 @@ function checkOrigin( |
99 | 104 | }; |
100 | 105 | } |
101 | 106 |
|
| 107 | +function shouldReturnClientToken( |
| 108 | + c: { req: { header: (name: string) => string | undefined } }, |
| 109 | + isProduction: boolean, |
| 110 | +): boolean { |
| 111 | + const origin = |
| 112 | + originHost(c.req.header("origin")) ?? originHost(c.req.header("referer")); |
| 113 | + if (origin === "elizaos.ai" || origin === "www.elizaos.ai") return true; |
| 114 | + return !isProduction && origin !== null && LOCAL_DEV_ORIGIN_HOSTS.has(origin); |
| 115 | +} |
| 116 | + |
102 | 117 | // ─── Helpers ────────────────────────────────────────────────────────────── |
103 | 118 |
|
104 | 119 | function stewardSecretConfigured(env: StewardVerifyEnv): boolean { |
@@ -396,8 +411,7 @@ app.post("/", async (c) => { |
396 | 411 | stewardUserId: claims.userId, |
397 | 412 | expiresAt: exchange.data.expiresAt, |
398 | 413 | expiresIn: exchange.data.expiresIn, |
399 | | - token, |
400 | | - refreshToken, |
| 414 | + ...(shouldReturnClientToken(c, isProduction) ? { token, refreshToken } : {}), |
401 | 415 | }); |
402 | 416 | }); |
403 | 417 |
|
|
0 commit comments