Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
web:framework:nextjs:nextauth [2025/03/18 13:57] – créée jcheron | web:framework:nextjs:nextauth [2025/08/12 02:35] (Version actuelle) – modification externe 127.0.0.1 | ||
---|---|---|---|
Ligne 7: | Ligne 7: | ||
npm install next-auth@beta @types/ | npm install next-auth@beta @types/ | ||
</ | </ | ||
+ | |||
+ | ===== Configuration ===== | ||
+ | |||
+ | <sxh typescript; | ||
+ | import NextAuth from " | ||
+ | import CredentialsProvider from " | ||
+ | import HttpService from " | ||
+ | import API_URLS from " | ||
+ | import { decodeJwt } from " | ||
+ | |||
+ | interface AuthToken { | ||
+ | accessToken: | ||
+ | refreshToken: | ||
+ | user: any; | ||
+ | } | ||
+ | |||
+ | async function refreshAccessToken(token: | ||
+ | try { | ||
+ | const refreshedToken = await HttpService.post(API_URLS.refreshToken, | ||
+ | refreshToken: | ||
+ | }); | ||
+ | |||
+ | if (!refreshedToken || !refreshedToken.accessToken) { | ||
+ | throw new Error(" | ||
+ | } | ||
+ | |||
+ | return { | ||
+ | ...token, | ||
+ | accessToken: | ||
+ | accessTokenExpires: | ||
+ | refreshToken: | ||
+ | }; | ||
+ | } catch (error) { | ||
+ | console.error(" | ||
+ | return { ...token, error: " | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // @ts-ignore | ||
+ | export const authConfig = { | ||
+ | pages: { | ||
+ | signIn: '/ | ||
+ | signOut: "/ | ||
+ | }, | ||
+ | providers: [ | ||
+ | CredentialsProvider({ | ||
+ | id: " | ||
+ | name: " | ||
+ | credentials: | ||
+ | username: { label: " | ||
+ | password: { label: " | ||
+ | }, | ||
+ | async authorize(credentials) { | ||
+ | const resp = await HttpService.post(API_URLS.authLogin, | ||
+ | username: credentials.username, | ||
+ | password: credentials.password, | ||
+ | }); | ||
+ | |||
+ | if (resp.ok) { | ||
+ | throw new Error(" | ||
+ | } | ||
+ | const token=resp.data; | ||
+ | const user = decodeJwt(token.accessToken); | ||
+ | |||
+ | return { | ||
+ | id: user.sub, | ||
+ | name: user.name, | ||
+ | email: user.email, | ||
+ | role: user.role, | ||
+ | accessToken: | ||
+ | // | ||
+ | accessTokenExpires: | ||
+ | }; | ||
+ | }, | ||
+ | }), | ||
+ | ], | ||
+ | callbacks: { | ||
+ | async jwt({ token, user }) { | ||
+ | if (user) { | ||
+ | return { | ||
+ | accessToken: | ||
+ | // | ||
+ | accessTokenExpires: | ||
+ | user: { | ||
+ | id: user.id, | ||
+ | name: user.name, | ||
+ | email: user.email, | ||
+ | role: user.role | ||
+ | }, | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | if (Date.now() < token.accessTokenExpires) { | ||
+ | return token; | ||
+ | } | ||
+ | |||
+ | return refreshAccessToken(token); | ||
+ | }, | ||
+ | async session({ session, token }) { | ||
+ | console.log(" | ||
+ | console.log(" | ||
+ | return { | ||
+ | ...session, | ||
+ | user: { | ||
+ | ...session.user, | ||
+ | id: token.user.id, | ||
+ | name: token.user.name, | ||
+ | email: token.user.email, | ||
+ | accessToken: | ||
+ | // | ||
+ | }, | ||
+ | }; | ||
+ | }, | ||
+ | }, | ||
+ | session: { | ||
+ | strategy: ' | ||
+ | }, | ||
+ | secret: process.env.NEXTAUTH_SECRET as string, | ||
+ | } satisfies NextAuthConfig; | ||
+ | |||
+ | // | ||
+ | export const {handlers, auth, signIn, signOut} = NextAuth(authConfig); | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Route api ===== | ||
+ | Toutes les requêtes NextAuth passeront par cette route : '' | ||
+ | |||
+ | <sxh typescript> | ||
+ | import {handlers} from " | ||
+ | export const {GET, POST} = handlers; | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Lib ===== | ||
+ | Fichier utilitaire pour simplifier connexion et déconnexion dans '' | ||
+ | |||
+ | <sxh typescript> | ||
+ | 'use server'; | ||
+ | import {signIn, signOut} from " | ||
+ | |||
+ | |||
+ | interface LoginFormValues { | ||
+ | username: string; | ||
+ | password: string; | ||
+ | rememberMe?: | ||
+ | }; | ||
+ | export const submitLogin = async (formData: LoginFormValues): | ||
+ | await signIn(' | ||
+ | }; | ||
+ | |||
+ | export const submitLogout = async () => { | ||
+ | await signOut({redirect: | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | ===== LoginForm ===== | ||
+ | Exemple de composant pour le login : | ||
+ | <sxh typescript> | ||
+ | 'use client'; | ||
+ | import {Button, Checkbox, Form, Input} from " | ||
+ | import {submitLogin} from " | ||
+ | |||
+ | |||
+ | export default function SignInComponent(){ | ||
+ | const onFinish = async (values: any) => { | ||
+ | await submitLogin(values); | ||
+ | }; | ||
+ | |||
+ | const onFinishFailed = (errorInfo: any) => { | ||
+ | console.log(' | ||
+ | }; | ||
+ | return | ||
+ | < | ||
+ | < | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | > | ||
+ | < | ||
+ | | ||
+ | | ||
+ | | ||
+ | > | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | | ||
+ | | ||
+ | | ||
+ | > | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Configuration ===== | ||
+ | |||
+ | Dans le fichier '' | ||
+ | |||
+ | <sxh env> | ||
+ | NEXTAUTH_URL=http:// | ||
+ | </ | ||
+ | |||
+ | |||
+ | Génération du secret pour encodage/ | ||
+ | |||
+ | <sxh bash> | ||
+ | npx auth secret | ||
+ | </ | ||
+ | |||
+ | Le **secret** est généré et inséré dans le fichier '' | ||
+ | ===== Usage ===== | ||
+ | Accès à la session nextAuth : | ||
+ | |||
+ | ==== Côté serveur ==== | ||
+ | |||
+ | <sxh ts; | ||
+ | import {auth} from " | ||
+ | |||
+ | const session= await auth(); | ||
+ | console.log(session.user); | ||
+ | </ | ||
+ | |||
+ | ==== Côté client ==== | ||
+ | |||
+ | <sxh ts; | ||
+ | 'use client'; | ||
+ | import {useSession} from " | ||
+ | |||
+ | const userData=useSession(); | ||
+ | console.log(userData.data? | ||
+ | </ | ||
+ | |||