This commit is contained in:
1 parent
c6b430a197
commit
ee5205e133
4 files changed
+33
-13
No files matched your search
+13
-7
@@ -96,6 +96,8 @@ function redirect(url, headers = {}) {
|
||||
else responseHeaders.set(name, value);
|
||||
});
|
||||
responseHeaders.set('location', url);
|
||||
responseHeaders.set('cache-control', 'no-store, no-cache, must-revalidate');
|
||||
responseHeaders.set('pragma', 'no-cache');
|
||||
return new Response(null, { status: 302, headers: responseHeaders });
|
||||
}
|
||||
|
||||
@@ -250,32 +252,36 @@ async function startLogin(request, env) {
|
||||
return redirect(authorize.toString(), { 'set-cookie': cookie(env.OAUTH_COOKIE_NAME, signedState, 600) });
|
||||
}
|
||||
|
||||
function oauthError(env, error, detail, status) {
|
||||
return json({ error, detail: detail || '' }, status, { 'set-cookie': cookie(env.OAUTH_COOKIE_NAME, '', 0, { delete: true }) });
|
||||
}
|
||||
|
||||
async function finishLogin(request, env) {
|
||||
const missing = requiredAuthConfig(env);
|
||||
if (missing.length) return json({ error: 'auth_not_configured', missing }, 503);
|
||||
const url = new URL(request.url);
|
||||
const signedState = getCookie(request, env.OAUTH_COOKIE_NAME);
|
||||
const statePayload = await verifyValue(signedState, env.SESSION_SECRET);
|
||||
if (!statePayload) return json({ error: 'invalid_oauth_state' }, 400);
|
||||
if (!statePayload) return oauthError(env, 'invalid_oauth_state', '', 400);
|
||||
let state;
|
||||
try { state = JSON.parse(decoder.decode(fromBase64url(statePayload))); } catch (error) { return json({ error: 'invalid_oauth_state' }, 400); }
|
||||
if (url.searchParams.get('state') !== state.state || Date.now() - state.createdAt > 10 * 60 * 1000) return json({ error: 'invalid_oauth_state' }, 400);
|
||||
try { state = JSON.parse(decoder.decode(fromBase64url(statePayload))); } catch (error) { return oauthError(env, 'invalid_oauth_state', '', 400); }
|
||||
if (url.searchParams.get('state') !== state.state || Date.now() - state.createdAt > 10 * 60 * 1000) return oauthError(env, 'invalid_oauth_state', '', 400);
|
||||
const code = url.searchParams.get('code');
|
||||
if (!code) return json({ error: 'oauth_code_missing', detail: url.searchParams.get('error_description') || url.searchParams.get('error') || '' }, 400);
|
||||
if (!code) return oauthError(env, 'oauth_code_missing', url.searchParams.get('error_description') || url.searchParams.get('error') || '', 400);
|
||||
|
||||
const tokenParams = new URLSearchParams({ grant_type: 'authorization_code', client_id: env.AUTH_CLIENT_ID, redirect_uri: env.AUTH_REDIRECT_URI, code, code_verifier: state.verifier });
|
||||
const tokenResponse = await fetch(env.AUTH_TOKEN_URL, { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' }, body: tokenParams });
|
||||
const tokens = await tokenResponse.json().catch(() => ({}));
|
||||
if (!tokenResponse.ok) return json({ error: 'oauth_token_exchange_failed', detail: tokens.error_description || tokens.error || '' }, 502);
|
||||
if (!tokenResponse.ok) return oauthError(env, 'oauth_token_exchange_failed', tokens.error_description || tokens.error || '', 502);
|
||||
let claims = parseJwt(tokens.id_token || tokens.access_token);
|
||||
if (state.nonce && claims.nonce && state.nonce !== claims.nonce) return json({ error: 'invalid_oauth_nonce' }, 400);
|
||||
if (state.nonce && claims.nonce && state.nonce !== claims.nonce) return oauthError(env, 'invalid_oauth_nonce', '', 400);
|
||||
if (env.AUTH_USERINFO_URL && tokens.access_token) {
|
||||
const userResponse = await fetch(env.AUTH_USERINFO_URL, { headers: { authorization: `Bearer ${tokens.access_token}`, accept: 'application/json' } });
|
||||
const userInfo = await userResponse.json().catch(() => ({}));
|
||||
if (userResponse.ok) claims = { ...claims, ...userInfo };
|
||||
}
|
||||
const user = normalizeClaims(claims);
|
||||
if (!user.ssoSubject) return json({ error: 'sso_subject_missing' }, 502);
|
||||
if (!user.ssoSubject) return oauthError(env, 'sso_subject_missing', '', 502);
|
||||
const sessionPayload = base64url(JSON.stringify({ user, expiresAt: Date.now() + Number(env.SESSION_TTL_SECONDS || 3600) * 1000 }));
|
||||
const session = await signValue(sessionPayload, env.SESSION_SECRET);
|
||||
return redirect(new URL(state.returnUrl || '/', url.origin).toString(), { 'set-cookie': [cookie(env.SESSION_COOKIE_NAME, session, Number(env.SESSION_TTL_SECONDS || 3600)), cookie(env.OAUTH_COOKIE_NAME, '', 0, { delete: true })] });
|
||||
|
||||
Reference in new issue
Block a user