From 635d70b91e0831e88041dfb42b420ba8d6f65e29 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 27 Mar 2026 17:21:54 +0100 Subject: [PATCH 1/3] feat: support for narrowing cors --- .env.development.example | 3 ++- .env.production.example | 3 ++- README.md | 3 ++- src/server.ts | 8 +++++++- test/cors.test.ts | 26 ++++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 test/cors.test.ts diff --git a/.env.development.example b/.env.development.example index 7a0814a..bf3f9fa 100644 --- a/.env.development.example +++ b/.env.development.example @@ -3,4 +3,5 @@ GITHUB_CLIENT_SECRET=your_github_oauth_client_secret GITHUB_AUTH_ISSUER=https://your_unique_authentication_issuer JWT_PRIVATE_KEY_PATH=./private-key.pem JWT_PUBLIC_KEY_PATH=./public-key.pem -JWT_KEY_ID=your-api-key-1 \ No newline at end of file +JWT_KEY_ID=your-api-key-1 +CORS_ORIGIN= \ No newline at end of file diff --git a/.env.production.example b/.env.production.example index d54d869..29e8db1 100644 --- a/.env.production.example +++ b/.env.production.example @@ -2,4 +2,5 @@ GITHUB_CLIENT_ID=your_github_oauth_client_id GITHUB_CLIENT_SECRET=your_github_oauth_client_secret GITHUB_AUTH_ISSUER=https://your_unique_authentication_issuer COOKIE_DOMAIN=.yourdomain.com -COOKIE_SAME_SITE=lax \ No newline at end of file +COOKIE_SAME_SITE=lax +CORS_ORIGIN= \ No newline at end of file diff --git a/README.md b/README.md index 69d2bd8..7817e43 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,10 @@ GITHUB_AUTH_ISSUER=https://your-domain.com/auth/github > [!NOTE] > The issuer must be unique for the service. The authentication modules use it to distinguish the providers. -3. (Optional) Configure cookie settings for cross-subdomain support in `.env.production`: +3. (Optional) Configure CORS and cookie settings in `.env.production`: ```bash +CORS_ORIGIN=https://yourapp.yourdomain.com COOKIE_DOMAIN=.yourdomain.com COOKIE_SAME_SITE=lax ``` diff --git a/src/server.ts b/src/server.ts index 3a4948d..abe93bd 100644 --- a/src/server.ts +++ b/src/server.ts @@ -15,6 +15,8 @@ import { authJwks } from './handlers/auth/jwks'; const { version: appVersion, name: appName, description: appDescription } = packageJson; +const corsOrigin = process.env.CORS_ORIGIN; + export const app = new Elysia() .error({ FetchApiError, @@ -42,7 +44,11 @@ export const app = new Elysia() } }) ) - .use(cors()) + .use( + cors({ + ...(corsOrigin !== undefined && { origin: corsOrigin }) + }) + ) .decorate('github', new GitHubDecorator()) .decorate('jwt', new JwtDecorator()) .group('/v1', (app) => diff --git a/test/cors.test.ts b/test/cors.test.ts new file mode 100644 index 0000000..4f278dc --- /dev/null +++ b/test/cors.test.ts @@ -0,0 +1,26 @@ +import { afterEach, describe, expect, it, mock } from 'bun:test'; + +describe('server > cors', () => { + afterEach(() => { + mock.clearAllMocks(); + }); + + describe('CORS', () => { + it('should restrict origin when CORS_ORIGIN is set', async () => { + const corsOrigin = process.env.CORS_ORIGIN; + process.env.CORS_ORIGIN = 'https://console.juno.build'; + + const { app } = await import('../src/server'); + + const response = await app.handle( + new Request('http://localhost/v1/auth/certs', { + headers: { Origin: 'https://yolo.com' } + }) + ); + + expect(response.headers.get('access-control-allow-origin')).toBeNull(); + + process.env.CORS_ORIGIN = corsOrigin; + }); + }); +}); From 671d2f731331854058ebaf835288bdee55683522 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 27 Mar 2026 17:30:06 +0100 Subject: [PATCH 2/3] chore: isolate test --- bunfig.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bunfig.toml b/bunfig.toml index a1f7644..1ee9aed 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -1,2 +1,3 @@ [test] -preload = ["./test-setup.ts"] \ No newline at end of file +preload = ["./test-setup.ts"] +isolateModules = true \ No newline at end of file From df6cc8b6ebbbe1a7a3acd270ce9d83e468c3b7cc Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 27 Mar 2026 17:32:35 +0100 Subject: [PATCH 3/3] chore: test are not isolated --- bunfig.toml | 1 - test/cors.test.ts | 26 -------------------------- 2 files changed, 27 deletions(-) delete mode 100644 test/cors.test.ts diff --git a/bunfig.toml b/bunfig.toml index 1ee9aed..9e75dd2 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -1,3 +1,2 @@ [test] preload = ["./test-setup.ts"] -isolateModules = true \ No newline at end of file diff --git a/test/cors.test.ts b/test/cors.test.ts deleted file mode 100644 index 4f278dc..0000000 --- a/test/cors.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { afterEach, describe, expect, it, mock } from 'bun:test'; - -describe('server > cors', () => { - afterEach(() => { - mock.clearAllMocks(); - }); - - describe('CORS', () => { - it('should restrict origin when CORS_ORIGIN is set', async () => { - const corsOrigin = process.env.CORS_ORIGIN; - process.env.CORS_ORIGIN = 'https://console.juno.build'; - - const { app } = await import('../src/server'); - - const response = await app.handle( - new Request('http://localhost/v1/auth/certs', { - headers: { Origin: 'https://yolo.com' } - }) - ); - - expect(response.headers.get('access-control-allow-origin')).toBeNull(); - - process.env.CORS_ORIGIN = corsOrigin; - }); - }); -});