Skip to content

Commit

Permalink
feat: infer trusted origins from env
Browse files Browse the repository at this point in the history
  • Loading branch information
Bekacru committed Oct 14, 2024
1 parent dfdf405 commit b3b2f5d
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 16 deletions.
6 changes: 5 additions & 1 deletion demo/nextjs/components/sign-in.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,11 @@ export default function SignIn() {
className="gap-2"
onClick={async () => {
await signIn.passkey({
callbackURL: "/dashboard",
fetchOptions: {
onResponse(context) {
router.push("/dashboard");
},
},
});
}}
>
Expand Down
1 change: 1 addition & 0 deletions demo/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"scripts": {
"dev": "next dev",
"dev:secure": "next dev --experimental-https",
"typecheck": "tsc --noEmit",
"build": "next build",
"start": "next start",
"lint": "next lint"
Expand Down
10 changes: 9 additions & 1 deletion docs/content/docs/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@ BETTER_AUTH_SECRET=
```
<GenerateSecret/>

2. **Set Base URL (optional)**
2. **Set Base URL**

```txt title=".env"
BETTER_AUTH_URL=http://localhost:3000 #Base URL of your app
```

3. **Trusted Origins (optional)**

If the requests are coming from different origins (not the base url), you can add them to the trusted origins.

```txt title=".env"
BETTER_AUTH_TRUSTED_ORIGINS="http://localhost:3000,https://example.com" //Add your trusted origins here
```
</Step>

<Step>
Expand Down
5 changes: 1 addition & 4 deletions packages/better-auth/src/api/middlewares/csrf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ export const csrfMiddleware = createAuthMiddleware(
* origin is in the trustedOrigins then we
* don't need to check the CSRF token.
*/
if (
url.origin === new URL(ctx.context.baseURL).origin ||
ctx.context.options.trustedOrigins?.includes(url.origin)
) {
if (ctx.context.trustedOrigins.includes(url.origin)) {
return;
}

Expand Down
5 changes: 1 addition & 4 deletions packages/better-auth/src/api/middlewares/redirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@ export const redirectURLMiddleware = createAuthMiddleware(async (ctx) => {
const clientCurrentURL = ctx.headers?.get("referer");
const currentURL =
ctx.query?.currentURL || clientCurrentURL || ctx.context.baseURL;
const trustedOrigins = ctx.context.trustedOrigins;

const trustedOrigins = [
ctx.context.baseURL ? new URL(ctx.context.baseURL).origin : undefined,
...(ctx.context.options.trustedOrigins || []),
];
if (callbackURL?.includes("http")) {
const callbackOrigin = new URL(callbackURL).origin;
if (!trustedOrigins.includes(callbackOrigin)) {
Expand Down
3 changes: 3 additions & 0 deletions packages/better-auth/src/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe("init", async () => {
const database = new Database(":memory:");
it("should match config", () => {
const res = init({
baseURL: "http://localhost:3000",
database,
});
expect(res).toMatchSnapshot();
Expand All @@ -16,6 +17,7 @@ describe("init", async () => {
it("should execute plugins init", async () => {
const newBaseURL = "http://test.test";
const res = await init({
baseURL: "http://localhost:3000",
database,
plugins: [
{
Expand Down Expand Up @@ -43,6 +45,7 @@ describe("init", async () => {
expect(ctx.baseURL).toBe(`http://localhost:3000${customPath}`);

const res = betterAuth({
baseURL: "http://localhost:3000",
database,
basePath: customPath,
});
Expand Down
43 changes: 37 additions & 6 deletions packages/better-auth/src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ import {
} from "./cookies";
import { createLogger, logger } from "./utils/logger";
import { oAuthProviderList, oAuthProviders } from "./social-providers";
import { BetterAuthError } from "./error/better-auth-error";

export const init = async (options: BetterAuthOptions) => {
const adapter = await getAdapter(options);
const plugins = options.plugins || [];
const internalPlugins = getInternalPlugins(options);

const { kysely: db } = await createKyselyAdapter(options);
const baseURL = getBaseURL(options.baseURL, options.basePath) || "";
const baseURL = getBaseURL(options.baseURL, options.basePath);

/**
* Add baseURL to trusted origins if it exists
*/
if (baseURL) {
options.trustedOrigins = [...(options.trustedOrigins || []), baseURL];
if (!baseURL) {
throw new BetterAuthError(
"Base URL can not be empty. Please add `BETTER_AUTH_URL` in your environment variables or pass it your auth config.",
);
}

const secret =
Expand All @@ -43,6 +43,17 @@ export const init = async (options: BetterAuthOptions) => {
process.env.AUTH_SECRET ||
DEFAULT_SECRET;

if (secret === DEFAULT_SECRET) {
if (process.env.NODE_ENV === "production") {
throw new BetterAuthError(
"You are using the default secret. Please set `BETTER_AUTH_SECRET` or `AUTH_SECRET` in your environment variables or pass `secret` in your auth config.",
);
}
logger.warn(
"You are using the default secret. This is not recommended. Please set `BETTER_AUTH_SECRET` or `AUTH_SECRET` in your environment variables or pass `secret` in your auth config.",
);
}

options = {
...options,
secret,
Expand Down Expand Up @@ -73,6 +84,7 @@ export const init = async (options: BetterAuthOptions) => {
socialProviders,
options,
tables,
trustedOrigins: getTrustedOrigins(options),
baseURL: baseURL,
sessionConfig: {
updateAge: options.session?.updateAge || 24 * 60 * 60, // 24 hours
Expand Down Expand Up @@ -119,6 +131,7 @@ export type AuthContext = {
options: BetterAuthOptions;
appName: string;
baseURL: string;
trustedOrigins: string[];
socialProviders: OAuthProvider[];
authCookies: BetterAuthCookies;
logger: ReturnType<typeof createLogger>;
Expand Down Expand Up @@ -190,3 +203,21 @@ function getInternalPlugins(options: BetterAuthOptions) {
}
return plugins;
}

function getTrustedOrigins(options: BetterAuthOptions) {
const baseURL = getBaseURL(options.baseURL, options.basePath);
if (!baseURL) {
throw new BetterAuthError(
"Base URL can not be empty. Please add `BETTER_AUTH_URL` in your environment variables or pass it in your auth config.",
);
}
const trustedOrigins = [new URL(baseURL).origin];
if (options.trustedOrigins) {
trustedOrigins.push(...options.trustedOrigins);
}
const envTrustedOrigins = process.env.BETTER_AUTH_TRUSTED_ORIGINS;
if (envTrustedOrigins) {
trustedOrigins.push(...envTrustedOrigins.split(","));
}
return trustedOrigins;
}
1 change: 1 addition & 0 deletions packages/better-auth/src/test-utils/test-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export async function getTestInstance<
} satisfies BetterAuthOptions;

const auth = betterAuth({
baseURL: "http://localhost:" + (config?.port || 3000),
...opts,
...options,
} as O extends undefined ? typeof opts : O & typeof opts);
Expand Down

0 comments on commit b3b2f5d

Please sign in to comment.