Deploy EG-BIM QA Gateway / deploy (push) Successful in 54s
Add the top-right account icon with the signed-in name and logout link. Expire the Q&A session before redirecting to the configured inquiry homepage in both environments. Preserve login return URL checks and ignore request-controlled logout destinations. Validation: 106 tests, syntax checks, and mocked Chromium desktop/mobile regressions pass, including session-cookie removal and the destination navigation request with external networking blocked.
45 lines
2.3 KiB
JavaScript
45 lines
2.3 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import worker from '../src/index.js';
|
|
|
|
const destination = 'https://test.baroncs.co.kr/ko/sw-inquiry.html';
|
|
|
|
for (const configFile of ['wrangler.toml', 'wrangler.production.toml']) {
|
|
test(configFile + ' logout expires its own session and redirects to the inquiry homepage', async () => {
|
|
const config = readFileSync(new URL('../' + configFile, import.meta.url), 'utf8');
|
|
const setting = name => config.match(new RegExp('^' + name + ' = "([^"]+)"', 'm'))[1];
|
|
const env = {
|
|
SESSION_COOKIE_NAME: setting('SESSION_COOKIE_NAME'),
|
|
AUTH_POST_LOGOUT_REDIRECT_URI: setting('AUTH_POST_LOGOUT_REDIRECT_URI')
|
|
};
|
|
const response = await worker.fetch(new Request('https://qa.example.test/auth/logout?return_url=https://untrusted.example/&redirect_uri=https://untrusted.example/', {
|
|
headers: { cookie: env.SESSION_COOKIE_NAME + '=existing-session' }
|
|
}), env);
|
|
assert.equal(response.status, 302);
|
|
assert.equal(response.headers.get('location'), destination);
|
|
const cookie = response.headers.get('set-cookie');
|
|
assert.ok(cookie.startsWith(env.SESSION_COOKIE_NAME + '=;'));
|
|
for (const attribute of ['Max-Age=0', 'Path=/', 'Secure', 'HttpOnly', 'SameSite=Lax', 'Expires=Thu, 01 Jan 1970 00:00:00 GMT']) assert.ok(cookie.includes(attribute));
|
|
assert.match(response.headers.get('cache-control'), /no-store/);
|
|
});
|
|
}
|
|
|
|
for (const [label, value, expected] of [
|
|
['no configured destination', undefined, '/'],
|
|
['same-origin relative destination', '/signed-out', '/signed-out'],
|
|
['invalid URL', 'https://[invalid', '/'],
|
|
['script URL', 'javascript:alert(1)', '/'],
|
|
['external insecure URL', 'http://untrusted.example/', '/'],
|
|
['URL containing credentials', 'https://user:pass@untrusted.example/', '/']
|
|
]) {
|
|
test('logout handles ' + label + ' while clearing the session', async () => {
|
|
const response = await worker.fetch(new Request('https://qa.example.test/auth/logout'), {
|
|
SESSION_COOKIE_NAME: 'fixture_session', AUTH_POST_LOGOUT_REDIRECT_URI: value
|
|
});
|
|
assert.equal(response.status, 302);
|
|
assert.equal(response.headers.get('location'), 'https://qa.example.test' + expected);
|
|
assert.match(response.headers.get('set-cookie'), /fixture_session=; Max-Age=0/);
|
|
});
|
|
}
|