Skip to Content

SDK Next.js (@auris/nextjs)

@auris/nextjs v0.1.0

@auris/nextjs offre une intégration complète pour les applications Next.js 13+ avec App Router. Il expose trois points d’entrée distincts selon l’environnement d’exécution :

Point d’entréeEnvironnementUsage
@auris/nextjsClient ComponentsRé-exporte tout @auris/react
@auris/nextjs/serverServer Components, Route HandlersgetSession, withAuth, requirePermission, checkPermission, createServerManagementClient, createServerFgaClient
@auris/nextjs/middlewareEdge MiddlewareaurisMiddleware

Installation

npm install @auris/nextjs
pnpm add @auris/nextjs
yarn add @auris/nextjs

Variables d’environnement

Crée un fichier .env.local à la racine de ton projet Next.js :

# Variables publiques (accessibles dans les Client Components) NEXT_PUBLIC_AURIS_DOMAIN=https://auth.votredomaine.com NEXT_PUBLIC_AURIS_CLIENT_ID=app_xxxxx NEXT_PUBLIC_APP_URL=http://localhost:3000 # Côté serveur : utilisées par aurisMiddleware, getSession, withAuth, requirePermission AURIS_DOMAIN=https://auth.votredomaine.com AURIS_CLIENT_ID=app_xxxxx # Variables privées (côté serveur uniquement) AURIS_CLIENT_SECRET=cs_live_xxxxx AURIS_TENANT=my-tenant # Optionnel : active la vérification JWT locale sans appel réseau AURIS_JWKS_URL=https://auth.votredomaine.com/.well-known/jwks.json

Ne préfixe jamais AURIS_CLIENT_SECRET avec NEXT_PUBLIC_. Le secret doit rester côté serveur uniquement.


Configuration (4 Étapes)

Étape 1 — Installer le package et configurer les variables d’environnement

Voir la section précédente.

Étape 2 — Créer le Provider client

// app/providers.tsx 'use client' import { AurisProvider } from '@auris/nextjs' export function Providers({ children }: { children: React.ReactNode }) { return ( <AurisProvider domain={process.env.NEXT_PUBLIC_AURIS_DOMAIN!} clientId={process.env.NEXT_PUBLIC_AURIS_CLIENT_ID!} redirectUri={`${process.env.NEXT_PUBLIC_APP_URL}/auth/callback`} > {children} </AurisProvider> ) }
// app/layout.tsx import { Providers } from './providers' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="fr"> <body> <Providers>{children}</Providers> </body> </html> ) }

Étape 3 — Configurer le Middleware

// middleware.ts (à la racine du projet) import { aurisMiddleware } from '@auris/nextjs/middleware' export default aurisMiddleware({ domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, protectedPaths: ['/dashboard/*', '/settings/*', '/admin/*'], publicPaths: ['/', '/login', '/auth/*'], loginUrl: '/login', }) export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'], }

Étape 4 — Créer les pages de connexion et de callback

// app/login/page.tsx 'use client' import { useAuris } from '@auris/nextjs' export default function LoginPage() { const { loginWithRedirect } = useAuris() return ( <div> <h1>Connexion</h1> <button onClick={() => loginWithRedirect()}> Continuer avec Auris </button> </div> ) }
// app/auth/callback/page.tsx 'use client' import { useEffect } from 'react' import { useAuris } from '@auris/nextjs' import { useRouter } from 'next/navigation' export default function CallbackPage() { const { isAuthenticated, isLoading, error } = useAuris() const router = useRouter() useEffect(() => { // AurisProvider effectue l'échange de code automatiquement au montage if (!isLoading && isAuthenticated) router.push('/dashboard') }, [isLoading, isAuthenticated, router]) if (error) return <div>Échec de la connexion : {error.message}</div> return <div>Finalisation de la connexion...</div> }

AurisProvider détecte les paramètres de requête code et state au montage et effectue lui-même l’échange de tokens — la page de callback n’a qu’à attendre isAuthenticated puis naviguer. Si tu dois déclencher l’échange manuellement (ex. en dehors du provider), utilise useAuris().client.handleRedirectCallback().


Edge Middleware

aurisMiddleware(config)

