Reputation: 141
I am building a project using the t3 stack Using app router, TRPC, prisma, and next auth.
With the initial set up and even on documentation, the user model for prisma they give is with an ID, but I need my user model to only have username email password, with username being the primary key.
When I change the prisma Model and make the migrations, And in the configurations for next auth I’m using the credentials provider, And inside of it in the authorize function, it gives me an error because it expects the user To have an ID.
I cannot find anywhere in the documentation or anywhere else. How can I make my authorization work with just username email and password and without an ID.
Anyone have any suggestions?
here is my code:
this is - src/server/auth.ts
/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
* object and keep type safety.
*
* @see https://next-auth.js.org/getting-started/typescript#module-augmentation
*/
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
username: string;
email: string;
first_name: string;
last_name: string;
} & DefaultSession["user"];
}
interface User {
username: string;
email: string;
password: string;
first_name: string;
last_name: string;
}
}
/**
* Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
*
* @see https://next-auth.js.org/configuration/options
*/
export const authOptions: NextAuthOptions = {
callbacks: {
session: ({ session, user }) => ({
...session,
user: {
...session.user,
username: user.username,
email: user.email,
first_name: user.first_name,
last_name: user.last_name,
},
}),
},
// adapter: PrismaAdapter(db) as Adapter,
providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. 'Sign in with...')
name: "Credentials",
// The credentials is used to generate a suitable form on the sign in page.
// You can specify whatever fields you are expecting to be submitted.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
username: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
const creds = await z
.object({
username: z.string(),
password: z.string().min(6),
})
.parseAsync(credentials);
// Find user by username
const user = await db.user.findUnique({
where: { username: creds.username },
});
// If user not found, return null
if (!user) return null;
// Verify password
const valid = await verifyPassword(creds.password, user.password);
// If password is invalid, return null
if (!valid) return null;
// If user is found and password is valid, return user
return user;
},
}),
/**
* ...add more providers here.
*
* Most other providers require a bit more work than the Discord provider. For example, the
* GitHub provider requires you to add the `refresh_token_expires_in` field to the Account
* model. Refer to the NextAuth.js docs for the provider you want to use. Example:
*
* @see https://next-auth.js.org/providers/github
*/
],
};
this is my prisma schema
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
generator zod {
provider = "zod-prisma-types"
}
datasource db {
provider = "postgresql"
// NOTE: When using mysql or sqlserver, uncomment the @db.Text annotations in model Account below
// Further reading:
// https://next-auth.js.org/adapters/prisma#create-the-prisma-schema
// https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#string
url = env("DATABASE_URL")
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
usernameId String
expires DateTime
user User @relation(fields: [usernameId], references: [username], onDelete: Cascade)
}
model User {
username String @unique
email String @unique
password String
first_name String
last_name String
sessions Session[]
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
this is the error
Type '(credentials: Record<"username" | "password", string> | undefined, req: Pick<RequestInternal, "body" | "query" | "headers" | "method">) => Promise<...>' is not assignable to type '(credentials: Record<"username" | "password", string> | undefined, req: Pick<RequestInternal, "body" | "query" | "headers" | "method">) => Awaitable<...>'.
Type 'Promise<{ username: string; email: string; password: string; first_name: string; last_name: string; } | null>' is not assignable to type 'Awaitable<User | null>'.
Type 'Promise<{ username: string; email: string; password: string; first_name: string; last_name: string; } | null>' is not assignable to type 'PromiseLike<User | null>'.
Types of property 'then' are incompatible.
Type '<TResult1 = { username: string; email: string; password: string; first_name: string; last_name: string; } | null, TResult2 = never>(onfulfilled?: ((value: { username: string; email: string; password: string; first_name: string; last_name: string; } | null) => TResult1 | PromiseLike<...>) | null | undefined, onreject...' is not assignable to type '<TResult1 = User | null, TResult2 = never>(onfulfilled?: ((value: User | null) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | null | undefined) => PromiseLike<...>'.
Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
Types of parameters 'value' and 'value' are incompatible.
Type '{ username: string; email: string; password: string; first_name: string; last_name: string; } | null' is not assignable to type 'User | null'.
Property 'id' is missing in type '{ username: string; email: string; password: string; first_name: string; last_name: string; }' but required in type 'User'.ts(2322)
types.d.ts(504, 5): 'id' is declared here.
credentials.d.ts(13, 5): The expected type comes from property 'authorize' which is declared here on type 'UserCredentialsConfig<{ username: { label: string; type: string; placeholder: string; }; password: { label: string; type: string; }; }>'
(property) authorize: (credentials: Record<"username" | "password", string> | undefined, req: Pick<RequestInternal, "body" | "query" | "headers" | "method">) => Awaitable<User | null>
Upvotes: 0
Views: 501
Reputation: 49561
Can yu use @id
in User
model User {
// @id makes it primary key.
username String @id @unique
}
Upvotes: 0