sidebase / nuxt-auth

Authentication built for Nuxt 3! Easily add authentication via OAuth providers, credentials or Email Magic URLs!
https://auth.sidebase.io
MIT License
1.31k stars 164 forks source link

No session is created with Credentials #486

Closed hasan-ahani closed 1 year ago

hasan-ahani commented 1 year ago

Environment

No response

Reproduction

No response

Describe the bug

I have written the authentication process as per the example. Everything works well. But the session is not created with Credentials.

The user matching process works correctly. But it is transferred to the main page and the user is not logged in yet Authentication with GitHub is correct and there is no problem.

import { NuxtAuthHandler } from "#auth";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import db from "@/lib/db";
import bcrypt from "bcrypt";

export default NuxtAuthHandler({
  secret: process.env.NUXTAUTH_SECRET,
  adapter: PrismaAdapter(db),
  providers: [
    // @ts-expect-error
    GithubProvider.default({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    }),
    // @ts-ignore
    GoogleProvider.default({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    // @ts-ignore
    CredentialsProvider.default({
      name: "Credentials",
      credentials: {
        email: {
          label: "Email",
          type: "email",
          placeholder: "user@example.com",
        },
        password: {
          label: "Password",
          type: "password",
          placeholder: "password",
        },
      },
      async authorize(credentials: any) {
        if (!credentials?.email || !credentials?.password) {
          return null;
        }

        const userFound = await db.user.findUnique({
          where: {
            email: credentials.email,
          },
        });

        if (!userFound) {
          return null;
        }

        const isCorrectPassword = await bcrypt.compare(
          credentials.password,
          userFound.password as string
        );

        if (!isCorrectPassword) {
          return null;
        }

        const user = {
          id: userFound.id.toString(),
          name: userFound.name ?? userFound.email,
          email: userFound.email,
          image: userFound.image,
        }

        console.log(user)
        return user;
      },
    }),
  ],
});

Additional context

{
  "devDependencies": {
    "@next-auth/prisma-adapter": "^1.0.7",
    "@nuxt/devtools": "latest",
    "@nuxthq/ui": "^2.5.0",
    "@nuxtjs/i18n": "^8.0.0-beta.13",
    "@nuxtjs/tailwindcss": "^6.8.0",
    "@sidebase/nuxt-auth": "^0.6.0-beta.3",
    "@types/bcrypt": "^5.0.0",
    "@types/node": "^18.16.19",
    "nuxt": "^3.6.2",
    "prisma": "^5.0.0"
  },
  "dependencies": {
    "@pinia-plugin-persistedstate/nuxt": "^1.1.1",
    "@pinia/nuxt": "^0.4.11",
    "@prisma/client": "^5.0.0",
    "bcrypt": "^5.1.0",
    "next-auth": "4.21.1",
    "yup": "^1.2.0"
  }
}
{
  // The module is enabled. Change this to disable the module
  isEnabled: true,
  // The origin is set to the development origin. Change this when deploying to production by setting `origin` in this config before build-time or by exporting `AUTH_ORIGIN` by running `export AUTH_ORIGIN=...`
  //
  origin: process.env.AUTH_ORIGIN,
  // The base path to the authentication endpoints. Change this if you want to add your auth-endpoints at a non-default location
  basePath: "/api/auth",
  // Whether to periodically refresh the session. Change this to `true` for a refresh every seconds or set this to a number like `5000` for a refresh every 5000 milliseconds (aka: 5 seconds)
  enableSessionRefreshPeriodically: 5000,
  // Whether to refresh the session whenever a window focus event happens, i.e, when your user refocuses the window. Set this to `false` to turn this off
  enableSessionRefreshOnWindowFocus: true,
  // Whether to add a global authentication middleware that will protect all pages without exclusion
  globalAppMiddleware: true,
  // Select the default-provider to use when `signIn` is called. Setting this here will also effect the global middleware behavior: E.g., when you set it to `github` and the user is unauthorized, they will be directly forwarded to the Github OAuth page instead of seeing the app-login page
  defaultProvider: undefined,
  // Whether to automatically set the callback url to the page the user tried to visit when the middleware stopped them. This is useful to disable this when using the credentials provider, as it does not allow a `callbackUrl`. Setting this to a string-value will result in that being used as the callbackUrl path.
  addDefaultCallbackUrl: true,
  // Configuration of the global auth-middleware (only applies if you set `globalAppMiddleware: true` above!)
  globalMiddlewareOptions: {
    // Whether to allow access to 404 pages without authentication. Set this to `false` to force users to sign-in before seeing `404` pages. Setting this to false may lead to vue-router problems (as the target page does not exist)
    allow404WithoutAuth: true,
    // Whether to automatically set the callback url to the page the user tried to visit when the middleware stopped them. This is useful to disable this when using the credentials provider, as it does not allow a `callbackUrl`. Setting this to a string-value will result in that being used as the callbackUrl path. Note: You also need to set the global `addDefaultCallbackUrl` setting to `false` if you want to fully disable this for the global middleware.
    addDefaultCallbackUrl: true,
  },
}

Logs

[7:44:25 PM] prisma:query SELECT main.User.id, main.User.name, main.User.email, main.User.emailVerified, main.User.image, main.User.password FROM main.User WHERE (main.User.email = ? AND 1=1) LIMIT ? OFFSET ?
{                                                                                                           7:44:25 PM
  id: 'clk8gsvd50000i0lwqh9fhxkf',
  name: 'test',
  email: 'test@gmail.com',
  image: null
}
codetheorist commented 1 year ago

Do you know how big the session token is when being saved in the browser? Is there enough that the session cookie is split into multiple chunks? If so, there's currently an issue outstanding regarding the re-joining of chunked cookies being out-of-order.

Could you check the browser inspector and see if there are multiple session cookies? If there are, then that would most certainly cause the issue of logging back out again.

Also, if you enable debug mode, the Nuxt console will state there's been a JWT_SESSION_ERROR which is JWE Initialization Vector missing or incorrect type.

zoey-kaiser commented 1 year ago

Hi @hasan-ahani,

I assume like mentioned above that this has to do with a large cookie not being stored correctly. Please refer to the linked issue. As this issue is also pretty old and stale, I will close it now. If you need further assistance please message in this issue and we can reopen it!

razbakov commented 11 months ago

I have the same problem. Once I remove PrismaAdapter, it works.