Μετάβαση στο περιεχόμενο
Τεκμηρίωση · Next.js

Γρήγορη έναρξη: Next.js

Προσθέστε σύνδεση σε μια εφαρμογή Next.js με το App Router. Το SDK @usher/nextjs έρχεται· μέχρι να κυκλοφορήσει, αυτός ο οδηγός χρησιμοποιεί την τυπική ροή OpenID Connect, που είναι ακριβώς ό,τι θα κάνει το SDK για εσάς.

Πριν ξεκινήσετε

  • Μια εφαρμογή Next.js 15 ή 16 που χρησιμοποιεί το App Router.
  • Ένα περιβάλλον Usher. Στο Usher Console, ανοίξτε το έργο σας, επιλέξτε ένα περιβάλλον και σημειώστε τον εκδότη του.

Καταχωρίστε την εφαρμογή σας

Στο Console, μεταβείτε στις Εφαρμογές και δημιουργήστε μια εφαρμογή ιστού. Προσθέστε ακριβώς αυτό το URI ανακατεύθυνσης:

http://localhost:3000/auth/callback

Αντιγράψτε το αναγνωριστικό πελάτη και το μυστικό πελάτη. Το μυστικό εμφανίζεται μία φορά.

Προσθέστε τις μεταβλητές περιβάλλοντος

.env.local
USHER_ISSUER=https://acme.usherid.com
USHER_CLIENT_ID=your_client_id
USHER_CLIENT_SECRET=your_client_secret
APP_URL=http://localhost:3000

Εγκαταστήστε έναν πελάτη OpenID Connect

Λειτουργεί οποιοσδήποτε πιστοποιημένος πελάτης. Αυτός ο οδηγός χρησιμοποιεί το openid-client, που χειρίζεται την ανακάλυψη, το PKCE και την επικύρωση διακριτικών.

Τερματικό
pnpm add openid-client

Ανακαλύψτε τον εκδότη σας

Η ανακάλυψη διαβάζει μία φορά τα τελικά σημεία και τα κλειδιά του εκδότη, οπότε τίποτα δεν είναι γραμμένο σταθερά στον κώδικα.

lib/usher.ts
import * as client from 'openid-client'

let config: Promise<client.Configuration> | undefined

export function usher() {
  config ??= client.discovery(
    new URL(process.env.USHER_ISSUER!),
    process.env.USHER_CLIENT_ID!,
    process.env.USHER_CLIENT_SECRET!,
  )
  return config
}

export const redirectUri = `${process.env.APP_URL}/auth/callback`

Στείλτε τους χρήστες στο Lobby

Ένας χειριστής διαδρομής δημιουργεί έναν επαληθευτή PKCE και μια τιμή state, τα κρατά σε ένα cookie σύντομης διάρκειας και ανακατευθύνει στο Lobby.

app/auth/sign-in/route.ts
import * as client from 'openid-client'
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'
import { redirectUri, usher } from '@/lib/usher'

export async function GET() {
  const config = await usher()
  const codeVerifier = client.randomPKCECodeVerifier()
  const state = client.randomState()

  const jar = await cookies()
  jar.set('usher_flow', JSON.stringify({ codeVerifier, state }), {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    path: '/auth',
    maxAge: 600,
  })

  const url = client.buildAuthorizationUrl(config, {
    redirect_uri: redirectUri,
    scope: 'openid profile email offline_access',
    code_challenge: await client.calculatePKCECodeChallenge(codeVerifier),
    code_challenge_method: 'S256',
    state,
  })
  redirect(url.href)
}

Χειριστείτε την επιστροφή

Το Usher στέλνει τον χρήστη πίσω με έναν κωδικό. Ανταλλάξτε τον με διακριτικά· το openid-client ελέγχει για εσάς το state, τον επαληθευτή PKCE και την υπογραφή του διακριτικού αναγνωριστικού.

app/auth/callback/route.ts
import * as client from 'openid-client'
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'
import { usher } from '@/lib/usher'

export async function GET(request: Request) {
  const config = await usher()
  const jar = await cookies()
  const flow = JSON.parse(jar.get('usher_flow')?.value ?? '{}')
  jar.delete('usher_flow')

  const tokens = await client.authorizationCodeGrant(config, new URL(request.url), {
    pkceCodeVerifier: flow.codeVerifier,
    expectedState: flow.state,
  })
  const claims = tokens.claims()! // sub, email, name, …

  // start your own session here: store claims.sub, and keep the refresh token server-side
  redirect('/')
}

Αποσύνδεση

Τερματίστε την περίοδο σύνδεσης του χρήστη στην εφαρμογή σας και, στη συνέχεια, στείλτε τον στο τελικό σημείο λήξης περιόδου σύνδεσης του Usher, ώστε να τον ξεχάσει και το Lobby.

app/auth/sign-out/route.ts
import * as client from 'openid-client'
import { redirect } from 'next/navigation'
import { usher } from '@/lib/usher'

export async function GET() {
  const config = await usher()
  // clear your own session first
  const url = client.buildEndSessionUrl(config, {
    post_logout_redirect_uri: process.env.APP_URL!,
  })
  redirect(url.href)
}

Με το SDK

Όταν δημοσιευτεί το @usher/nextjs, η ίδια εφαρμογή θα μοιάζει έτσι. Η παρακάτω προεπισκόπηση μπορεί να αλλάξει πριν από την κυκλοφορία.

app/layout.tsx · app/page.tsx (προεπισκόπηση)
// app/layout.tsx
import { UsherProvider } from '@usher/nextjs'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <UsherProvider>{children}</UsherProvider>
      </body>
    </html>
  )
}

// app/page.tsx
import { SignIn, UserButton, currentUser } from '@usher/nextjs'

export default async function Page() {
  const user = await currentUser()
  return user ? <UserButton /> : <SignIn />
}

Επόμενα βήματα