CI / ci (push) Canceled after 0s
Fixed an issue where the user would be redirected to a localhost address because an auth url was not set in the env.
67 lines
2.8 KiB
TypeScript
67 lines
2.8 KiB
TypeScript
import { PrismaAdapter } from "@auth/prisma-adapter";
|
|
import NextAuth from "next-auth";
|
|
import Credentials from "next-auth/providers/credentials";
|
|
import Google from "next-auth/providers/google";
|
|
import { authConfig } from "@/auth.config";
|
|
import { authorizeCredentials } from "@/lib/auth/authorize-credentials";
|
|
import { prisma } from "@/lib/db/prisma";
|
|
|
|
export { authorizeCredentials } from "@/lib/auth/authorize-credentials";
|
|
|
|
export const { handlers, auth, signIn, signOut } = NextAuth({
|
|
...authConfig,
|
|
// `@auth/prisma-adapter`'s published types still import `PrismaClient`
|
|
// from the legacy `@prisma/client` path; Prisma 7's `prisma-client`
|
|
// generator no longer populates that path (see prisma/schema.prisma).
|
|
// The adapter only calls plain `prisma.<model>.<method>()` at runtime,
|
|
// so this is a type-only mismatch, not a behavioural one — narrowed
|
|
// here instead of silencing it project-wide.
|
|
adapter: PrismaAdapter(prisma as Parameters<typeof PrismaAdapter>[0]),
|
|
providers: [
|
|
Google,
|
|
Credentials({
|
|
credentials: {
|
|
email: { label: "Email", type: "email" },
|
|
code: { label: "Code", type: "text" },
|
|
// Only ever set by the installer's own trusted server-side sign-in
|
|
// call — never rendered on any real form. See
|
|
// src/lib/auth/authorize-credentials.ts's own header for the full
|
|
// finalize/token design.
|
|
finalize: { label: "Finalize", type: "text" },
|
|
token: { label: "Token", type: "text" },
|
|
},
|
|
// Kept in its own module (not inlined here) so it's importable from
|
|
// a plain Vitest test without dragging in this file's NextAuth(...)
|
|
// construction, which needs the Next.js runtime — see
|
|
// authorize-credentials.ts's own header.
|
|
authorize: authorizeCredentials,
|
|
}),
|
|
],
|
|
callbacks: {
|
|
async jwt({ token, user, trigger, session }) {
|
|
if (user?.id) {
|
|
token.id = user.id;
|
|
}
|
|
// Lets a client-side `useSession().update({ email })` call (see
|
|
// change-email.ts's verifyEmailChangeAction, whose caller triggers
|
|
// this right after a successful email change) refresh the JWT's own
|
|
// email claim without forcing a full sign-out/sign-in — otherwise
|
|
// session.user.email would keep showing the old address until the
|
|
// token's next natural refresh. Nothing else in this app reads
|
|
// session.user.email for authorization (every permission/tenant
|
|
// check is keyed on token.id/session.user.id), so this is purely a
|
|
// display-freshness fix.
|
|
if (trigger === "update" && typeof session?.email === "string") {
|
|
token.email = session.email;
|
|
}
|
|
return token;
|
|
},
|
|
async session({ session, token }) {
|
|
if (session.user && typeof token.id === "string") {
|
|
session.user.id = token.id;
|
|
}
|
|
return session;
|
|
},
|
|
},
|
|
});
|