From ad8977817ae3a3367164f6fa9b898e4074c3d97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Demirel?= Date: Fri, 3 Apr 2026 23:11:37 +0300 Subject: [PATCH] fix: cf secret --- src/env.d.ts | 19 ++++++++++++++++ src/lib/auth.ts | 40 ++++++++++++++++++---------------- src/middleware.ts | 5 +++-- src/pages/api/auth/callback.ts | 17 ++++++++------- src/pages/api/auth/login.ts | 10 ++++----- src/pages/api/auth/me.ts | 13 ++++++----- 6 files changed, 64 insertions(+), 40 deletions(-) create mode 100644 src/env.d.ts diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..c561c96 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,19 @@ +interface CloudflareEnv { + JWT_SECRET: string + GITHUB_CLIENT_ID: string + GITHUB_CLIENT_SECRET: string + GITHUB_CALLBACK_URL: string + DEV?: string +} + +declare global { + namespace App { + interface Locals { + runtime: { + env: CloudflareEnv + } + } + } +} + +export {} diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 2d3ca89..30bbcb6 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,15 +1,17 @@ import * as jose from 'jose' -const getSecret = () => { - const secret = import.meta.env.JWT_SECRET +type Env = Record + +const getSecret = (env: Env) => { + const secret = env.JWT_SECRET if (!secret) { throw new Error('JWT_SECRET is not set') } return new TextEncoder().encode(secret) } -const getTokenSecret = () => { - const secret = import.meta.env.JWT_SECRET +const getTokenSecret = (env: Env) => { + const secret = env.JWT_SECRET if (!secret) { throw new Error('JWT_SECRET is not set') } @@ -32,8 +34,8 @@ export interface GitHubTokens { scope: string } -export async function createToken(user: SessionUser): Promise { - const secret = getSecret() +export async function createToken(user: SessionUser, env: Env): Promise { + const secret = getSecret(env) return await new jose.SignJWT({ ...user }) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() @@ -41,9 +43,9 @@ export async function createToken(user: SessionUser): Promise { .sign(secret) } -export async function verifyToken(token: string): Promise { +export async function verifyToken(token: string, env: Env): Promise { try { - const secret = getSecret() + const secret = getSecret(env) const { payload } = await jose.jwtVerify(token, secret) return payload as unknown as SessionUser } catch { @@ -51,8 +53,8 @@ export async function verifyToken(token: string): Promise { } } -export async function createTokensCookie(tokens: GitHubTokens): Promise { - const secret = getTokenSecret() +export async function createTokensCookie(tokens: GitHubTokens, env: Env): Promise { + const secret = getTokenSecret(env) return await new jose.SignJWT({ ...tokens }) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() @@ -60,9 +62,9 @@ export async function createTokensCookie(tokens: GitHubTokens): Promise .sign(secret) } -export async function verifyTokensCookie(token: string): Promise { +export async function verifyTokensCookie(token: string, env: Env): Promise { try { - const secret = getTokenSecret() + const secret = getTokenSecret(env) const { payload } = await jose.jwtVerify(token, secret) return payload as unknown as GitHubTokens } catch { @@ -70,9 +72,9 @@ export async function verifyTokensCookie(token: string): Promise { - const clientId = import.meta.env.GITHUB_CLIENT_ID - const clientSecret = import.meta.env.GITHUB_CLIENT_SECRET +export async function refreshAccessToken(refreshToken: string, env: Env): Promise { + const clientId = env.GITHUB_CLIENT_ID + const clientSecret = env.GITHUB_CLIENT_SECRET if (!clientId || !clientSecret) { return null @@ -123,8 +125,8 @@ export function getTokensCookieName(): string { return TOKEN_COOKIE_NAME } -export function getCookieOptions() { - const isDev = import.meta.env.DEV +export function getCookieOptions(env: Env) { + const isDev = env.DEV return { httpOnly: true, secure: !isDev, @@ -134,8 +136,8 @@ export function getCookieOptions() { } } -export function getTokensCookieOptions() { - const isDev = import.meta.env.DEV +export function getTokensCookieOptions(env: Env) { + const isDev = env.DEV return { httpOnly: true, secure: !isDev, diff --git a/src/middleware.ts b/src/middleware.ts index 9acc8f9..00a6fb5 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -4,9 +4,10 @@ import { verifyToken, getCookieName, type SessionUser } from './lib/auth' export const onRequest = defineMiddleware(async (context, next) => { const cookieName = getCookieName() const token = context.cookies.get(cookieName)?.value + const env = context.locals.runtime?.env - if (token) { - const user = await verifyToken(token) + if (token && env) { + const user = await verifyToken(token, env) if (user) { context.locals.user = user } diff --git a/src/pages/api/auth/callback.ts b/src/pages/api/auth/callback.ts index f8888ba..6291fb0 100644 --- a/src/pages/api/auth/callback.ts +++ b/src/pages/api/auth/callback.ts @@ -12,10 +12,11 @@ import { type GitHubTokens, } from '../../../lib/auth' -export const GET: APIRoute = async ({ url, redirect, cookies }) => { - const clientId = import.meta.env.GITHUB_CLIENT_ID - const clientSecret = import.meta.env.GITHUB_CLIENT_SECRET - const callbackUrl = import.meta.env.GITHUB_CALLBACK_URL +export const GET: APIRoute = async ({ url, redirect, cookies, locals }) => { + const env = locals.runtime.env + const clientId = env.GITHUB_CLIENT_ID + const clientSecret = env.GITHUB_CLIENT_SECRET + const callbackUrl = env.GITHUB_CALLBACK_URL if (!clientId || !clientSecret || !callbackUrl) { return new Response('GitHub OAuth not configured', { status: 500 }) @@ -67,8 +68,8 @@ export const GET: APIRoute = async ({ url, redirect, cookies }) => { name: githubUser.name, } - const userToken = await createToken(sessionUser) - cookies.set(getCookieName(), userToken, getCookieOptions()) + const userToken = await createToken(sessionUser, env) + cookies.set(getCookieName(), userToken, getCookieOptions(env)) if (refreshToken) { const tokens: GitHubTokens = { @@ -77,8 +78,8 @@ export const GET: APIRoute = async ({ url, redirect, cookies }) => { expires_at: Date.now() + (tokenData.expires_in || 3600) * 1000, scope: tokenData.scope || '', } - const tokensCookie = await createTokensCookie(tokens) - cookies.set(getTokensCookieName(), tokensCookie, getTokensCookieOptions()) + const tokensCookie = await createTokensCookie(tokens, env) + cookies.set(getTokensCookieName(), tokensCookie, getTokensCookieOptions(env)) } return redirect('/') diff --git a/src/pages/api/auth/login.ts b/src/pages/api/auth/login.ts index c637933..e02c8ee 100644 --- a/src/pages/api/auth/login.ts +++ b/src/pages/api/auth/login.ts @@ -1,12 +1,12 @@ export const prerender = false import type { APIRoute } from 'astro' -import { createToken, getCookieName, getCookieOptions, type SessionUser } from '../../../lib/auth' -export const GET: APIRoute = async ({ url, redirect }) => { - const clientId = import.meta.env.GITHUB_CLIENT_ID - const clientSecret = import.meta.env.GITHUB_CLIENT_SECRET - const callbackUrl = import.meta.env.GITHUB_CALLBACK_URL +export const GET: APIRoute = async ({ redirect, locals }) => { + const env = locals.runtime.env + const clientId = env.GITHUB_CLIENT_ID + const clientSecret = env.GITHUB_CLIENT_SECRET + const callbackUrl = env.GITHUB_CALLBACK_URL if (!clientId || !clientSecret || !callbackUrl) { return new Response('GitHub OAuth not configured', { status: 500 }) diff --git a/src/pages/api/auth/me.ts b/src/pages/api/auth/me.ts index 293ccd7..a4bec49 100644 --- a/src/pages/api/auth/me.ts +++ b/src/pages/api/auth/me.ts @@ -11,7 +11,8 @@ import { getTokensCookieOptions, } from '../../../lib/auth' -export const GET: APIRoute = async ({ cookies }) => { +export const GET: APIRoute = async ({ cookies, locals }) => { + const env = locals.runtime.env const sessionToken = cookies.get(getCookieName())?.value const tokensToken = cookies.get(getTokensCookieName())?.value @@ -22,7 +23,7 @@ export const GET: APIRoute = async ({ cookies }) => { }) } - const user = await verifyToken(sessionToken) + const user = await verifyToken(sessionToken, env) if (!user) { return new Response(JSON.stringify({ user: null, accessToken: null }), { status: 200, @@ -30,18 +31,18 @@ export const GET: APIRoute = async ({ cookies }) => { }) } - let tokens = await verifyTokensCookie(tokensToken) + let tokens = await verifyTokensCookie(tokensToken, env) if (tokens) { const isExpired = Date.now() >= tokens.expires_at const shouldRefresh = tokens.refresh_token && isExpired if (shouldRefresh) { - const newTokens = await refreshAccessToken(tokens.refresh_token) + const newTokens = await refreshAccessToken(tokens.refresh_token, env) if (newTokens) { tokens = newTokens - const newTokensCookie = await createTokensCookie(newTokens) - cookies.set(getTokensCookieName(), newTokensCookie, getTokensCookieOptions()) + const newTokensCookie = await createTokensCookie(newTokens, env) + cookies.set(getTokensCookieName(), newTokensCookie, getTokensCookieOptions(env)) } } }