sign cooies
This commit is contained in:
@@ -39,23 +39,51 @@ export async function gscGoogleCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { code, state } = query.data;
|
const { code, state } = query.data;
|
||||||
const storedState = req.cookies.gsc_oauth_state ?? null;
|
|
||||||
const codeVerifier = req.cookies.gsc_code_verifier ?? null;
|
|
||||||
const projectId = req.cookies.gsc_project_id ?? null;
|
|
||||||
|
|
||||||
const hasStoredState = storedState !== null;
|
const rawStoredState = req.cookies.gsc_oauth_state ?? null;
|
||||||
const hasCodeVerifier = codeVerifier !== null;
|
const rawCodeVerifier = req.cookies.gsc_code_verifier ?? null;
|
||||||
const hasProjectId = projectId !== null;
|
const rawProjectId = req.cookies.gsc_project_id ?? null;
|
||||||
const hasAllCookies = hasStoredState && hasCodeVerifier && hasProjectId;
|
|
||||||
if (!hasAllCookies) {
|
const storedStateResult =
|
||||||
|
rawStoredState !== null ? req.unsignCookie(rawStoredState) : null;
|
||||||
|
const codeVerifierResult =
|
||||||
|
rawCodeVerifier !== null ? req.unsignCookie(rawCodeVerifier) : null;
|
||||||
|
const projectIdResult =
|
||||||
|
rawProjectId !== null ? req.unsignCookie(rawProjectId) : null;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
storedStateResult?.value &&
|
||||||
|
codeVerifierResult?.value &&
|
||||||
|
projectIdResult?.value
|
||||||
|
)
|
||||||
|
) {
|
||||||
throw new LogError('Missing GSC OAuth cookies', {
|
throw new LogError('Missing GSC OAuth cookies', {
|
||||||
storedState: !hasStoredState,
|
storedState: !storedStateResult?.value,
|
||||||
codeVerifier: !hasCodeVerifier,
|
codeVerifier: !codeVerifierResult?.value,
|
||||||
projectId: !hasProjectId,
|
projectId: !projectIdResult?.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state !== storedState) {
|
if (
|
||||||
|
!(
|
||||||
|
storedStateResult?.valid &&
|
||||||
|
codeVerifierResult?.valid &&
|
||||||
|
projectIdResult?.valid
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new LogError('Invalid GSC OAuth cookies', {
|
||||||
|
storedState: !storedStateResult?.value,
|
||||||
|
codeVerifier: !codeVerifierResult?.value,
|
||||||
|
projectId: !projectIdResult?.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const stateStr = storedStateResult?.value;
|
||||||
|
const codeVerifierStr = codeVerifierResult?.value;
|
||||||
|
const projectIdStr = projectIdResult?.value;
|
||||||
|
|
||||||
|
if (state !== stateStr) {
|
||||||
throw new LogError('GSC OAuth state mismatch', {
|
throw new LogError('GSC OAuth state mismatch', {
|
||||||
hasState: true,
|
hasState: true,
|
||||||
hasStoredState: true,
|
hasStoredState: true,
|
||||||
@@ -65,7 +93,7 @@ export async function gscGoogleCallback(
|
|||||||
|
|
||||||
const tokens = await googleGsc.validateAuthorizationCode(
|
const tokens = await googleGsc.validateAuthorizationCode(
|
||||||
code,
|
code,
|
||||||
codeVerifier
|
codeVerifierStr
|
||||||
);
|
);
|
||||||
|
|
||||||
const accessToken = tokens.accessToken();
|
const accessToken = tokens.accessToken();
|
||||||
@@ -79,18 +107,20 @@ export async function gscGoogleCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const project = await db.project.findUnique({
|
const project = await db.project.findUnique({
|
||||||
where: { id: projectId },
|
where: { id: projectIdStr },
|
||||||
select: { id: true, organizationId: true },
|
select: { id: true, organizationId: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
throw new LogError('Project not found for GSC connection', { projectId });
|
throw new LogError('Project not found for GSC connection', {
|
||||||
|
projectId: projectIdStr,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.gscConnection.upsert({
|
await db.gscConnection.upsert({
|
||||||
where: { projectId },
|
where: { projectId: projectIdStr },
|
||||||
create: {
|
create: {
|
||||||
projectId,
|
projectId: projectIdStr,
|
||||||
accessToken: encrypt(accessToken),
|
accessToken: encrypt(accessToken),
|
||||||
refreshToken: encrypt(refreshToken),
|
refreshToken: encrypt(refreshToken),
|
||||||
accessTokenExpiresAt,
|
accessTokenExpiresAt,
|
||||||
@@ -111,7 +141,7 @@ export async function gscGoogleCallback(
|
|||||||
|
|
||||||
const dashboardUrl =
|
const dashboardUrl =
|
||||||
process.env.DASHBOARD_URL || process.env.NEXT_PUBLIC_DASHBOARD_URL!;
|
process.env.DASHBOARD_URL || process.env.NEXT_PUBLIC_DASHBOARD_URL!;
|
||||||
const redirectUrl = `${dashboardUrl}/${project.organizationId}/${projectId}/settings/gsc`;
|
const redirectUrl = `${dashboardUrl}/${project.organizationId}/${projectIdStr}/settings/gsc`;
|
||||||
return reply.redirect(redirectUrl);
|
return reply.redirect(redirectUrl);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
req.log.error(error);
|
req.log.error(error);
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export const gscRouter = createTRPCRouter({
|
|||||||
url.searchParams.set('access_type', 'offline');
|
url.searchParams.set('access_type', 'offline');
|
||||||
url.searchParams.set('prompt', 'consent');
|
url.searchParams.set('prompt', 'consent');
|
||||||
|
|
||||||
const cookieOpts = { maxAge: 60 * 10 };
|
const cookieOpts = { maxAge: 60 * 10, signed: true };
|
||||||
ctx.setCookie('gsc_oauth_state', state, cookieOpts);
|
ctx.setCookie('gsc_oauth_state', state, cookieOpts);
|
||||||
ctx.setCookie('gsc_code_verifier', codeVerifier, cookieOpts);
|
ctx.setCookie('gsc_code_verifier', codeVerifier, cookieOpts);
|
||||||
ctx.setCookie('gsc_project_id', input.projectId, cookieOpts);
|
ctx.setCookie('gsc_project_id', input.projectId, cookieOpts);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export async function createContext({ req, res }: CreateFastifyContextOptions) {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
res.setCookie(key, value, {
|
res.setCookie(key, value, {
|
||||||
maxAge: options.maxAge,
|
maxAge: options.maxAge,
|
||||||
|
signed: options.signed,
|
||||||
...COOKIE_OPTIONS,
|
...COOKIE_OPTIONS,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -112,5 +112,6 @@ export type ISetCookie = (
|
|||||||
sameSite?: 'lax' | 'strict' | 'none';
|
sameSite?: 'lax' | 'strict' | 'none';
|
||||||
secure?: boolean;
|
secure?: boolean;
|
||||||
httpOnly?: boolean;
|
httpOnly?: boolean;
|
||||||
|
signed?: boolean;
|
||||||
},
|
},
|
||||||
) => void;
|
) => void;
|
||||||
|
|||||||
Reference in New Issue
Block a user