example: fix auth client

This commit is contained in:
Bereket Engida
2024-09-07 11:42:12 +03:00
parent c1b0328005
commit 2d43dbc479
11 changed files with 45 additions and 98 deletions

View File

@@ -154,4 +154,22 @@ export async function ServerComponent() {
</div>
)
}
```
```
## Middleware
You can use the `authMiddleware` to protect your routes. It's a wrapper around the Next.js middleware.
```ts twoslash title="middleware.ts"
import { authMiddleware } from "better-auth/next-js"
export default authMiddleware({
redirectTo: "/sign-in" // redirect to this path if the user is not authenticated
})
export const config = {
matcher: ['/dashboard/:path*'],
}
```

View File

@@ -1,4 +1,4 @@
import { auth } from "@/lib/_auth";
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { POST, GET } = toNextJsHandler(auth);

View File

@@ -1,6 +1,6 @@
import { Organization } from "@/components/organization";
import UserCard from "@/components/user-card";
import { auth } from "@/lib/_auth";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
export default async function TypewriterEffectSmoothDemo() {

View File

@@ -212,7 +212,6 @@ export function Organization() {
</li>
))}
</ul>
<div>
<div className="flex items-center gap-2 mt-4">
<MessageSquareText size={18} />

View File

@@ -5,12 +5,8 @@ import {
passkeyClient,
usernameClient,
} from "better-auth/client/plugins";
import { ac } from "./permissions";
export const authClient = createAuthClient({
fetchOptions: {
baseURL: "http://localhost:3000/api/auth",
},
plugins: [
organizationClient(),
twoFactorClient({

View File

@@ -1,20 +0,0 @@
import { betterAuth } from "better-auth";
import { twoFactor, organization, passkey } from "better-auth/plugins";
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./prisma/sqlite.db",
},
plugins: [
twoFactor({
issuer: "my app",
}),
organization(),
passkey({
rpID: "localhost",
rpName: "BetterAuth",
origin: "http://localhost:3000",
}),
],
});

View File

@@ -9,7 +9,6 @@ import { github, google } from "better-auth/social-providers";
import { ac, admin } from "./permissions";
export const auth = betterAuth({
basePath: "/api/auth",
socialProvider: [
github({
clientId: process.env.GITHUB_CLIENT_ID as string,
@@ -51,7 +50,7 @@ export const auth = betterAuth({
}),
passkey({
rpID: "localhost",
rpName: "BetterAuth",
rpName: "better-auth",
origin: "http://localhost:3000",
}),
username(),

View File

@@ -1,5 +1,5 @@
import type { InferSession, InferUser } from "better-auth/types";
import type { auth } from "./_auth";
import type { auth } from "./auth";
export type User = InferUser<typeof auth>;
export type Session = InferSession<typeof auth>;

View File

@@ -1,25 +1,10 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { authClient } from "./lib/auth-client";
import { authMiddleware } from "better-auth/next-js";
import { NextRequest } from "next/server";
export async function middleware(request: NextRequest) {
const session = await authClient.session({
options: {
headers: request.headers,
},
});
if (!session.data) {
return NextResponse.redirect(new URL("/sign-in", request.url));
}
const canInvite = await authClient.organization.hasPermission({
permission: {
invitation: ["create"],
},
options: {
headers: request.headers,
},
});
return NextResponse.next();
export default async function middleware(request: NextRequest) {
const res = await authMiddleware({
redirectTo: "/sign-in",
})(request);
}
export const config = {

View File

@@ -26,7 +26,7 @@ export const betterAuth = <O extends BetterAuthOptions>(options: O) => {
return handler(request);
},
api,
options: authContext.options,
options: authContext.options as O,
};
};

View File

@@ -17,51 +17,21 @@ export function toNextJsHandler(auth: Auth | Auth["handler"]) {
* Middleware that checks if the user is authenticated.
* If not, it redirects to the redirectTo URL.
*/
export async function authMiddleware<T extends Auth>(
auth: T,
options: {
matcher: (request: NextRequest) =>
| Array<{
redirectTo: string;
shouldRedirect: boolean;
}>
| Promise<
Array<{
redirectTo: string;
shouldRedirect: boolean;
}>
>
| {
redirectTo: string;
shouldRedirect: boolean;
}
| Promise<{
redirectTo: string;
shouldRedirect: boolean;
}>;
},
) {
return async (request: NextRequest) => {
let redirection = await options.matcher(request);
if (!Array.isArray(redirection)) {
redirection = [redirection];
}
for (const { shouldRedirect, redirectTo } of redirection) {
console.log({ shouldRedirect, redirectTo });
if (shouldRedirect) {
const url = new URL(request.url).origin;
const basePath = auth.options.basePath || "/api/auth";
const fullURL = `${url}${basePath}/session`;
const res = await betterFetch<{
session: Session;
}>(fullURL, {
headers: request.headers,
});
if (!res.data?.session) {
return NextResponse.redirect(new URL(redirectTo, request.url));
}
}
export function authMiddleware(options: {
baePath?: string;
redirectTo: string;
}) {
return async (request: Request) => {
const url = new URL(request.url).origin;
const basePath = options?.baePath || "/api/auth";
const fullURL = `${url}${basePath}/session`;
const res = await betterFetch<{
session: Session;
}>(fullURL, {
headers: request.headers,
});
if (!res.data) {
return NextResponse.redirect(new URL(options.redirectTo, url));
}
return NextResponse.next();
};