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ée | Environnement | Usage |
|---|---|---|
@auris/nextjs | Client Components | Ré-exporte tout @auris/react |
@auris/nextjs/server | Server Components, Route Handlers | getSession, withAuth, requirePermission, checkPermission, createServerManagementClient, createServerFgaClient |
@auris/nextjs/middleware | Edge Middleware | aurisMiddleware |
Installation
npm install @auris/nextjspnpm add @auris/nextjsyarn add @auris/nextjsVariables 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.jsonNe 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 :
| Option | Type | Défaut | Description |
|---|---|---|---|
domain | string | requis | URL de base de l’API Auris |
clientId | string | requis | ID client OAuth |
tenant | string | 'default' | Nom du tenant/realm |
protectedPaths | string[] | [] | Chemins nécessitant une authentification. Correspondance exacte, ou par préfixe avec un /* final (ex. '/dashboard/*') |
publicPaths | string[] | [] | Chemins qui contournent entièrement les vérifications d’auth (mêmes règles de correspondance) |
loginUrl | string | '/login' | Où rediriger les utilisateurs non authentifiés. Le chemin demandé à l’origine est transmis via ?callbackUrl= |
callbackPaths | string[] | tous les chemins protégés | Chemins 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
- SDK React — Hooks et composants React exposés par @auris/nextjs
- SDK JavaScript — SDK de bas niveau
- Guide Connexion Hébergée — Procédure complète du flux PKCE
- Guide RBAC — Contrôle d’accès basé sur les rôles
- Autorisation Fine-Grained — Modèle FGA et gestion des tuples