Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add next.js external storage #951

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/quick-starts/framework/next-app-router/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sidebar_custom_props:

import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';
import ExternalStorage from '../next/_external-storage.mdx';
import Installation from '../next/_installation.mdx';

import GetUserInformation from './_get-user-information.mdx';
Expand Down Expand Up @@ -101,6 +102,10 @@ HTTP does not allow setting cookies after streaming starts, `getOrganizationToke

:::

## Use external session storage \{#use-external-session-storage}

<ExternalStorage />

## Further readings \{#further-readings}

<FurtherReadings />
5 changes: 5 additions & 0 deletions docs/quick-starts/framework/next/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ framework: Next.js
import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';

import ExternalStorage from './_external-storage.mdx';
import GetUserInformation from './_get-user-information.mdx';
import GuideTip from './_guide-tip.mdx';
import Installation from './_installation.mdx';
Expand Down Expand Up @@ -96,6 +97,10 @@ export const config = {
Check the [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) to see full example.
:::

## Use external session storage \{#use-external-session-storage}
charIeszhao marked this conversation as resolved.
Show resolved Hide resolved

<ExternalStorage />

## Further readings \{#further-readings}

<FurtherReadings />
39 changes: 39 additions & 0 deletions docs/quick-starts/framework/next/_external-storage.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
The SDK uses cookies to store encrypted session data by default. This approach is secure, requires no additional infrastructure, and works especially well in serverless environments like Vercel.

However, there are times when you might need to store session data externally. For instance, when your session data grows too large for cookies, especially when you need to maintain multiple active organization sessions simultaneously. In these cases, you can implement external session storage using the `sessionWrapper` option:

```ts
import { MemorySessionWrapper } from './storage';

export const config = {
// ...
sessionWrapper: new MemorySessionWrapper(),
};
```

```ts
import { randomUUID } from 'node:crypto';

import { type SessionWrapper, type SessionData } from '@logto/next';

export class MemorySessionWrapper implements SessionWrapper {
private readonly storage = new Map<string, unknown>();

async wrap(data: unknown, _key: string): Promise<string> {
const sessionId = randomUUID();
this.storage.set(sessionId, data);
return sessionId;
}

async unwrap(value: string, _key: string): Promise<SessionData> {
if (!value) {
return {};
}

const data = this.storage.get(value);
return data ?? {};
}
}
```

The above implementation uses a simple in-memory storage. In a production environment, you might want to use a more persistent storage solution, such as Redis or a database.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sidebar_custom_props:

import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';
import ExternalStorage from '../next/_external-storage.mdx';
import Installation from '../next/_installation.mdx';

import GetUserInformation from './_get-user-information.mdx';
Expand Down Expand Up @@ -101,6 +102,10 @@ HTTP erlaubt es nicht, Cookies zu setzen, nachdem das Streaming begonnen hat. `g

:::

## Externen Sitzungspeicher verwenden \{#use-external-session-storage}

<ExternalStorage />

## Weiterführende Lektüre \{#further-readings}

<FurtherReadings />
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ framework: Next.js
import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';

