mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-09 20:27:44 +00:00
fix: bearer token interception for direct API calls
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import {
|
||||
bearer,
|
||||
organization,
|
||||
passkey,
|
||||
phoneNumber,
|
||||
@@ -12,6 +13,7 @@ import { resend } from "./email/resend";
|
||||
|
||||
const from = process.env.BETTER_AUTH_EMAIL || "delivered@resend.dev";
|
||||
const to = process.env.TEST_EMAIL || "";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: new LibsqlDialect({
|
||||
url: process.env.TURSO_DATABASE_URL || "",
|
||||
@@ -80,6 +82,7 @@ export const auth = betterAuth({
|
||||
},
|
||||
}),
|
||||
passkey(),
|
||||
bearer()
|
||||
],
|
||||
socialProviders: {
|
||||
github: {
|
||||
|
||||
@@ -110,11 +110,33 @@ export function getEndpoints<
|
||||
let api: Record<string, any> = {};
|
||||
for (const [key, value] of Object.entries(endpoints)) {
|
||||
api[key] = async (context: any) => {
|
||||
/**
|
||||
* TODO: move this to respond a json response
|
||||
* instead of response object.
|
||||
*/
|
||||
const c = await ctx;
|
||||
let c = await ctx;
|
||||
for (const plugin of options.plugins || []) {
|
||||
if (plugin.hooks?.before) {
|
||||
for (const hook of plugin.hooks.before) {
|
||||
const match = hook.matcher({
|
||||
...value,
|
||||
...context,
|
||||
context: c,
|
||||
});
|
||||
if (match) {
|
||||
const hookRes = await hook.handler({
|
||||
...context,
|
||||
context: {
|
||||
...c,
|
||||
...context.context,
|
||||
},
|
||||
});
|
||||
if (hookRes && "context" in hookRes) {
|
||||
c = {
|
||||
...c,
|
||||
...hookRes.context,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//@ts-ignore
|
||||
const endpointRes = await value({
|
||||
...context,
|
||||
|
||||
@@ -19,7 +19,6 @@ type InferAPI<API> = Omit<
|
||||
export const betterAuth = <O extends BetterAuthOptions>(options: O) => {
|
||||
const authContext = init(options);
|
||||
const { api } = getEndpoints(authContext, options);
|
||||
type API = typeof api;
|
||||
|
||||
return {
|
||||
handler: async (request: Request) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { bearer } from ".";
|
||||
import { getTestInstance } from "../../test-utils/test-instance";
|
||||
|
||||
describe("bearer", async () => {
|
||||
const { client, signInWithTestUser } = await getTestInstance({
|
||||
const { client, signInWithTestUser, auth } = await getTestInstance({
|
||||
plugins: [bearer()],
|
||||
});
|
||||
|
||||
@@ -32,4 +32,15 @@ describe("bearer", async () => {
|
||||
});
|
||||
expect(sessions.data).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("should work on server actions", async () => {
|
||||
const { res } = await signInWithTestUser();
|
||||
token = res.data?.session.id || "";
|
||||
const headers = new Headers();
|
||||
headers.set("authorization", `Bearer ${token}`);
|
||||
const session = await auth.api.getSession({
|
||||
headers,
|
||||
});
|
||||
expect(session?.session.id).toBe(token);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { serializeSigned } from "better-call";
|
||||
import { createAuthMiddleware } from "../../api/call";
|
||||
import { BetterAuthError } from "../../error/better-auth-error";
|
||||
import type { BetterAuthPlugin } from "../../types/plugins";
|
||||
|
||||
/**
|
||||
@@ -9,25 +7,49 @@ import type { BetterAuthPlugin } from "../../types/plugins";
|
||||
export const bearer = () => {
|
||||
return {
|
||||
id: "bearer",
|
||||
async onRequest(request, ctx) {
|
||||
const token = request.headers
|
||||
.get("authorization")
|
||||
?.replace("Bearer ", "");
|
||||
hooks: {
|
||||
before: [
|
||||
{
|
||||
matcher(context) {
|
||||
return Boolean(
|
||||
context.request?.headers.get("authorization") ||
|
||||
context.headers?.get("authorization"),
|
||||
);
|
||||
},
|
||||
handler: async (c) => {
|
||||
const token =
|
||||
c.request?.headers.get("authorization")?.replace("Bearer ", "") ||
|
||||
c.headers?.get("authorization")?.replace("Bearer ", "");
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
const headers = request.headers || new Headers();
|
||||
const signedToken = await serializeSigned("", token, ctx.secret);
|
||||
headers.set(
|
||||
"cookie",
|
||||
`${ctx.authCookies.sessionToken.name}=${signedToken.replace("=", "")}`,
|
||||
const signedToken = await serializeSigned(
|
||||
"",
|
||||
token,
|
||||
c.context.secret,
|
||||
);
|
||||
if (c.request) {
|
||||
c.request.headers.set(
|
||||
"cookie",
|
||||
`${
|
||||
c.context.authCookies.sessionToken.name
|
||||
}=${signedToken.replace("=", "")}`,
|
||||
);
|
||||
}
|
||||
if (c.headers) {
|
||||
c.headers.set(
|
||||
"cookie",
|
||||
`${
|
||||
c.context.authCookies.sessionToken.name
|
||||
}=${signedToken.replace("=", "")}`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
request: new Request(request.url, {
|
||||
method: request.method,
|
||||
headers,
|
||||
}),
|
||||
context: c,
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} satisfies BetterAuthPlugin;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user