File tree Expand file tree Collapse file tree 15 files changed +505
-1
lines changed
packages/next-auth-sample Expand file tree Collapse file tree 15 files changed +505
-1
lines changed Original file line number Diff line number Diff line change 1+ {
2+ "extends" : " next/core-web-vitals"
3+ }
Original file line number Diff line number Diff line change 1+ .vercel
Original file line number Diff line number Diff line change 1+ # Auth.js (next-auth) Sample
2+
3+ This is a sample project for integrating Auth.js (next-auth) with Logto.
4+
5+ ## Configuration
6+
7+ You can configure the sample project by setting the following environment variables:
8+
9+ | key | description | example |
10+ | ----------------- | ------------------------------------------- | ------------------------------------ |
11+ | AUTH_SECRET | The secret for cookie encryption | ` my-cookie-secret ` |
12+ | AUTH_LOGTO_ISSUER | The issuer of your Logto server | ` https://[tenant-id].logto.app/oidc ` |
13+ | AUTH_LOGTO_ID | The client ID of your Logto application | ` my-app ` |
14+ | AUTH_LOGTO_SECRET | The client secret of your Logto application | ` my-secret ` |
15+
16+ ## Run the sample
17+
18+ ``` bash
19+ pnpm dev
20+ ```
21+
22+ ## Resources
23+
24+ - [ Logto Auth.js Documentation] ( https://docs.logto.io/quick-starts/next-auth )
Original file line number Diff line number Diff line change 1+ import { handlers } from '../../../../auth' ;
2+
3+ export const { GET , POST } = handlers ;
Original file line number Diff line number Diff line change 1+ import { signIn } from '../../auth' ;
2+
3+ export default function SignIn ( ) {
4+ return (
5+ < form
6+ action = { async ( ) => {
7+ 'use server' ;
8+ await signIn ( 'logto' ) ;
9+ } }
10+ >
11+ < button type = "submit" > Sign In</ button >
12+ </ form >
13+ ) ;
14+ }
Original file line number Diff line number Diff line change 1+ import { signOut } from '../../auth' ;
2+ import { redirect } from 'next/navigation' ;
3+
4+ const generateSignOutUri = ( postLogoutRedirectUri : string ) => {
5+ if ( ! process . env . AUTH_LOGTO_ID ) {
6+ throw new Error ( 'AUTH_LOGTO_ID is not set' ) ;
7+ }
8+
9+ const urlSearchParameters = new URLSearchParams ( { 'client_id' : process . env . AUTH_LOGTO_ID , 'post_logout_redirect_uri' : postLogoutRedirectUri } ) ;
10+
11+ return `${ process . env . AUTH_LOGTO_ISSUER } /session/end?${ urlSearchParameters . toString ( ) } ` ;
12+ } ;
13+
14+ export default function SignOut ( ) {
15+ return (
16+ < form
17+ action = { async ( ) => {
18+ 'use server' ;
19+ // Visit post-sign-out URL to implement federated sign-out,
20+ // @see https://authjs.dev/reference/core/adapters#federated-logout
21+ const { redirect : signOutRedirect } = await signOut ( { redirect : false } ) ;
22+ redirect ( generateSignOutUri ( signOutRedirect ) ) ;
23+ // If you don't need to implement federated sign-out, you can use the following code instead:
24+ // await signOut();
25+ } }
26+ >
27+ < button type = "submit" >
28+ Sign Out
29+ </ button >
30+ </ form >
31+ ) ;
32+ }
Original file line number Diff line number Diff line change 1+ import { auth } from '../../auth' ;
2+
3+ // This is a sample page to fetch user info from Logto
4+ export default async function FetchUserInfo ( ) {
5+ const session = await auth ( ) ;
6+ const response = await fetch ( `${ process . env . AUTH_LOGTO_ISSUER } /me` , {
7+ headers : {
8+ // @ts -expect-error
9+ Authorization : `Bearer ${ session ?. accessToken } ` ,
10+ } ,
11+ } ) ;
12+ const user = await response . json ( ) ;
13+
14+ return < div > { JSON . stringify ( user ) } </ div > ;
15+ }
Original file line number Diff line number Diff line change 1+ export const metadata = {
2+ title : 'Next.js' ,
3+ description : 'Generated by Next.js' ,
4+ }
5+
6+ export default function RootLayout ( {
7+ children,
8+ } : {
9+ children : React . ReactNode
10+ } ) {
11+ return (
12+ < html lang = "en" >
13+ < body > { children } </ body >
14+ </ html >
15+ )
16+ }
Original file line number Diff line number Diff line change 1+ import { auth } from '../auth' ;
2+ import SignIn from './components/sign-in' ;
3+ import SignOut from './components/sign-out' ;
4+
5+ export default async function Home ( ) {
6+ const session = await auth ( ) ;
7+
8+ return (
9+ < main >
10+ { session ?. user ? < SignOut /> : < SignIn /> }
11+ { session ?. user && (
12+ < div >
13+ < h2 > Claims:</ h2 >
14+ < table >
15+ < thead >
16+ < tr >
17+ < th > Name</ th >
18+ < th > Value</ th >
19+ </ tr >
20+ </ thead >
21+ < tbody >
22+ { Object . entries ( session . user ) . map ( ( [ key , value ] ) => (
23+ < tr key = { key } >
24+ < td > { key } </ td >
25+ < td > { String ( value ) } </ td >
26+ </ tr >
27+ ) ) }
28+ </ tbody >
29+ </ table >
30+ </ div >
31+ ) }
32+ </ main >
33+ ) ;
34+ }
Original file line number Diff line number Diff line change 1+ import NextAuth , { NextAuthResult } from 'next-auth' ;
2+ import Logto from 'next-auth/providers/logto' ;
3+
4+ const result = NextAuth ( {
5+ providers : [
6+ Logto ( {
7+ authorization : {
8+ params : {
9+ // If you don't need to customize the scope, you can use the default scope by leaving the config empty.
10+ scope : 'openid offline_access profile email' ,
11+ } ,
12+ } ,
13+ } ) ,
14+ ] ,
15+ callbacks : {
16+ async jwt ( { token, account } ) {
17+ if ( account ) {
18+ token . accessToken = account . access_token ;
19+ }
20+ return token ;
21+ } ,
22+ async session ( { session, token } ) {
23+ // Inject the access token into the session object
24+ // @ts -expect-error
25+ session . accessToken = token . accessToken ;
26+ return session ;
27+ } ,
28+ } ,
29+ } ) ;
30+
31+ // A workaround to make the types work
32+ // @see https://github.com/nextauthjs/next-auth/discussions/9950
33+ export const handlers : NextAuthResult [ 'handlers' ] = result . handlers ;
34+ export const auth : NextAuthResult [ 'auth' ] = result . auth ;
35+ export const signIn : NextAuthResult [ 'signIn' ] = result . signIn ;
36+ export const signOut : NextAuthResult [ 'signOut' ] = result . signOut ;
You can’t perform that action at this time.
0 commit comments