authClient help

How to make it so, with auth-client signUp, i can insert other stuff than email and name?
11 Replies
In&Out
In&OutOP2mo ago
@nikatune do you know by any chance, still cant find in docs @Ping sorry for tagging if not, can you at least tell me how to change message of errors in auth?
export async function registerUser(prevState: unknown, formData: FormData) {
try {
const email = formData.get("email")?.toString().trim();
const password = formData.get("password")?.toString();
const userName = formData.get("username")?.toString().trim();
const category = formData.get("category")?.toString();

if (!email || !password || !userName || !category) {
return { error: "Sva polja su obavezna." };
}

const ibk_slug = userName
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");

await auth.api.signUpEmail({
body: {
email,
password,
name: userName,
ibk_slug,
category,
role: "admin",
},
});

return { redirect: `/dashboard/${ibk_slug}` };
} catch (error) {
if (error instanceof APIError) {
console.log(error.message, error.status);
return { error: error.message };
} else {
console.error("Registration error:", error);
return { error: "Došlo je do greške. Molimo pokušajte ponovo." };
}
}
}
export async function registerUser(prevState: unknown, formData: FormData) {
try {
const email = formData.get("email")?.toString().trim();
const password = formData.get("password")?.toString();
const userName = formData.get("username")?.toString().trim();
const category = formData.get("category")?.toString();

if (!email || !password || !userName || !category) {
return { error: "Sva polja su obavezna." };
}

const ibk_slug = userName
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");

await auth.api.signUpEmail({
body: {
email,
password,
name: userName,
ibk_slug,
category,
role: "admin",
},
});

return { redirect: `/dashboard/${ibk_slug}` };
} catch (error) {
if (error instanceof APIError) {
console.log(error.message, error.status);
return { error: error.message };
} else {
console.error("Registration error:", error);
return { error: "Došlo je do greške. Molimo pokušajte ponovo." };
}
}
}
Ping
Ping2mo ago
Can you show me your auth config? @In&Out
nikatune
nikatune2mo ago
hooks: {
after: createAuthMiddleware(async (ctx) => {
const path = ctx.path;
const response = ctx.context.returned as APIError;
if (
path.startsWith('/sign-up') &&
response.body?.code === 'USER_ALREADY_EXISTS'
) {
throw new APIError('BAD_REQUEST', {
...response.body,
message: 'Tài khoản đã tồn tại', // account already exists
});
}
if (
path.startsWith('/sign-in') &&
response.body?.code === 'INVALID_EMAIL_OR_PASSWORD'
) {
throw new APIError('UNAUTHORIZED', {
...response.body,
message: 'Tên đăng nhập hoặc mật khẩu không hợp lệ', // invalid email or password
});
}
if(path.startsWith('/change-password') && response.body?.code === 'INVALID_PASSWORD'){
throw new APIError('BAD_REQUEST', {
...response.body,
message: "Mật khẩu hiện tại không hợp lệ" //current password is invalid
})
}
}),
},
hooks: {
after: createAuthMiddleware(async (ctx) => {
const path = ctx.path;
const response = ctx.context.returned as APIError;
if (
path.startsWith('/sign-up') &&
response.body?.code === 'USER_ALREADY_EXISTS'
) {
throw new APIError('BAD_REQUEST', {
...response.body,
message: 'Tài khoản đã tồn tại', // account already exists
});
}
if (
path.startsWith('/sign-in') &&
response.body?.code === 'INVALID_EMAIL_OR_PASSWORD'
) {
throw new APIError('UNAUTHORIZED', {
...response.body,
message: 'Tên đăng nhập hoặc mật khẩu không hợp lệ', // invalid email or password
});
}
if(path.startsWith('/change-password') && response.body?.code === 'INVALID_PASSWORD'){
throw new APIError('BAD_REQUEST', {
...response.body,
message: "Mật khẩu hiện tại không hợp lệ" //current password is invalid
})
}
}),
},
i guess you can do something like this for customizing error messages
In&Out
In&OutOP2mo ago
i ended up doing this, it works but idk how well it is
export async function registerUser(prevState: unknown, formData: FormData) {
try {
const email = formData.get("email")?.toString().trim();
const password = formData.get("password")?.toString();
const userName = formData.get("username")?.toString().trim();
const category = formData.get("category")?.toString();

if (!email || !password || !userName || !category) {
return { error: "Sva polja su obavezna." };
}

const ibk_slug = userName
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");

await auth.api.signUpEmail({
body: {
email,
password,
name: userName,
ibk_slug,
category,
role: "admin",
},
});

return { redirect: `/dashboard/${ibk_slug}` };
} catch (error) {
if (error instanceof APIError) {
console.log(error.message, error.status);
const customError = getCustomError(error.message);
return { error: customError };
} else {
console.error("Registration error:", error);
return { error: "Došlo je do greške. Molimo pokušajte ponovo." };
}
}
}

