مواد پر جائیں
دستاویزات · Next.js

فوری آغاز: Next.js

App Router والی Next.js ایپ میں سائن ان شامل کریں۔ @usher/nextjs SDK آ رہا ہے؛ اس کے آنے تک، یہ گائیڈ معیاری OpenID Connect فلو استعمال کرتی ہے، جو بالکل وہی ہے جو SDK آپ کے لیے کرے گا۔

شروع کرنے سے پہلے

  • App Router استعمال کرنے والی Next.js 15 یا 16 ایپ۔
  • ایک Usher انوائرنمنٹ۔ Usher Console میں اپنا پروجیکٹ کھولیں، کوئی انوائرنمنٹ چنیں، اور اس کا جاری کنندہ نوٹ کر لیں۔

اپنی ایپ رجسٹر کریں

Console میں ایپلیکیشنز پر جائیں اور ایک ویب ایپلیکیشن بنائیں۔ یہ ری ڈائریکٹ URI بالکل اسی طرح شامل کریں:

http://localhost:3000/auth/callback

کلائنٹ ID اور کلائنٹ سیکرٹ کاپی کریں۔ سیکرٹ صرف ایک بار دکھایا جاتا ہے۔

اپنے انوائرنمنٹ ویری ایبلز شامل کریں

.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`

لوگوں کو لابی میں بھیجیں

ایک روٹ ہینڈلر ایک PKCE ویریفائر اور ایک state قدر بناتا ہے، انہیں مختصر مدت کی کوکی میں رکھتا ہے، اور لابی پر ری ڈائریکٹ کرتا ہے۔

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 ویریفائر اور ID ٹوکن کے دستخط کو جانچتا ہے۔

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 کے اینڈ سیشن اینڈ پوائنٹ پر بھیجیں تاکہ لابی بھی اسے بھول جائے۔

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 />
}

اگلے مراحل