Skip to content

Commit 253754c

Browse files
authored
fix: authLoader relying on request.url causing infinite redirects (#78)
1 parent 8d1964f commit 253754c

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/authkit-callback-route.spec.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,75 @@ describe('authLoader', () => {
191191
}),
192192
);
193193
});
194+
195+
it('fixes protocol mismatch for load balancer TLS termination', async () => {
196+
// Set WORKOS_REDIRECT_URI to HTTPS (as configured for production)
197+
const originalRedirectUri = process.env.WORKOS_REDIRECT_URI;
198+
process.env.WORKOS_REDIRECT_URI = 'https://example.com/callback';
199+
200+
try {
201+
const request = createRequestWithSearchParams(new Request('http://example.com/callback'), {
202+
code: 'test-code-123',
203+
});
204+
205+
const loader = authLoader();
206+
const response = await loader({
207+
request,
208+
params: {},
209+
context: {},
210+
});
211+
212+
// Should be a redirect response
213+
assertIsResponse(response);
214+
expect(response.status).toBe(302);
215+
216+
// The redirect URL should be fixed to HTTPS (not HTTP)
217+
const location = response.headers.get('Location');
218+
expect(location).toBe('https://example.com/');
219+
expect(new URL(location!).protocol).toBe('https:');
220+
} finally {
221+
// Restore original env var
222+
if (originalRedirectUri) {
223+
process.env.WORKOS_REDIRECT_URI = originalRedirectUri;
224+
} else {
225+
delete process.env.WORKOS_REDIRECT_URI;
226+
}
227+
}
228+
});
229+
230+
it('preserves port from request URL when fixing protocol mismatch', async () => {
231+
// Set WORKOS_REDIRECT_URI to HTTPS with different port
232+
const originalRedirectUri = process.env.WORKOS_REDIRECT_URI;
233+
process.env.WORKOS_REDIRECT_URI = 'https://example.com:8443/callback';
234+
235+
try {
236+
const request = createRequestWithSearchParams(new Request('http://example.com:3000/callback'), {
237+
code: 'test-code-123',
238+
});
239+
240+
const loader = authLoader();
241+
const response = await loader({
242+
request,
243+
params: {},
244+
context: {},
245+
});
246+
247+
// Should be a redirect response
248+
assertIsResponse(response);
249+
expect(response.status).toBe(302);
250+
251+
// The redirect URL should use HTTPS but preserve the request port (3000)
252+
// This documents current behavior - may need adjustment if port should come from config
253+
const location = response.headers.get('Location');
254+
expect(location).toBe('https://example.com:3000/');
255+
expect(new URL(location!).port).toBe('3000');
256+
} finally {
257+
// Restore original env var
258+
if (originalRedirectUri) {
259+
process.env.WORKOS_REDIRECT_URI = originalRedirectUri;
260+
} else {
261+
delete process.env.WORKOS_REDIRECT_URI;
262+
}
263+
}
264+
});
194265
});

src/authkit-callback-route.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ export function authLoader(options: HandleAuthOptions = {}) {
7070
});
7171
}
7272

73+
// Fix protocol mismatch for load balancer scenarios
74+
// If WORKOS_REDIRECT_URI is HTTPS but request is HTTP, use HTTPS for redirect
75+
const redirectUri = getConfig('redirectUri');
76+
const configUrl = new URL(redirectUri);
77+
if (configUrl.protocol === 'https:' && url.protocol === 'http:') {
78+
url.protocol = 'https:';
79+
}
80+
7381
return redirect(url.toString(), {
7482
headers: {
7583
'Set-Cookie': cookie,

0 commit comments

Comments
 (0)