Auth.js: fornecedor OIDC próprio com exemplo de Next.js

Precisa de três valores da consola para programadores: o ID de cliente, o segredo de cliente (apenas aplicações de servidor web) e o URI de redirecionamento que registou. O resto está no documento de descoberta em https://identity.dazr.eu/.well-known/openid-configuration.

Auth.js / NextAuth

O Auth.js (NextAuth.js v5) aceita um objeto de fornecedor OpenID Connect personalizado. Registe uma aplicação de servidor web, defina AUTH_SECRET, AUTH_DAZR_ID e AUTH_DAZR_SECRET, e use este URL de callback como URI de redirecionamento: https://app.example.eu/api/auth/callback/dazr.

// auth.ts
import NextAuth from "next-auth"

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    {
      id: "dazr",
      name: "Dazr Identity",
      type: "oidc",
      issuer: "https://identity.dazr.eu",
      clientId: process.env.AUTH_DAZR_ID,
      clientSecret: process.env.AUTH_DAZR_SECRET,
      authorization: { params: { scope: "openid profile email" } },
      checks: ["pkce", "state", "nonce"],
      client: { id_token_signed_response_alg: "ES256" },
    },
  ],
})

O NextAuth.js v4 usa a mesma ideia com type: "oauth" e o URL de descoberta:

// pages/api/auth/[...nextauth].ts (NextAuth.js v4), in providers: [ ... ]
{
  id: "dazr",
  name: "Dazr Identity",
  type: "oauth",
  wellKnown: "https://identity.dazr.eu/.well-known/openid-configuration",
  clientId: process.env.DAZR_CLIENT_ID,
  clientSecret: process.env.DAZR_CLIENT_SECRET,
  authorization: { params: { scope: "openid profile email" } },
  idToken: true,
  checks: ["pkce", "state"],
  client: { id_token_signed_response_alg: "ES256" },
  profile(profile) {
    return { id: profile.sub, name: profile.name ?? null, email: profile.email }
  },
}

Next.js App Router

Com o ficheiro auth.ts acima, adicione o route handler e um botão de início de sessão que executa uma server action.

// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers

// app/page.tsx
import { auth, signIn, signOut } from "@/auth"

export default async function Page() {
  const session = await auth()
  if (session?.user) {
    return (
      <form action={async () => { "use server"; await signOut() }}>
        <p>Signed in as {session.user.email}</p>
        <button type="submit">Sign out</button>
      </form>
    )
  }
  return (
    <form action={async () => { "use server"; await signIn("dazr") }}>
      <button type="submit" className="dazr-signin">Sign in with Dazr Identity</button>
    </form>
  )
}

Formate o botão como mostrado em O botão. Nos callbacks, o sub do Dazr é account.providerAccountId.

Mais para programadores