Maqed
Maqed
BABetter Auth
Created by Maqed on 4/15/2025 in #help
updating schema field of type: string[] doesn't work.
No description
2 replies
BABetter Auth
Created by Maqed on 4/12/2025 in #help
How can I get member with user in adapter
No description
5 replies
BABetter Auth
Created by Maqed on 4/12/2025 in #help
Error generating schema
No description
11 replies
BABetter Auth
Created by Maqed on 4/12/2025 in #help
How can I get other plugin's option in my plugin?
I'm building a plugin to extend organization plugin. I want to get organizationOptions so I can handle other stuff in the plugin. How can I achieve that? I tried
ctx.context.options.plugins?.find((plugin) => plugin.id === "organization")?.options
ctx.context.options.plugins?.find((plugin) => plugin.id === "organization")?.options
but that didn't work even though organization plugin is setup correctly...
7 replies
BABetter Auth
Created by Maqed on 4/10/2025 in #help
How to make two unique fields in a schema
No description
2 replies
BABetter Auth
Created by Maqed on 4/7/2025 in #bug-reports
Reference naming doesn't fit all use-cases
No description
10 replies
BABetter Auth
Created by Maqed on 4/3/2025 in #help
Plugin to extend organization plugin
Hello everyone 👋 I'm building a plugin to extend organizations by making sub-organizations. The idea is that I want to extend organization schema to include sub-organizations to make it one-to-many (one organization to many sub-organization) how can I achieve such thing? I'm thinking of auth.ts:
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
import {subOrganization} from "./subOrganization"

const auth = betterAuth({
plugins: [
organization({
schema: {
organization: {
fields: {
name: "subOrganizationId"
}
}
}
}),
subOrganization({
// ...
})
]
})
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
import {subOrganization} from "./subOrganization"

const auth = betterAuth({
plugins: [
organization({
schema: {
organization: {
fields: {
name: "subOrganizationId"
}
}
}
}),
subOrganization({
// ...
})
]
})
subOrganization.ts
import type { BetterAuthPlugin } from "better-auth";

export const subOrganization= ()=>{
return {
id: "subOrganization",
schema: {
organization: {
fields: {
name: "organizationId"
}
}
}
// rest of the subOrganization logic
} satisfies BetterAuthPlugin
}
import type { BetterAuthPlugin } from "better-auth";

export const subOrganization= ()=>{
return {
id: "subOrganization",
schema: {
organization: {
fields: {
name: "organizationId"
}
}
}
// rest of the subOrganization logic
} satisfies BetterAuthPlugin
}
I don't really like this implementation as I think it would be better If I could handle all of the schema logic inside my subOrganization plugin. Is there any way better than this to handle it? thank you in advance
2 replies
BABetter Auth
Created by Maqed on 2/11/2025 in #help
Link phone number to existing users
As title says. Is there a way to link phone number to existing users? And after linking the phone number the user can sign in with this phone number.
2 replies
BABetter Auth
Created by Maqed on 2/5/2025 in #help
Can I use Phone Number plugin to just add phone number to existing users?
Basically I just wanna add phone number to existing users. Can I use Phone number plugin to do so or should I implement it myself? because Everytime I verify the phone number. callbackOnVerification return null for the user. Here is my code: client:
await authClient.phoneNumber.verify({
phoneNumber,
code,
disableSession: true,
fetchOptions: {
onError: (ctx) => {
form.setError("code", {
message: `phone-number.OTP.${ctx.error.code}`,
});
},
onSuccess: () => {
setIsDialogOpen(false);
setDialogState("InputNumber");
},
},
});
});
await authClient.phoneNumber.verify({
phoneNumber,
code,
disableSession: true,
fetchOptions: {
onError: (ctx) => {
form.setError("code", {
message: `phone-number.OTP.${ctx.error.code}`,
});
},
onSuccess: () => {
setIsDialogOpen(false);
setDialogState("InputNumber");
},
},
});
});
/lib/auth.ts:
export const auth = betterAuth({
database: prismaAdapter(db, {
provider: "postgresql",
}),
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, request) => {
// TODO: Implement sending OTP code via Whatsapp
console.log({
phoneNumber,
code,
});
},
callbackOnVerification: async ({ phoneNumber, user }, request) => {
console.log({
user,
});
// await db.user.update({
// where: {
// id: user?.id,
// },
// data: {
// phoneNumber,
// phoneNumberVerified: true,
// },
// });
},
}),
],
});
export const auth = betterAuth({
database: prismaAdapter(db, {
provider: "postgresql",
}),
plugins: [
phoneNumber({
sendOTP: ({ phoneNumber, code }, request) => {
// TODO: Implement sending OTP code via Whatsapp
console.log({
phoneNumber,
code,
});
},
callbackOnVerification: async ({ phoneNumber, user }, request) => {
console.log({
user,
});
// await db.user.update({
// where: {
// id: user?.id,
// },
// data: {
// phoneNumber,
// phoneNumberVerified: true,
// },
// });
},
}),
],
});
11 replies
BABetter Auth
Created by Maqed on 2/2/2025 in #help
Session fetched in the middleware doesn't update on every request.
As shown in the video, After signing in. I can go back to /login page even though I protected it using middleware.ts. I even tried no-storing the session but in vain. Here is middleware.ts:
import createMiddleware from "next-intl/middleware";
import { locales } from "./config";
import { NextRequest, NextResponse } from "next/server";
import {
ONLY_UNAUTHENTICATED_ROUTES,
DEFAULT_UNAUTHENTICATED_REDIRECT,
PROTECTED_ROUTES,
DEFAULT_LOGIN_REDIRECT,
} from "./consts/routes";
import { absoluteURL } from "./lib/utils";

