@procedures/better-auth 0.13.2 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/auth.d.ts +3 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +3 -27
- package/dist/auth.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/handler.d.ts +101 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +122 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +10 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +32 -0
- package/dist/options.js.map +1 -0
- package/package.json +7 -3
- package/src/auth.ts +6 -29
- package/src/config.ts +8 -0
- package/src/handler.test.ts +216 -0
- package/src/handler.ts +200 -0
- package/src/index.ts +1 -0
- package/src/options.ts +39 -0
package/README.md
CHANGED
|
@@ -20,13 +20,13 @@ The package has no procedures. The package root registers nothing.
|
|
|
20
20
|
`betterAuthConfig` reads the environment. `createBetterAuth` makes the server. Give Better Auth its own database: its `user` collection must not mix with the data of the app.
|
|
21
21
|
|
|
22
22
|
```ts
|
|
23
|
-
import { betterAuthConfig, createBetterAuth } from "@procedures/better-auth";
|
|
24
|
-
import { toNodeHandler } from "better-auth/node";
|
|
23
|
+
import { betterAuthConfig, betterAuthHandler, createBetterAuth } from "@procedures/better-auth";
|
|
25
24
|
|
|
26
|
-
const
|
|
25
|
+
const origins = ["https://app.example.com"];
|
|
26
|
+
const config = betterAuthConfig(process.env, { port: 9091, trustedOrigins: origins, appName: "Example" });
|
|
27
27
|
if (typeof config === "string") throw new Error(config);
|
|
28
28
|
const auth = createBetterAuth(client.db("example-auth"), client, config);
|
|
29
|
-
app.
|
|
29
|
+
app.use(betterAuthHandler(auth, { allowedOrigins: origins }).middleware); // the routes belong to the app
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
| Variable | Use |
|
|
@@ -37,6 +37,36 @@ app.all("/auth/*path", toNodeHandler(auth)); // the routes belong to the app
|
|
|
37
37
|
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | The sign-in with Google. |
|
|
38
38
|
| `PASSKEY_RP_ID` | The domain of the passkeys. The default is the host of the first trusted origin. |
|
|
39
39
|
| `AUTH_TEST_ACCOUNTS=1` | Accounts with an email and a password, for the tests. Their email counts as verified. Production refuses it. |
|
|
40
|
+
| `AUTH_CROSS_SITE_COOKIES=1` | The cookies get `SameSite=None` and `Secure`, for a page on another site. Refer to [A page on another origin](#a-page-on-another-origin). |
|
|
41
|
+
|
|
42
|
+
### A page on another origin
|
|
43
|
+
|
|
44
|
+
The handler of Better Auth sends no CORS headers. `betterAuthHandler(auth, options)` gives the Node handler of the auth routes with credentialed CORS. Use the `allowedOrigins` of the host, the list of the browser checks of `procedureHandler`. Thus one list of trusted origins drives the procedures and the auth routes.
|
|
45
|
+
|
|
46
|
+
- A response for a trusted origin names that one origin, with `Access-Control-Allow-Credentials: true` and `Vary: Origin`.
|
|
47
|
+
- The handler answers a preflight (`OPTIONS`) with 204. For a trusted origin, it names the methods (`GET`, `POST`) and the headers (`Content-Type`, `Authorization`).
|
|
48
|
+
- An origin that is not trusted gets no CORS header. The CSRF checks of Better Auth also refuse its writes.
|
|
49
|
+
- Each response has `Vary: Origin`, also a response without CORS headers. Thus a shared cache keeps one answer for each origin.
|
|
50
|
+
- The handler refuses `"*"`, because each site could then send the cookies of the user (CSRF).
|
|
51
|
+
- The option `cors` changes the methods, the headers, the exposed headers and `maxAge`. The option `basePath` is `/auth` by default.
|
|
52
|
+
- Mount the handler on the mount list of a listener. For Express, give `handler.middleware` to the app.
|
|
53
|
+
|
|
54
|
+
`betterAuthFace(auth)` gives the same handler as a face of a procedures host (`createProcedureHost()` of `@procedures/peer`). The face takes `browser.allowedOrigins` of the policy of the host. Each request of the routes goes through the request tracking of the host, on the route pattern of the face (`auth *`):
|
|
55
|
+
|
|
56
|
+
- A request after the stop of the intake gets 503, with the CORS headers. Thus the page can read the refusal.
|
|
57
|
+
- The drain waits for a request in flight. Thus a sign-in at the stop writes its session and sends its answer.
|
|
58
|
+
- The readiness of the controller of the host applies: `controller.requires` can name the database of Better Auth.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const policy = hostPolicy({ browser: { allowedOrigins: origins } });
|
|
62
|
+
const host = createProcedureHost({ registry, policy, faces: { http: true, auth: betterAuthFace(auth) }, listen });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The cookies need more for a page on another site, for example `https://app.example.com` and `https://api.other.example`:
|
|
66
|
+
|
|
67
|
+
- A browser sends a cookie to another site only when the cookie has `SameSite=None`. It keeps such a cookie only when it is `Secure`, so the server needs HTTPS (or `localhost`).
|
|
68
|
+
- Set `AUTH_CROSS_SITE_COOKIES=1`, or give `crossSiteCookies: true` in the configuration. The cookies then get `SameSite=None; Secure`.
|
|
69
|
+
- Two ports of one host are the same site, for example the dev ports `localhost:5173` and `localhost:9091`. They need CORS, but not `SameSite=None`.
|
|
40
70
|
|
|
41
71
|
## The browser
|
|
42
72
|
|
|
@@ -63,8 +93,8 @@ if ("url" in out) location.assign(out.url);
|
|
|
63
93
|
|
|
64
94
|
- Each call sends the cookies. The session cookie is `httpOnly`, so a script of the page cannot read it.
|
|
65
95
|
- Give the page and the server one origin. A proxy under the origin of the page also works. This is the simplest form.
|
|
66
|
-
- A server on another origin needs CORS that names exactly one trusted origin, with `Access-Control-Allow-Credentials: true`.
|
|
67
|
-
- A server on another site also needs the cookie attributes `SameSite=None` and `Secure
|
|
96
|
+
- A server on another origin needs CORS that names exactly one trusted origin, with `Access-Control-Allow-Credentials: true`. `betterAuthHandler` sends these headers. Without them, `session()` gives `undefined` and the other calls fail. Refer to [A page on another origin](#a-page-on-another-origin).
|
|
97
|
+
- A server on another site also needs the cookie attributes `SameSite=None` and `Secure` (`AUTH_CROSS_SITE_COOKIES=1`).
|
|
68
98
|
- A refused call gives `{ error }`. The functions do not throw for an answer of the server.
|
|
69
99
|
- The passkeys use `@simplewebauthn/browser`, which loads only when a passkey function operates.
|
|
70
100
|
|