Protège les routes au niveau du Edge Middleware. Redirige les utilisateurs non authentifiés vers la page de connexion avant même que la page ne commence à se charger.

Options :

OptionTypeDéfautDescription
domainstringrequisURL de base de l’API Auris
clientIdstringrequisID client OAuth
tenantstring'default'Nom du tenant/realm
protectedPathsstring[][]Chemins nécessitant une authentification. Correspondance exacte, ou par préfixe avec un /* final (ex. '/dashboard/*')
publicPathsstring[][]Chemins qui contournent entièrement les vérifications d’auth (mêmes règles de correspondance)
loginUrlstring'/login'Où rediriger les utilisateurs non authentifiés. Le chemin demandé à l’origine est transmis via ?callbackUrl=
callbackPathsstring[]tous les chemins protégésChemins autorisés à recevoir le callback OAuth2 (?code=&state=) sans authentification

Les patterns de chemins ne sont pas des expressions régulières : un pattern correspond soit exactement, soit par préfixe lorsqu’il se termine par /* ('/dashboard/*' correspond à /dashboard et à tout ce qui se trouve en dessous).

// middleware.ts import { aurisMiddleware } from '@auris/nextjs/middleware' export default aurisMiddleware({ domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, protectedPaths: [ '/dashboard/*', '/settings/*', '/admin/*', ], publicPaths: [ '/', '/login', '/admin/login', '/auth/*', '/api/public/*', ], loginUrl: '/login', // N'autoriser le callback OAuth (?code=&state=) que sur ce chemin callbackPaths: ['/auth/callback'], }) export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'], }

Helpers Côté Serveur

Importés depuis @auris/nextjs/server. Ces fonctions s’exécutent uniquement dans les environnements Node.js (Server Components, Route Handlers, Server Actions).

getSession(config)

Lit la session de l’utilisateur courant depuis le cookie accessToken et le valide auprès de l’API Auris (ou localement, sans appel réseau, lorsque jwksUrl est défini dans la config ou via la variable d’environnement AURIS_JWKS_URL).

Signature :

import { getSession } from '@auris/nextjs/server' const session = await getSession({ domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, }) // Promise<AurisSession | null>

Retourne :

interface AurisSession { userId: string email: string username?: string firstName?: string lastName?: string roles: string[] tenant?: string accessToken: string }
// app/dashboard/page.tsx (Server Component) import { getSession } from '@auris/nextjs/server' import { redirect } from 'next/navigation' export default async function DashboardPage() { const session = await getSession({ domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, }) if (!session) { redirect('/login') } return <h1>Bonjour, {session.firstName} !</h1> }

withAuth(handler, config)

Fonction d’ordre supérieur qui enveloppe un Route Handler et injecte la session authentifiée comme req.session. Retourne 401 si l’utilisateur n’est pas authentifié, et 403 si la permission optionnelle de la config n’est pas accordée.

Signature :

import { withAuth } from '@auris/nextjs/server' export const GET = withAuth( async (req: AuthenticatedRequest) => Response, // req.session: AurisSession { domain: string, // requis clientId: string, // requis tenant?: string, jwksUrl?: string, permission?: string | string[], // vérification de permission optionnelle (403 en cas d'échec) } )
// app/api/profile/route.ts import { withAuth } from '@auris/nextjs/server' const aurisConfig = { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, } export const GET = withAuth(async (req) => { return Response.json({ id: req.session.userId, email: req.session.email, firstName: req.session.firstName, }) }, aurisConfig)

requirePermission(permission, config, handler)

Comme withAuth, mais vérifie également que l’utilisateur a le permission spécifié. Retourne 403 si le permission est manquant.

Signature :

import { requirePermission } from '@auris/nextjs/server' export const GET = requirePermission( 'manage:users', // string | string[] { domain: string, clientId: string, tenant?: string }, async (req: AuthenticatedRequest) => Response // req.session: AurisSession )
// app/api/admin/users/route.ts import { requirePermission } from '@auris/nextjs/server' const aurisConfig = { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, } export const GET = requirePermission('manage:users', aurisConfig, async (req) => { const users = await fetchUsers() return Response.json(users) })

checkPermission(permission, config)

Vérifie un permission dans un Server Component. Retourne un boolean — utile pour le rendu conditionnel côté serveur.

Signature :

import { checkPermission } from '@auris/nextjs/server' const allowed = await checkPermission('manage:users', { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, }) // Promise<boolean>
// app/dashboard/page.tsx import { checkPermission } from '@auris/nextjs/server' const aurisConfig = { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, } export default async function DashboardPage() { const canManageUsers = await checkPermission('manage:users', aurisConfig) const canViewReports = await checkPermission('view:reports', aurisConfig) return ( <div> {canManageUsers && <UserManagementPanel />} {canViewReports && <ReportsSection />} </div> ) }

createServerManagementClient(config?)

Crée un client de gestion côté serveur en utilisant la variable d’environnement AURIS_CLIENT_SECRET. Utilise-le dans les Route Handlers et les Server Actions pour les opérations d’administration.

Signature :

import { createServerManagementClient } from '@auris/nextjs/server' const mgmt = createServerManagementClient()
// app/api/admin/users/route.ts import { requirePermission, createServerManagementClient } from '@auris/nextjs/server' const aurisConfig = { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, } export const POST = requirePermission('manage:users', aurisConfig, async (req) => { const mgmt = createServerManagementClient() const body = await req.json() const user = await mgmt.users.create({ email: body.email, firstName: body.firstName, lastName: body.lastName, roles: body.roles ?? [], }) return Response.json(user, { status: 201 }) })

createServerFgaClient()

Crée un client FGA côté serveur avec un token M2M. Utilise-le dans les Server Components et les Route Handlers pour les vérifications d’autorisation fine-grained.

Signature :

createServerFgaClient(): Promise<FgaClient>
// app/api/documents/[id]/route.ts import { withAuth, createServerFgaClient } from '@auris/nextjs/server' export const GET = withAuth(async (req) => { const docId = new URL(req.url).pathname.split('/').at(-1) const fga = await createServerFgaClient() const result = await fga.check({ objectType: 'document', objectId: docId, relation: 'viewer', subjectType: 'user', subjectId: req.session.userId, }) if (!result.allowed) { return Response.json({ error: 'Accès refusé' }, { status: 403 }) } const doc = await getDocument(docId) return Response.json(doc) }, { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, })

Composants Client

Tous les hooks et composants de @auris/react sont ré-exportés depuis @auris/nextjs. Dans les projets Next.js, importe toujours depuis @auris/nextjs, pas directement depuis @auris/react.

// ✅ Correct dans un projet Next.js import { useAuris, useUser, AuthGuard, PermissionGate } from '@auris/nextjs' // ⚠️ Également correct mais non recommandé dans les projets Next.js import { useAuris } from '@auris/react'

Tous les hooks (useAuris, useUser, useAccessToken, usePermissions, useCheckPermission, useOrganization, useFga) et tous les composants (AuthGuard, PermissionGate, LoginButton, LogoutButton) sont disponibles — voir la documentation SDK React pour leurs signatures complètes.


Structure d’Application Complète

Exemple de structure de fichiers pour une application Next.js complète avec Auris :

    • layout.tsx
    • providers.tsx
  • middleware.ts
  • .env.local
// app/dashboard/layout.tsx (Server Component — vérifie la session) import { getSession } from '@auris/nextjs/server' import { redirect } from 'next/navigation' const aurisConfig = { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, } export default async function DashboardLayout({ children, }: { children: React.ReactNode }) { const session = await getSession(aurisConfig) if (!session) { redirect('/login') } return ( <div className="dashboard-layout"> <Sidebar /> <main>{children}</main> </div> ) }
// app/dashboard/page.tsx (Server Component) import { getSession, checkPermission } from '@auris/nextjs/server' const aurisConfig = { domain: process.env.AURIS_DOMAIN!, clientId: process.env.AURIS_CLIENT_ID!, } export default async function DashboardPage() { const session = await getSession(aurisConfig) const [canViewAnalytics, canManageUsers] = await Promise.all([ checkPermission('view:analytics', aurisConfig), checkPermission('manage:users', aurisConfig), ]) return ( <div> <h1>Tableau de bord — {session!.firstName}</h1> {canViewAnalytics && <AnalyticsWidget />} {canManageUsers && <UserManagementWidget />} </div> ) }

Corrélés