const intlMiddleware = createMiddleware({
// A list of all locales that are supported
locales,

// Used when no locale matches
defaultLocale: "ar",
});

export default async function middleware(req: NextRequest) {
const data = await fetch(absoluteURL("/api/auth/get-session"), {
headers: {
cookie: req.headers.get("cookie") || "",
},
cache: "no-cache",
});
const session = await data.json();

// Remove locale and clean pathname
const localeMatch = req.nextUrl.pathname.match(/^\/(ar|en)(\/|$)/);
const locale = localeMatch ? localeMatch[1] : null;
const pathnameWithoutLocale = locale
? req.nextUrl.pathname.replace(`/${locale}`, "") || "/"
: req.nextUrl.pathname;

const isProtectedRoute = PROTECTED_ROUTES.some((route) =>
pathnameWithoutLocale.startsWith(route),
);

if (isProtectedRoute && !session) {
return NextResponse.redirect(
new URL(DEFAULT_UNAUTHENTICATED_REDIRECT, req.url),
);
}

if (
session &&
ONLY_UNAUTHENTICATED_ROUTES.some((route) =>
pathnameWithoutLocale.startsWith(route),
)
) {
return NextResponse.redirect(new URL(DEFAULT_LOGIN_REDIRECT, req.url));
}

return intlMiddleware(req);
}
import createMiddleware from "next-intl/middleware";
import { locales } from "./config";
import { NextRequest, NextResponse } from "next/server";
import {
ONLY_UNAUTHENTICATED_ROUTES,
DEFAULT_UNAUTHENTICATED_REDIRECT,
PROTECTED_ROUTES,
DEFAULT_LOGIN_REDIRECT,
} from "./consts/routes";
import { absoluteURL } from "./lib/utils";

const intlMiddleware = createMiddleware({
// A list of all locales that are supported
locales,

// Used when no locale matches
defaultLocale: "ar",
});

export default async function middleware(req: NextRequest) {
const data = await fetch(absoluteURL("/api/auth/get-session"), {
headers: {
cookie: req.headers.get("cookie") || "",
},
cache: "no-cache",
});
const session = await data.json();

// Remove locale and clean pathname
const localeMatch = req.nextUrl.pathname.match(/^\/(ar|en)(\/|$)/);
const locale = localeMatch ? localeMatch[1] : null;
const pathnameWithoutLocale = locale
? req.nextUrl.pathname.replace(`/${locale}`, "") || "/"
: req.nextUrl.pathname;

const isProtectedRoute = PROTECTED_ROUTES.some((route) =>
pathnameWithoutLocale.startsWith(route),
);

if (isProtectedRoute && !session) {
return NextResponse.redirect(
new URL(DEFAULT_UNAUTHENTICATED_REDIRECT, req.url),
);
}

if (
session &&
ONLY_UNAUTHENTICATED_ROUTES.some((route) =>
pathnameWithoutLocale.startsWith(route),
)
) {
return NextResponse.redirect(new URL(DEFAULT_LOGIN_REDIRECT, req.url));
}

return intlMiddleware(req);
}
NOTE: same issue occurs when I sign out and I'm in a protected route. I don't get routed to /login for some reason.
45 replies
BABetter Auth
Created by Maqed on 2/2/2025 in #help
Client side session isn't removed after deleting user
No description
4 replies