Next.js Discord

Discord Forum

Next auth

Unanswered
Sun bear posted this in #help-forum
Open in Discord
Sun bearOP
how can i combine credentials authentication with google and github provider?

9 Replies

Sun bearOP
for example
if user wants to sign in with credentials he should register firstly on different page
but user also can register with github or google
import { prisma } from "@/lib/prisma";
import { compare } from "bcryptjs";
import type { NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import CredentialsProvider from "next-auth/providers/credentials";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@next-auth/prisma-adapter";

function updateLastLoginTime(id: string) {
  return prisma.user.update({
    where: {
      id: id,
    },
    data: {
      lastLoginTime: new Date(),
    },
  });
}

export const authOptions: NextAuthOptions = {
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET as string,
  adapter: PrismaAdapter(prisma),
  providers: [
    CredentialsProvider({
      name: "Sign in",
      credentials: {
        email: { label: "Email", type: "email", placeholder: "jsmith" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        const { email, password } = credentials as {
          email: string;
          password: string;
        };
        if (!credentials || !email || !password) {
          throw new Error("Invalid credentials");
        }
        const user = await prisma.user.findUnique({
          where: {
            email: email,
          },
        });
        if (!user || !(await compare(password, user.password))) {
          throw new Error("Email or password is incorrect");
        }
        if (user.isBlocked) {
          throw new Error("User is blocked");
        }
        await updateLastLoginTime(user.id);
        return {
          id: user.id,
          email: user.email,
        };
      },
    }),
    GithubProvider({
      clientId: process.env.GITHUB_ID as string,
      clientSecret: process.env.GITHUB_SECRET as string,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    }),
  ],
  pages: {
  },
};
model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String? @db.Text
  access_token      String? @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String? @db.Text
  session_state     String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@index([userId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId])
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]

  password         String
  isAdmin          Boolean   @default(false)
  lastLoginTime    DateTime? @db.Timestamp(0)
  registrationTime DateTime  @default(now()) @db.Timestamp(0)
  isBlocked        Boolean   @default(false)
  reviews          Review[]
  comments         Comment[]
  likes            Like[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}
i want one table for users
where i will have as credential users and also provider google, github ones
i mean, i dont want to link github provider on already created user
i want new user if user firstly enters with github