function getCustomError(error: string | { message?: string }): string {
const errorMessage = typeof error === "string" ? error : error.message || "";

const errorMessages: Record<string, string> = {
"Email already in use": "Email adresa je već u upotrebi",
"Invalid email": "Neispravna email adresa",
"Weak password": "Lozinka mora biti jača (minimalno 8 karaktera)",
"User already exists": "Korisnik sa ovim podacima već postoji",
"Missing required fields": "Nisu popunjena sva obavezna polja",
};

return (
errorMessages[errorMessage] ||
"Došlo je do greške prilikom registracije. Pokušajte ponovo kasnije."
);
}
export async function registerUser(prevState: unknown, formData: FormData) {
try {
const email = formData.get("email")?.toString().trim();
const password = formData.get("password")?.toString();
const userName = formData.get("username")?.toString().trim();
const category = formData.get("category")?.toString();

if (!email || !password || !userName || !category) {
return { error: "Sva polja su obavezna." };
}

const ibk_slug = userName
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");

await auth.api.signUpEmail({
body: {
email,
password,
name: userName,
ibk_slug,
category,
role: "admin",
},
});

return { redirect: `/dashboard/${ibk_slug}` };
} catch (error) {
if (error instanceof APIError) {
console.log(error.message, error.status);
const customError = getCustomError(error.message);
return { error: customError };
} else {
console.error("Registration error:", error);
return { error: "Došlo je do greške. Molimo pokušajte ponovo." };
}
}
}

function getCustomError(error: string | { message?: string }): string {
const errorMessage = typeof error === "string" ? error : error.message || "";

const errorMessages: Record<string, string> = {
"Email already in use": "Email adresa je već u upotrebi",
"Invalid email": "Neispravna email adresa",
"Weak password": "Lozinka mora biti jača (minimalno 8 karaktera)",
"User already exists": "Korisnik sa ovim podacima već postoji",
"Missing required fields": "Nisu popunjena sva obavezna polja",
};

return (
errorMessages[errorMessage] ||
"Došlo je do greške prilikom registracije. Pokušajte ponovo kasnije."
);
}
and auth client
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";
import { Pool } from "pg";
import { admin } from "better-auth/plugins";

export const auth = betterAuth({
database: new Pool({
connectionString: process.env.DATABASE_URL,
}),
emailAndPassword: {
enabled: true,
},
secret:process.env.BETTER_AUTH_SECRET,
user: {
additionalFields: {
role: {
type: "string",
required: false,
defaultValue: "admin",
input: true,
},
ibk_slug: {
type: "string",
required: false,
},
category: {
type: "string",
required: true,
},
},
},
plugins: [
nextCookies(),
admin({
defaultRole: "admin",
}),
],
});
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";
import { Pool } from "pg";
import { admin } from "better-auth/plugins";

export const auth = betterAuth({
database: new Pool({
connectionString: process.env.DATABASE_URL,
}),
emailAndPassword: {
enabled: true,
},
secret:process.env.BETTER_AUTH_SECRET,
user: {
additionalFields: {
role: {
type: "string",
required: false,
defaultValue: "admin",
input: true,
},
ibk_slug: {
type: "string",
required: false,
},
category: {
type: "string",
required: true,
},
},
},
plugins: [
nextCookies(),
admin({
defaultRole: "admin",
}),
],
});
where do you put this?
nikatune
nikatune2mo ago
auth.ts
In&Out
In&OutOP2mo ago
okay, it works well ngl, thank you but for login, i use client auth,
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
setIsLoading(true);

try {
const { error } = await signIn.email({
email,
password,
});

if (error) {
console.log(error)
setError(error.message || "Login failed. Please try again.");
} else {
router.push("/dashboard");
}
} catch (err) {
console.error(err);
setError("An unexpected error occurred. Please try again.");
} finally {
setIsLoading(false);
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
setIsLoading(true);

try {
const { error } = await signIn.email({
email,
password,
});

if (error) {
console.log(error)
setError(error.message || "Login failed. Please try again.");
} else {
router.push("/dashboard");
}
} catch (err) {
console.error(err);
setError("An unexpected error occurred. Please try again.");
} finally {
setIsLoading(false);
}
};
tho when i console.log error, i get this
{
"status": 0,
"statusText": ""
}
{
"status": 0,
"statusText": ""
}
the heck is status 0? lol
Ping
Ping2mo ago
I'm not sure what the purpose of your app is, but it's usually not a good idea to allow sending the role from your front-end. Also make sure the nextCookies plugin is at the end of the array. does your server logs say anything?
In&Out
In&OutOP2mo ago
nop i couldnt figure out how to make it default so i had to do that well its not in client anyways so no worries i guess its in server actions file
const ibk_slug = userName
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");

await auth.api.signUpEmail({
body: {
email,
password,
name: userName,
ibk_slug,
category,
role: "admin",
},
});
const ibk_slug = userName
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");

await auth.api.signUpEmail({
body: {
email,
password,
name: userName,
ibk_slug,
category,
role: "admin",
},
});
nevermind, fixed it
Ping
Ping2mo ago
The endpoint is open, anyone can call that endpoint.
In&Out
In&OutOP2mo ago
oh dumb me lol
nikatune
nikatune2mo ago
lol

Did you find this page helpful?