Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
pilcrowonpaper committed Oct 30, 2024
2 parents d898ba9 + 86da6b9 commit 6428975
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 25 deletions.
4 changes: 2 additions & 2 deletions pages/sessions/basic-api/drizzle-orm.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ import { sha256 } from "@oslojs/crypto/sha2";

// ...

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down Expand Up @@ -253,7 +253,7 @@ export function generateSessionToken(): string {
return token;
}

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down
4 changes: 2 additions & 2 deletions pages/sessions/basic-api/mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ import { sha256 } from "@oslojs/crypto/sha2";

// ...

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down Expand Up @@ -195,7 +195,7 @@ export function generateSessionToken(): string {
return token;
}

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down
2 changes: 1 addition & 1 deletion pages/sessions/basic-api/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ import { sha256 } from "@oslojs/crypto/sha2";

// ...

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down
4 changes: 2 additions & 2 deletions pages/sessions/basic-api/prisma.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ import { sha256 } from "@oslojs/crypto/sha2";

// ...

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down Expand Up @@ -186,7 +186,7 @@ export function generateSessionToken(): string {
return token;
}

export async function createSession(token: string, userId: number): Session {
export async function createSession(token: string, userId: number): Promise<Session> {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const session: Session = {
id: sessionId,
Expand Down
2 changes: 1 addition & 1 deletion pages/sessions/cookies/astro.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ CSRF protection is a must when using cookies. From Astro v5.0, basic CSRF protec
export default defineConfig({
output: "server",
security: {
checkOrigin: false
checkOrigin: true
}
});
```
Expand Down
17 changes: 12 additions & 5 deletions pages/sessions/cookies/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ import { cookies } from "next/headers";

// ...

export function setSessionTokenCookie(token: string, expiresAt: Date): void {
cookies().set("session", token, {
export async function setSessionTokenCookie(token: string, expiresAt: Date): Promise<void> {
const cookieStore = await cookies();
cookieStore.set("session", token, {
httpOnly: true,
sameSite: "lax",
secure: process.env.NODE_ENV === "production",
Expand All @@ -72,8 +73,9 @@ export function setSessionTokenCookie(token: string, expiresAt: Date): void {
});
}

export function deleteSessionTokenCookie(): void {
cookies().set("session", "", {
export async function deleteSessionTokenCookie(): Promise<void> {
const cookieStore = await cookies();
cookieStore.set("session", "", {
httpOnly: true,
sameSite: "lax",
secure: process.env.NODE_ENV === "production",
Expand All @@ -83,6 +85,8 @@ export function deleteSessionTokenCookie(): void {
}
```

> Before Next.js 15, `cookies()` was synchronous. If you are using an older version, you should replace `await cookies()` with `cookies()`. You should also switch the function return type to `void`, and remove the `async` keyword.
Since we can't extend set cookies insides server components due to a limitation with React, we recommend continuously extending the cookie expiration inside middleware. However, this comes with its own issue. We can't detect if a new cookie was set inside server actions or route handlers from middleware. This becomes an issue if we need to assign a new session inside server actions (e.g. after updating the password) as the middleware cookie will override it. As such, we'll only extend the cookie expiration on GET requests.

> While Lucia v3 recommended setup extended session cookie lifetime, it did not avoid the revalidation issue.
Expand Down Expand Up @@ -154,7 +158,8 @@ import { cache } from "react";
// ...

export const getCurrentSession = cache(async (): Promise<SessionValidationResult> => {
const token = cookies().get("session")?.value ?? null;
const cookieStore = await cookies();
const token = cookieStore.get("session")?.value ?? null;
if (token === null) {
return { session: null, user: null };
}
Expand All @@ -163,6 +168,8 @@ export const getCurrentSession = cache(async (): Promise<SessionValidationResult
});
```

> On versions of Next.js below 15, replace `await cookies()` with `cookies()`.
This function can be used in server components, server actions, and route handlers (but importantly not middleware).

```ts
Expand Down
12 changes: 7 additions & 5 deletions pages/tutorials/github-oauth/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ export async function GET(): Promise<Response> {
const state = generateState();
const url = github.createAuthorizationURL(state, []);

cookies().set("github_oauth_state", state, {
const cookieStore = await cookies();
cookieStore.set("github_oauth_state", state, {
path: "/",
secure: process.env.NODE_ENV === "production",
httpOnly: true,
Expand Down Expand Up @@ -117,7 +118,8 @@ export async function GET(request: Request): Promise<Response> {
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const storedState = cookies().get("github_oauth_state")?.value ?? null;
const cookieStore = await cookies();
const storedState = cookieStore.get("github_oauth_state")?.value ?? null;
if (code === null || state === null || storedState === null) {
return new Response(null, {
status: 400
Expand Down Expand Up @@ -153,7 +155,7 @@ export async function GET(request: Request): Promise<Response> {
if (existingUser !== null) {
const sessionToken = generateSessionToken();
const session = await createSession(sessionToken, existingUser.id);
setSessionTokenCookie(sessionToken, session.expiresAt);
await setSessionTokenCookie(sessionToken, session.expiresAt);
return new Response(null, {
status: 302,
headers: {
Expand All @@ -167,7 +169,7 @@ export async function GET(request: Request): Promise<Response> {

const sessionToken = generateSessionToken();
const session = await createSession(sessionToken, user.id);
setSessionTokenCookie(sessionToken, session.expiresAt);
await setSessionTokenCookie(sessionToken, session.expiresAt);
return new Response(null, {
status: 302,
headers: {
Expand Down Expand Up @@ -221,7 +223,7 @@ async function logout(): Promise<ActionResult> {
}

await invalidateSession(session.id);
deleteSessionTokenCookie();
await deleteSessionTokenCookie();
return redirect("/login");
}

Expand Down
16 changes: 9 additions & 7 deletions pages/tutorials/google-oauth/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,15 @@ export async function GET(): Promise<Response> {
const codeVerifier = generateCodeVerifier();
const url = google.createAuthorizationURL(state, codeVerifier, ["openid", "profile"]);

cookies().set("google_oauth_state", state, {
const cookieStore = await cookies();
cookieStore.set("google_oauth_state", state, {
path: "/",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
maxAge: 60 * 10, // 10 minutes
sameSite: "lax"
});
cookies().set("google_code_verifier", codeVerifier, {
cookieStore.set("google_code_verifier", codeVerifier, {
path: "/",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
Expand Down Expand Up @@ -123,8 +124,9 @@ export async function GET(request: Request): Promise<Response> {
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const storedState = cookies().get("google_oauth_state")?.value ?? null;
const codeVerifier = cookies().get("google_code_verifier")?.value ?? null;
const cookieStore = await cookies();
const storedState = cookieStore.get("google_oauth_state")?.value ?? null;
const codeVerifier = cookieStore.get("google_code_verifier")?.value ?? null;
if (code === null || state === null || storedState === null || codeVerifier === null) {
return new Response(null, {
status: 400
Expand Down Expand Up @@ -155,7 +157,7 @@ export async function GET(request: Request): Promise<Response> {
if (existingUser !== null) {
const sessionToken = generateSessionToken();
const session = await createSession(sessionToken, existingUser.id);
setSessionTokenCookie(sessionToken, session.expiresAt);
await setSessionTokenCookie(sessionToken, session.expiresAt);
return new Response(null, {
status: 302,
headers: {
Expand All @@ -169,7 +171,7 @@ export async function GET(request: Request): Promise<Response> {

const sessionToken = generateSessionToken();
const session = await createSession(sessionToken, user.id);
setSessionTokenCookie(sessionToken, session.expiresAt);
await setSessionTokenCookie(sessionToken, session.expiresAt);
return new Response(null, {
status: 302,
headers: {
Expand Down Expand Up @@ -223,7 +225,7 @@ async function logout(): Promise<ActionResult> {
}

await invalidateSession(session.id);
deleteSessionTokenCookie();
await deleteSessionTokenCookie();
return redirect("/login");
}

Expand Down
1 change: 1 addition & 0 deletions pages/tutorials/google-oauth/sveltekit.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Create an API route in `routes/login/google/callback/+server.ts` to handle the c
// routes/login/google/callback/+server.ts
import { generateSessionToken, createSession, setSessionTokenCookie } from "$lib/server/session";
import { google } from "$lib/server/oauth";
import { decodeIdToken } from "arctic";

import type { RequestEvent } from "@sveltejs/kit";
import type { OAuth2Tokens } from "arctic";
Expand Down

0 comments on commit 6428975

Please sign in to comment.