import ExternalStorage from './_external-storage.mdx';
import GetUserInformation from './_get-user-information.mdx';
import GuideTip from './_guide-tip.mdx';
import Installation from './_installation.mdx';
Expand Down Expand Up @@ -96,6 +97,10 @@ export const config = {
Sieh dir das [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) an, um ein vollständiges Beispiel zu sehen.
:::

## Externen Sitzungs-Speicher verwenden \{#use-external-session-storage}

<ExternalStorage />

## Weiterführende Lektüre \{#further-readings}

<FurtherReadings />
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Das SDK verwendet standardmäßig Cookies, um verschlüsselte Sitzungsdaten zu speichern. Dieser Ansatz ist sicher, erfordert keine zusätzliche Infrastruktur und funktioniert besonders gut in serverlosen Umgebungen wie Vercel.

Es gibt jedoch Zeiten, in denen du Sitzungsdaten extern speichern musst. Zum Beispiel, wenn deine Sitzungsdaten zu groß für Cookies werden, insbesondere wenn du mehrere aktive Organisation-Sitzungen gleichzeitig aufrechterhalten musst. In diesen Fällen kannst du eine externe Sitzungspeicherung mit der Option `sessionWrapper` implementieren:

```ts
import { MemorySessionWrapper } from './storage';

export const config = {
// ...
sessionWrapper: new MemorySessionWrapper(),
};
```

```ts
import { randomUUID } from 'node:crypto';

import { type SessionWrapper, type SessionData } from '@logto/next';

export class MemorySessionWrapper implements SessionWrapper {
private readonly storage = new Map<string, unknown>();

async wrap(data: unknown, _key: string): Promise<string> {
const sessionId = randomUUID();
this.storage.set(sessionId, data);
return sessionId;
}

async unwrap(value: string, _key: string): Promise<SessionData> {
if (!value) {
return {};
}

const data = this.storage.get(value);
return data ?? {};
}
}
```

Die obige Implementierung verwendet einen einfachen In-Memory-Speicher. In einer Produktionsumgebung möchtest du möglicherweise eine beständigere Speicherlösung verwenden, wie Redis oder eine Datenbank.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sidebar_custom_props:

import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';
import ExternalStorage from '../next/_external-storage.mdx';
import Installation from '../next/_installation.mdx';

import GetUserInformation from './_get-user-information.mdx';
Expand Down Expand Up @@ -43,7 +44,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t

<ApiResourcesDescription />

### Configurar cliente Logto \{#configure-logto-client}
### Configurar el cliente de Logto \{#configure-logto-client}

<ConfigApiResources />

Expand All @@ -70,7 +71,7 @@ export default async function Home() {

:::tip

HTTP no permite establecer cookies después de que comienza la transmisión, `getAccessTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se conservará en la sesión. Se recomienda usar la función `getAccessToken` en el lado del cliente o en los manejadores de rutas.
HTTP no permite establecer cookies después de que comienza la transmisión, `getAccessTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se persistirá en la sesión. Se recomienda usar la función `getAccessToken` en el lado del cliente o en los manejadores de rutas.

:::

Expand All @@ -97,10 +98,14 @@ export default async function Home() {

:::tip

HTTP no permite establecer cookies después de que comienza la transmisión, `getOrganizationTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se conservará en la sesión. Se recomienda usar la función `getOrganizationToken` en el lado del cliente o en los manejadores de rutas.
HTTP no permite establecer cookies después de que comienza la transmisión, `getOrganizationTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se persistirá en la sesión. Se recomienda usar la función `getOrganizationToken` en el lado del cliente o en los manejadores de rutas.

:::

## Usar almacenamiento de sesión externo \{#use-external-session-storage}

<ExternalStorage />

## Lecturas adicionales \{#further-readings}

<FurtherReadings />
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ framework: Next.js
import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';

import ExternalStorage from './_external-storage.mdx';
import GetUserInformation from './_get-user-information.mdx';
import GuideTip from './_guide-tip.mdx';
import Installation from './_installation.mdx';
Expand Down Expand Up @@ -78,7 +79,7 @@ export const logtoClient = new LogtoClient({
});
```

Luego, establece el runtime en `experimental-edge` o `edge` en la ruta de la API.
Luego establece el runtime en `experimental-edge` o `edge` en la ruta de la API.

```ts title="pages/api/logto/sign-in.ts"
import { logtoClient } from '../../../../libraries/logto';
Expand All @@ -96,6 +97,10 @@ export const config = {
Consulta el [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) para ver un ejemplo completo.
:::

## Usar almacenamiento de sesión externo \{#use-external-session-storage}

<ExternalStorage />

## Lecturas adicionales \{#further-readings}

<FurtherReadings />
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
El SDK utiliza cookies para almacenar datos de sesión cifrados por defecto. Este enfoque es seguro, no requiere infraestructura adicional y funciona especialmente bien en entornos sin servidor como Vercel.

Sin embargo, hay ocasiones en las que podrías necesitar almacenar los datos de sesión externamente. Por ejemplo, cuando tus datos de sesión crecen demasiado para las cookies, especialmente cuando necesitas mantener múltiples sesiones activas de organización simultáneamente. En estos casos, puedes implementar un almacenamiento de sesión externo utilizando la opción `sessionWrapper`:

```ts
import { MemorySessionWrapper } from './storage';

export const config = {
// ...
sessionWrapper: new MemorySessionWrapper(),
};
```

```ts
import { randomUUID } from 'node:crypto';

import { type SessionWrapper, type SessionData } from '@logto/next';

export class MemorySessionWrapper implements SessionWrapper {
private readonly storage = new Map<string, unknown>();

async wrap(data: unknown, _key: string): Promise<string> {
const sessionId = randomUUID();
this.storage.set(sessionId, data);
return sessionId;
}

async unwrap(value: string, _key: string): Promise<SessionData> {
if (!value) {
return {};
}

const data = this.storage.get(value);
return data ?? {};
}
}
```

La implementación anterior utiliza un almacenamiento en memoria simple. En un entorno de producción, podrías querer usar una solución de almacenamiento más persistente, como Redis o una base de datos.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ slug: /quick-starts/next-app-router
sidebar_label: Next.js (App Router)
sidebar_custom_props:
logoFilename: 'next.svg'
darkLogoFilename: 'next-dark.svg'
description: Next.js App Router est un nouveau paradigme pour construire des applications en utilisant les dernières fonctionnalités de React.
---

import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';
import ExternalStorage from '../next/_external-storage.mdx';
import Installation from '../next/_installation.mdx';

import GetUserInformation from './_get-user-information.mdx';
Expand All @@ -34,7 +36,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t

<Integration />

## Récupérer les informations de l'utilisateur \{#fetch-user-information}
## Récupérer les informations utilisateur \{#fetch-user-information}

<GetUserInformation />

Expand All @@ -46,7 +48,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t

<ConfigApiResources />

### Récupérer un jeton d’accès pour la ressource API \{#fetch-access-token-for-the-api-resource}
### Récupérer le jeton d’accès pour la ressource API \{#fetch-access-token-for-the-api-resource}

<FetchAccessTokenForApiResources />

Expand All @@ -61,7 +63,7 @@ export default async function Home() {

return (
<main>
<p>Access token: {accessToken}</p>
<p>Jeton d’accès : {accessToken}</p>
</main>
);
}
Expand All @@ -73,7 +75,7 @@ HTTP ne permet pas de définir des cookies après le début du streaming, `getAc

:::

### Récupérer des jetons d’organisation \{#fetch-organization-tokens}
### Récupérer les jetons d’organisation \{#fetch-organization-tokens}

<FetchOrganizationTokenForUser />

Expand All @@ -88,7 +90,7 @@ export default async function Home() {

return (
<main>
<p>Organization token: {token}</p>
<p>Jeton d’organisation : {token}</p>
</main>
);
}
Expand All @@ -100,6 +102,10 @@ HTTP ne permet pas de définir des cookies après le début du streaming, `getOr

:::

## Utiliser un stockage de session externe \{#use-external-session-storage}

<ExternalStorage />

## Lectures complémentaires \{#further-readings}

<FurtherReadings />
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ framework: Next.js
import ApiResourcesDescription from '../../fragments/_api-resources-description.md';
import FurtherReadings from '../../fragments/_further-readings.md';

import ExternalStorage from './_external-storage.mdx';
import GetUserInformation from './_get-user-information.mdx';
import GuideTip from './_guide-tip.mdx';
import Installation from './_installation.mdx';
Expand Down Expand Up @@ -70,8 +71,8 @@ import LogtoClient from '@logto/next/edge';
export const logtoClient = new LogtoClient({
appId: '<your-application-id>',
appSecret: '<your-app-secret-copied-from-console>',
endpoint: '<your-logto-endpoint>', // Par exemple http://localhost:3001
baseUrl: '<your-nextjs-app-base-url>', // Par exemple http://localhost:3000
endpoint: '<your-logto-endpoint>', // Par exemple, http://localhost:3001
baseUrl: '<your-nextjs-app-base-url>', // Par exemple, http://localhost:3000
cookieSecret: 'complex_password_at_least_32_characters_long',
cookieSecure: process.env.NODE_ENV === 'production',
resources: ['<your-api-resource>'],
Expand All @@ -96,6 +97,10 @@ export const config = {
Consultez le [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) pour voir un exemple complet.
:::

## Utiliser un stockage de session externe \{#use-external-session-storage}

<ExternalStorage />

## Lectures complémentaires \{#further-readings}

<FurtherReadings />
Loading
Loading