auth.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import NextAuth, { type NextAuthOptions } from "next-auth";
  2. import CredentialsProvider from "next-auth/providers/credentials";
  3. import { bagistoFetch, /*restApiFetch*/} from "@/utils/bagisto";
  4. import { CUSTOMER_LOGIN } from "@/graphql/customer/mutations";
  5. import type {CustomerLoginResponse} from "@/types/customer/type";
  6. import { env } from "@/env";
  7. export const authOptions: NextAuthOptions = {
  8. session: {
  9. strategy: "jwt",
  10. maxAge: 30 * 24 * 60 * 60,
  11. },
  12. providers: [
  13. // https://next-auth.js.org/configuration/providers/credentials
  14. CredentialsProvider({
  15. name: "Credentials",
  16. credentials: {
  17. username: { label: "Email", type: "text" },
  18. password: { label: "Password", type: "password" },
  19. },
  20. authorize: async (credentials): Promise<any> => {
  21. if (!credentials?.username || !credentials?.password) {
  22. throw new Error("Email and password are required.");
  23. }
  24. const input = {
  25. email: credentials.username,
  26. password: credentials.password,
  27. };
  28. const res = await bagistoFetch<{
  29. data: CustomerLoginResponse,
  30. variables: {input:{email:string;password:string;}}
  31. }>({
  32. query: CUSTOMER_LOGIN,
  33. variables: { input },
  34. cache: "no-store",
  35. });
  36. const data = res?.body?.data?.createCustomerLogin?.customerLogin;
  37. /* 使用rest api
  38. const res = await restApiFetch<any>({
  39. api: "/customer/login",
  40. variables: { ...input },
  41. cache: "no-store",
  42. });
  43. const data = res?.body;
  44. */
  45. if (!data || !data.success || !data.token) {
  46. throw new Error(data?.message || "Invalid credentials.");
  47. }
  48. return {
  49. id: data.id, // required by NextAuth
  50. email: credentials.username,
  51. name: credentials.username, // Using email as name since firstName/lastName are missing in response
  52. apiToken: data.apiToken,
  53. accessToken: data.token, // Sanctum token
  54. role: "customer",
  55. };
  56. },
  57. }),
  58. ],
  59. //https://next-auth.js.org/configuration/callbacks
  60. // nextAuth.js 的jwt token 和session 存在自动续签问题
  61. // 但是accessToken没有刷新机制
  62. callbacks: {
  63. async jwt({ token, user }) {
  64. // 登录时 user是有值的,登录过后,获取用户信息user是null
  65. if (user) {
  66. token.id = user.id;
  67. token.apiToken = user.apiToken;
  68. token.accessToken = user.accessToken;
  69. token.role = "customer";
  70. }
  71. return token;
  72. },
  73. async session({ session, token }) {
  74. session.user = {
  75. ...session.user,
  76. id: token.id || "",
  77. // apiToken: token.apiToken,
  78. accessToken: token.accessToken,
  79. role: token.role,
  80. };
  81. return session;
  82. },
  83. },
  84. pages: {
  85. signIn: "/customer/login",
  86. error: "/login",
  87. },
  88. secret: env.NEXTAUTH_SECRET,
  89. };
  90. export const handler = NextAuth(authOptions);