Skip to content

Commit 728898a

Browse files
Merge pull request #222 from CodeForPhilly/fix/oauth-callback-port
fix(api): keep the port in the GitHub OAuth callback URL
2 parents 72c3137 + c17b1d6 commit 728898a

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

‎apps/api/src/routes/auth.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,12 @@ function callbackRedirectUri(request: FastifyRequest): string {
6565
const protocol = request.headers['x-forwarded-proto']
6666
? String(request.headers['x-forwarded-proto']).split(',')[0]?.trim() ?? 'http'
6767
: request.protocol;
68+
// `request.host` keeps the port (`request.hostname` strips it), which the
69+
// registered callback carries whenever the app isn't on 80/443 — local dev
70+
// on :3001, a test instance on :3100.
6871
const host = request.headers['x-forwarded-host']
69-
? String(request.headers['x-forwarded-host']).split(',')[0]?.trim() ?? request.hostname
70-
: request.hostname;
72+
? String(request.headers['x-forwarded-host']).split(',')[0]?.trim() ?? request.host
73+
: request.host;
7174
return `${protocol}://${host}/api/auth/github/callback`;
7275
}
7376

‎apps/api/tests/github-oauth.test.ts‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,28 @@ describe('GET /api/auth/github/start', () => {
198198
expect(state).toBeTruthy();
199199
});
200200

201+
it('derives redirect_uri from the request host, port included, or from X-Forwarded-* behind a proxy', async () => {
202+
const direct = await app.inject({
203+
method: 'GET',
204+
url: '/api/auth/github/start',
205+
headers: { host: 'devbox:3100' },
206+
remoteAddress: nextTestIp(),
207+
});
208+
expect(new URL(String(direct.headers['location'])).searchParams.get('redirect_uri')).toBe(
209+
'http://devbox:3100/api/auth/github/callback',
210+
);
211+
212+
const proxied = await app.inject({
213+
method: 'GET',
214+
url: '/api/auth/github/start',
215+
headers: { host: '10.0.0.5:3001', 'x-forwarded-host': 'codeforphilly.org', 'x-forwarded-proto': 'https' },
216+
remoteAddress: nextTestIp(),
217+
});
218+
expect(new URL(String(proxied.headers['location'])).searchParams.get('redirect_uri')).toBe(
219+
'https://codeforphilly.org/api/auth/github/callback',
220+
);
221+
});
222+
201223
it('sets cfp_oauth_state and cfp_oauth_session cookies with HttpOnly + SameSite=Lax', async () => {
202224
const res = await app.inject({
203225
method: 'GET',

0 commit comments

Comments
 (0)