@growth-labs/auth 0.7.0 → 0.7.2

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.
Files changed (43) hide show
  1. package/dist/index.d.ts.map +1 -1
  2. package/dist/index.js +4 -1
  3. package/dist/index.js.map +1 -1
  4. package/package.json +7 -2
  5. package/src/client/login-page.ts +12 -0
  6. package/src/cloudflare-workers.d.ts +3 -0
  7. package/src/config-store.ts +70 -0
  8. package/src/index.ts +177 -0
  9. package/src/middleware/auth.ts +88 -0
  10. package/src/options.ts +75 -0
  11. package/src/renderers.ts +182 -0
  12. package/src/routes/api/code-request.ts +33 -0
  13. package/src/routes/api/code-verify.ts +35 -0
  14. package/src/routes/api/password-reset-confirm.ts +36 -0
  15. package/src/routes/api/password-reset-request.ts +32 -0
  16. package/src/routes/api/password-verify.ts +35 -0
  17. package/src/routes/api/shared.ts +130 -0
  18. package/src/routes/callback.ts +105 -0
  19. package/src/routes/flow.ts +53 -0
  20. package/src/routes/forgot-password.ts +31 -0
  21. package/src/routes/login.ts +130 -0
  22. package/src/routes/logout.ts +59 -0
  23. package/src/routes/password.ts +27 -0
  24. package/src/routes/reset-password.ts +33 -0
  25. package/src/routes/verify-code.ts +28 -0
  26. package/src/runtime-bridge.ts +15 -0
  27. package/src/runtime.ts +5 -0
  28. package/src/server.ts +185 -0
  29. package/src/types.ts +158 -0
  30. package/src/utils/analytics.ts +56 -0
  31. package/src/utils/client-secret.ts +21 -0
  32. package/src/utils/cookies.ts +134 -0
  33. package/src/utils/encoding.ts +5 -0
  34. package/src/utils/env-marker.ts +39 -0
  35. package/src/utils/identity-cookie.ts +138 -0
  36. package/src/utils/identity.ts +240 -0
  37. package/src/utils/index.ts +19 -0
  38. package/src/utils/issuer.ts +7 -0
  39. package/src/utils/openauth.ts +163 -0
  40. package/src/utils/pkce.ts +16 -0
  41. package/src/utils/state.ts +20 -0
  42. package/src/utils/tokens.ts +128 -0
  43. package/src/virtual.d.ts +5 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,UAAU,gBAAgB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QACN,oBAAoB,EAAE,CAAC,MAAM,EAAE;YAC9B,aAAa,EAAE,CAAC,IAAI,EAAE;gBAAE,UAAU,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;aAAE,KAAK,IAAI,CAAA;YAC5E,WAAW,EAAE,CAAC,IAAI,EAAE;gBAAE,OAAO,EAAE,MAAM,CAAC;gBAAC,UAAU,EAAE,MAAM,CAAC;gBAAC,SAAS,CAAC,EAAE,OAAO,CAAA;aAAE,KAAK,IAAI,CAAA;YACzF,YAAY,EAAE,CAAC,MAAM,EAAE;gBACtB,IAAI,CAAC,EAAE;oBAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;oBAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAA;iBAAE,CAAA;aAC/D,KAAK,IAAI,CAAA;SACV,KAAK,IAAI,CAAA;KACV,CAAA;CACD;AAQD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAuBjE;AAWD,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,gBAAgB,CAyGvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,UAAU,gBAAgB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QACN,oBAAoB,EAAE,CAAC,MAAM,EAAE;YAC9B,aAAa,EAAE,CAAC,IAAI,EAAE;gBAAE,UAAU,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;aAAE,KAAK,IAAI,CAAA;YAC5E,WAAW,EAAE,CAAC,IAAI,EAAE;gBAAE,OAAO,EAAE,MAAM,CAAC;gBAAC,UAAU,EAAE,MAAM,CAAC;gBAAC,SAAS,CAAC,EAAE,OAAO,CAAA;aAAE,KAAK,IAAI,CAAA;YACzF,YAAY,EAAE,CAAC,MAAM,EAAE;gBACtB,IAAI,CAAC,EAAE;oBAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;oBAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAA;iBAAE,CAAA;aAC/D,KAAK,IAAI,CAAA;SACV,KAAK,IAAI,CAAA;KACV,CAAA;CACD;AAYD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAuBjE;AAWD,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,gBAAgB,CAyGvE"}
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { _setConfig } from './config-store.js';
2
2
  import { authOptionsSchema } from './options.js';
3
- const ENTRYPOINT_EXTENSION = import.meta.url.endsWith('.ts') ? '.ts' : '.js';
3
+ function isSourceEntrypoint() {
4
+ return typeof import.meta.url === 'string' && import.meta.url.endsWith('.ts');
5
+ }
6
+ const ENTRYPOINT_EXTENSION = isSourceEntrypoint() ? '.ts' : '.js';
4
7
  function resolveEntrypoint(path) {
5
8
  return decodeURIComponent(new URL(`${path}${ENTRYPOINT_EXTENSION}`, import.meta.url).pathname);
6
9
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAgBhD,SAAS,kBAAkB;IAC1B,OAAO,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC9E,CAAC;AAED,MAAM,oBAAoB,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAEjE,SAAS,iBAAiB,CAAC,IAAY;IACtC,OAAO,kBAAkB,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,oBAAoB,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA;AAC/F,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,SAAwB;IACvD,OAAO;QACN,IAAI,EAAE,6BAA6B;QACnC,SAAS,CAAC,EAAU;YACnB,IAAI,EAAE,KAAK,oCAAoC;gBAAE,OAAO,sCAAsC,CAAA;QAC/F,CAAC;QACD,IAAI,CAAC,EAAU;YACd,IAAI,EAAE,KAAK,sCAAsC;gBAAE,OAAM;YAEzD,MAAM,WAAW,GAAa,EAAE,CAAA;YAChC,MAAM,UAAU,GAAa,EAAE,CAAA;YAC/B,IAAI,CAAC,GAAG,CAAC,CAAA;YACT,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBACxC,MAAM,KAAK,GAAG,sBAAsB,CAAC,EAAE,EAAE,CAAA;gBACzC,WAAW,CAAC,IAAI,CACf,YAAY,IAAI,CAAC,MAAM,OAAO,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAC5E,CAAA;gBACD,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,KAAK,GAAG,CAAC,CAAA;YAC3D,CAAC;YACD,OAAO,CAAC,GAAG,WAAW,EAAE,4BAA4B,EAAE,GAAG,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1F,CAAC;KACD,CAAA;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IAC1C,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAQ,KAA8B,CAAC,MAAM,KAAK,QAAQ;QAC1D,OAAQ,KAA8B,CAAC,MAAM,KAAK,QAAQ,CAC1D,CAAA;AACF,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,WAAwB;IACpD,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACpD,UAAU,CAAC,OAAO,CAAC,CAAA;IACnB,MAAM,mBAAmB,GAAG,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAA;IAEzD,OAAO;QACN,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE;YACN,oBAAoB,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,EAAE;gBACtE,YAAY,CAAC;oBACZ,IAAI,EAAE;wBACL,MAAM,EAAE;4BACP,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC;yBACpE;wBACD,OAAO,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;qBAC7C;iBACD,CAAC,CAAA;gBAEF,aAAa,CAAC;oBACb,UAAU,EAAE,iBAAiB,CAAC,mBAAmB,CAAC;oBAClD,KAAK,EAAE,KAAK;iBACZ,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,OAAO,CAAC,SAAS;oBAC1B,UAAU,EAAE,iBAAiB,CAAC,gBAAgB,CAAC;oBAC/C,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,SAAS;oBAClB,UAAU,EAAE,iBAAiB,CAAC,iBAAiB,CAAC;oBAChD,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,OAAO,CAAC,YAAY;oBAC7B,UAAU,EAAE,iBAAiB,CAAC,mBAAmB,CAAC;oBAClD,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;gBAEF,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5C,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,kBAAkB;wBACnC,UAAU,EAAE,iBAAiB,CAAC,0BAA0B,CAAC;wBACzD,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,iBAAiB;wBAClC,UAAU,EAAE,iBAAiB,CAAC,yBAAyB,CAAC;wBACxD,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,kBAAkB;wBACnC,UAAU,EAAE,iBAAiB,CAAC,8BAA8B,CAAC;wBAC7D,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,wBAAwB;wBACzC,UAAU,EAAE,iBAAiB,CAAC,qCAAqC,CAAC;wBACpE,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,wBAAwB;wBACzC,UAAU,EAAE,iBAAiB,CAAC,qCAAqC,CAAC;wBACpE,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;wBAChC,WAAW,CAAC;4BACX,OAAO,EAAE,OAAO,CAAC,YAAY;4BAC7B,UAAU,EAAE,iBAAiB,CAAC,mBAAmB,CAAC;4BAClD,SAAS,EAAE,KAAK;yBAChB,CAAC,CAAA;oBACH,CAAC;gBACF,CAAC;gBAED,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC9C,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,eAAe;wBAChC,UAAU,EAAE,iBAAiB,CAAC,2BAA2B,CAAC;wBAC1D,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,WAAW,CAAC;wBACX,OAAO,EAAE,OAAO,CAAC,cAAc;wBAC/B,UAAU,EAAE,iBAAiB,CAAC,0BAA0B,CAAC;wBACzD,SAAS,EAAE,KAAK;qBAChB,CAAC,CAAA;oBAEF,IAAI,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;wBAClC,WAAW,CAAC;4BACX,OAAO,EAAE,OAAO,CAAC,cAAc;4BAC/B,UAAU,EAAE,iBAAiB,CAAC,sBAAsB,CAAC;4BACrD,SAAS,EAAE,KAAK;yBAChB,CAAC,CAAA;oBACH,CAAC;gBACF,CAAC;YACF,CAAC;SACD;KACD,CAAA;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/auth",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -33,6 +33,11 @@
33
33
  },
34
34
  "files": [
35
35
  "dist",
36
+ "src/**/*.ts",
37
+ "src/**/*.astro",
38
+ "src/**/*.css",
39
+ "src/**/*.md",
40
+ "src/**/*.sql",
36
41
  "README.md"
37
42
  ],
38
43
  "publishConfig": {
@@ -57,7 +62,7 @@
57
62
  "typescript": "^5.8.0",
58
63
  "vite": "^7.3.2",
59
64
  "vitest": "^3.0.0",
60
- "@growth-labs/analytics": "0.4.0"
65
+ "@growth-labs/analytics": "0.4.2"
61
66
  },
62
67
  "scripts": {
63
68
  "build": "tsc",
@@ -0,0 +1,12 @@
1
+ export function loginPageScript(): string {
2
+ return `
3
+ document.querySelectorAll('[data-provider]').forEach(function(el) {
4
+ el.addEventListener('click', function() {
5
+ var provider = el.getAttribute('data-provider');
6
+ if (window.glAnalytics) {
7
+ window.glAnalytics.track('login_clicked', { provider: provider });
8
+ }
9
+ });
10
+ });
11
+ `
12
+ }
@@ -0,0 +1,3 @@
1
+ declare module 'cloudflare:workers' {
2
+ export const env: Record<string, unknown>
3
+ }
@@ -0,0 +1,70 @@
1
+ import type { ResolvedAuthOptions } from './options.js'
2
+ import { isEnvMarker, resolveEnvMarker } from './utils/env-marker.js'
3
+
4
+ let _config: ResolvedAuthOptions | null = null
5
+
6
+ export function _setConfig(config: ResolvedAuthOptions): void {
7
+ _config = config
8
+ }
9
+
10
+ export function getConfig(): ResolvedAuthOptions {
11
+ const runtimeConfig = (
12
+ globalThis as typeof globalThis & {
13
+ __GL_AUTH_CONFIG__?: ResolvedAuthOptions
14
+ }
15
+ ).__GL_AUTH_CONFIG__
16
+ const base = runtimeConfig ?? _config
17
+ if (!base) {
18
+ throw new Error(
19
+ '@growth-labs/auth: integration not configured. Add auth() to your astro.config.mjs integrations array.',
20
+ )
21
+ }
22
+ return resolveEnvMarkers(base)
23
+ }
24
+
25
+ /**
26
+ * Resolves any `"env:VAR_NAME"` markers on auth-tuple fields against the
27
+ * runtime env stashed by `src/runtime-bridge.ts`. The bridge is loaded
28
+ * via `middleware/auth.ts` at module-init time, so by the time any
29
+ * request reaches `getConfig()` the env is on globalThis. Plain string
30
+ * values pass through unchanged, preserving backwards compatibility.
31
+ *
32
+ * If callers exist that don't go through the auth middleware first AND
33
+ * the config has markers, we throw a clear error rather than silently
34
+ * dropping the lookup.
35
+ */
36
+ function resolveEnvMarkers(base: ResolvedAuthOptions): ResolvedAuthOptions {
37
+ const env = (
38
+ globalThis as typeof globalThis & {
39
+ __GL_AUTH_RUNTIME_ENV__?: Record<string, unknown>
40
+ }
41
+ ).__GL_AUTH_RUNTIME_ENV__
42
+ if (env === undefined) {
43
+ if (anyMarkerPresent(base)) {
44
+ throw new Error(
45
+ '@growth-labs/auth: runtime env unavailable for "env:" marker resolution. Ensure the auth middleware ran first (it loads src/runtime-bridge.ts which stashes the env on globalThis).',
46
+ )
47
+ }
48
+ return base
49
+ }
50
+ const issuer = resolveEnvMarker(base.issuer, env)
51
+ if (typeof issuer !== 'string') {
52
+ throw new Error('@growth-labs/auth: issuer must resolve to a string')
53
+ }
54
+ return {
55
+ ...base,
56
+ issuer,
57
+ issuerInternal: resolveEnvMarker(base.issuerInternal, env),
58
+ clientId: resolveEnvMarker(base.clientId, env),
59
+ resource: resolveEnvMarker(base.resource, env),
60
+ }
61
+ }
62
+
63
+ function anyMarkerPresent(base: ResolvedAuthOptions): boolean {
64
+ return (
65
+ isEnvMarker(base.issuer) ||
66
+ isEnvMarker(base.issuerInternal) ||
67
+ isEnvMarker(base.clientId) ||
68
+ isEnvMarker(base.resource)
69
+ )
70
+ }
package/src/index.ts ADDED
@@ -0,0 +1,177 @@
1
+ import { _setConfig } from './config-store.js'
2
+ import type { AuthOptions } from './options.js'
3
+ import { authOptionsSchema } from './options.js'
4
+ import type { AuthRenderers } from './types.js'
5
+
6
+ interface AstroIntegration {
7
+ name: string
8
+ hooks: {
9
+ 'astro:config:setup': (params: {
10
+ addMiddleware: (opts: { entrypoint: string; order: 'pre' | 'post' }) => void
11
+ injectRoute: (opts: { pattern: string; entrypoint: string; prerender?: boolean }) => void
12
+ updateConfig: (config: {
13
+ vite?: { define?: Record<string, string>; plugins?: unknown[] }
14
+ }) => void
15
+ }) => void
16
+ }
17
+ }
18
+
19
+ function isSourceEntrypoint(): boolean {
20
+ return typeof import.meta.url === 'string' && import.meta.url.endsWith('.ts')
21
+ }
22
+
23
+ const ENTRYPOINT_EXTENSION = isSourceEntrypoint() ? '.ts' : '.js'
24
+
25
+ function resolveEntrypoint(path: string): string {
26
+ return decodeURIComponent(new URL(`${path}${ENTRYPOINT_EXTENSION}`, import.meta.url).pathname)
27
+ }
28
+
29
+ /**
30
+ * Vite plugin that turns the integration's `renderers` option (per-surface
31
+ * `{ module, export }` specs) into the `virtual:growth-labs/auth/renderers`
32
+ * module by emitting REAL static ES imports — NOT a serialized function
33
+ * body. Static imports are bundleable, tree-shakeable, and immune to the
34
+ * SSR-transform bug that crashed 0.3.6 (where Vite rewrote `await import()`
35
+ * inside a `Function.prototype.toString()`-serialized renderer body to
36
+ * `__vite_ssr_dynamic_import__()`, a helper missing in production bundles).
37
+ */
38
+ export function renderersPlugin(renderers: AuthRenderers): unknown {
39
+ return {
40
+ name: '@growth-labs/auth:renderers',
41
+ resolveId(id: string) {
42
+ if (id === 'virtual:growth-labs/auth/renderers') return '\0virtual:growth-labs/auth/renderers'
43
+ },
44
+ load(id: string) {
45
+ if (id !== '\0virtual:growth-labs/auth/renderers') return
46
+
47
+ const importLines: string[] = []
48
+ const mapEntries: string[] = []
49
+ let n = 0
50
+ for (const [surface, spec] of Object.entries(renderers)) {
51
+ if (!isValidRendererSpec(spec)) continue
52
+ const local = `__gl_auth_renderer_${n++}`
53
+ importLines.push(
54
+ `import { ${spec.export} as ${local} } from ${JSON.stringify(spec.module)};`,
55
+ )
56
+ mapEntries.push(` ${JSON.stringify(surface)}: ${local},`)
57
+ }
58
+ return [...importLines, 'export const renderers = {', ...mapEntries, '};', ''].join('\n')
59
+ },
60
+ }
61
+ }
62
+
63
+ function isValidRendererSpec(value: unknown): value is { module: string; export: string } {
64
+ return (
65
+ typeof value === 'object' &&
66
+ value !== null &&
67
+ typeof (value as { module?: unknown }).module === 'string' &&
68
+ typeof (value as { export?: unknown }).export === 'string'
69
+ )
70
+ }
71
+
72
+ export default function auth(userOptions: AuthOptions): AstroIntegration {
73
+ const options = authOptionsSchema.parse(userOptions)
74
+ _setConfig(options)
75
+ const serializableOptions = { ...options, renderers: {} }
76
+
77
+ return {
78
+ name: '@growth-labs/auth',
79
+ hooks: {
80
+ 'astro:config:setup': ({ addMiddleware, injectRoute, updateConfig }) => {
81
+ updateConfig({
82
+ vite: {
83
+ define: {
84
+ 'globalThis.__GL_AUTH_CONFIG__': JSON.stringify(serializableOptions),
85
+ },
86
+ plugins: [renderersPlugin(options.renderers)],
87
+ },
88
+ })
89
+
90
+ addMiddleware({
91
+ entrypoint: resolveEntrypoint('./middleware/auth'),
92
+ order: 'pre',
93
+ })
94
+
95
+ injectRoute({
96
+ pattern: options.loginPath,
97
+ entrypoint: resolveEntrypoint('./routes/login'),
98
+ prerender: false,
99
+ })
100
+
101
+ injectRoute({
102
+ pattern: '/logout',
103
+ entrypoint: resolveEntrypoint('./routes/logout'),
104
+ prerender: false,
105
+ })
106
+
107
+ injectRoute({
108
+ pattern: options.callbackPath,
109
+ entrypoint: resolveEntrypoint('./routes/callback'),
110
+ prerender: false,
111
+ })
112
+
113
+ if (options.providers.includes('password')) {
114
+ injectRoute({
115
+ pattern: options.forgotPasswordPath,
116
+ entrypoint: resolveEntrypoint('./routes/forgot-password'),
117
+ prerender: false,
118
+ })
119
+
120
+ injectRoute({
121
+ pattern: options.resetPasswordPath,
122
+ entrypoint: resolveEntrypoint('./routes/reset-password'),
123
+ prerender: false,
124
+ })
125
+
126
+ injectRoute({
127
+ pattern: options.passwordVerifyPath,
128
+ entrypoint: resolveEntrypoint('./routes/api/password-verify'),
129
+ prerender: false,
130
+ })
131
+
132
+ injectRoute({
133
+ pattern: options.passwordResetRequestPath,
134
+ entrypoint: resolveEntrypoint('./routes/api/password-reset-request'),
135
+ prerender: false,
136
+ })
137
+
138
+ injectRoute({
139
+ pattern: options.passwordResetConfirmPath,
140
+ entrypoint: resolveEntrypoint('./routes/api/password-reset-confirm'),
141
+ prerender: false,
142
+ })
143
+
144
+ if (options.renderers.password) {
145
+ injectRoute({
146
+ pattern: options.passwordPath,
147
+ entrypoint: resolveEntrypoint('./routes/password'),
148
+ prerender: false,
149
+ })
150
+ }
151
+ }
152
+
153
+ if (options.providers.includes('email-code')) {
154
+ injectRoute({
155
+ pattern: options.codeRequestPath,
156
+ entrypoint: resolveEntrypoint('./routes/api/code-request'),
157
+ prerender: false,
158
+ })
159
+
160
+ injectRoute({
161
+ pattern: options.codeVerifyPath,
162
+ entrypoint: resolveEntrypoint('./routes/api/code-verify'),
163
+ prerender: false,
164
+ })
165
+
166
+ if (options.renderers.verifyCode) {
167
+ injectRoute({
168
+ pattern: options.verifyCodePath,
169
+ entrypoint: resolveEntrypoint('./routes/verify-code'),
170
+ prerender: false,
171
+ })
172
+ }
173
+ }
174
+ },
175
+ },
176
+ }
177
+ }
@@ -0,0 +1,88 @@
1
+ import { getConfig } from '../config-store.js'
2
+ import '../runtime-bridge.js'
3
+ import type { User } from '../types.js'
4
+ import { resolveClientSecret } from '../utils/client-secret.js'
5
+ import { getCookie, setTokenCookies } from '../utils/cookies.js'
6
+ import { resolveInternalIssuer } from '../utils/issuer.js'
7
+ import { refreshTokens, verifyAccessToken } from '../utils/tokens.js'
8
+
9
+ export async function onRequest(
10
+ context: { request: Request; url: URL; locals: Record<string, unknown> },
11
+ next: () => Promise<Response>,
12
+ ): Promise<Response> {
13
+ const options = getConfig()
14
+ const issuer = resolveInternalIssuer(options)
15
+ const { request } = context
16
+
17
+ // 1. Read tokens from cookies
18
+ const accessToken = getCookie(request, `${options.cookiePrefix}_at`)
19
+ const refreshToken = getCookie(request, `${options.cookiePrefix}_rt`)
20
+
21
+ // 2. Attempt to authenticate
22
+ let user: User | null = null
23
+ let refreshed: Awaited<ReturnType<typeof refreshTokens>> = null
24
+
25
+ if (accessToken) {
26
+ const verified = await verifyAccessToken(issuer, accessToken)
27
+ if (verified) {
28
+ user = {
29
+ id: verified.sub,
30
+ email: verified.email,
31
+ name: verified.name ?? null,
32
+ avatarUrl: verified.image ?? null,
33
+ }
34
+ }
35
+ }
36
+
37
+ if (!user && refreshToken) {
38
+ const clientId = options.clientId || context.url.hostname
39
+ const clientSecret = resolveClientSecret(options.clientSecret)
40
+ refreshed = await refreshTokens(issuer, refreshToken, clientId, clientSecret, options.resource)
41
+ if (refreshed) {
42
+ user = {
43
+ id: refreshed.claims.sub,
44
+ email: refreshed.claims.email,
45
+ name: refreshed.claims.name ?? null,
46
+ avatarUrl: refreshed.claims.image ?? null,
47
+ }
48
+ }
49
+ }
50
+
51
+ // 3. Populate context.locals.user
52
+ context.locals.user = user
53
+
54
+ // 4. Gate protected paths
55
+ if (!user && isGatedPath(context.url.pathname, options.gatedPaths)) {
56
+ const loginUrl = new URL(
57
+ `${options.loginPath}?redirect=${encodeURIComponent(context.url.pathname)}`,
58
+ context.url.origin,
59
+ )
60
+ return Response.redirect(loginUrl.toString(), 302)
61
+ }
62
+
63
+ // 5. Continue to the page
64
+ const response = await next()
65
+
66
+ // 6. If tokens were refreshed, set new cookies on the response
67
+ if (refreshed) {
68
+ const modifiedResponse = new Response(response.body, {
69
+ status: response.status,
70
+ statusText: response.statusText,
71
+ headers: new Headers(response.headers),
72
+ })
73
+ setTokenCookies(modifiedResponse, options, refreshed.accessToken, refreshed.refreshToken)
74
+ return modifiedResponse
75
+ }
76
+
77
+ return response
78
+ }
79
+
80
+ function isGatedPath(pathname: string, gatedPaths: string[]): boolean {
81
+ return gatedPaths.some((pattern) => {
82
+ if (pattern.endsWith('/*')) {
83
+ const prefix = pattern.slice(0, -1) // '/premium/*' → '/premium/'
84
+ return pathname.startsWith(prefix)
85
+ }
86
+ return pathname === pattern
87
+ })
88
+ }
package/src/options.ts ADDED
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod'
2
+ import type { AuthRenderers } from './types.js'
3
+
4
+ // String accepted as either a literal URL or an "env:VAR_NAME" marker that
5
+ // gets resolved against the Worker runtime env at request time. See
6
+ // `src/utils/env-marker.ts` and `src/config-store.ts`. Bare "env:" (no
7
+ // binding name) is rejected — it can never resolve to anything useful.
8
+ const urlOrEnvMarker = z
9
+ .string()
10
+ .refine((v) => (v.startsWith('env:') && v.length > 4) || /^https?:\/\//i.test(v), {
11
+ message: 'Must be a URL (https?://...) or an "env:VAR_NAME" marker',
12
+ })
13
+
14
+ // String that, if shaped as an "env:VAR_NAME" marker, must include a
15
+ // non-empty binding name. Literal values pass through unconstrained
16
+ // (they can be any string, e.g. OAuth client IDs). A literal value that
17
+ // happens to start with the reserved "env:" prefix will be treated as a
18
+ // marker — pick a non-colliding name in that edge case.
19
+ const stringOrEnvMarker = z.string().refine((v) => !v.startsWith('env:') || v.length > 4, {
20
+ message: '"env:" marker must include a binding name (e.g. "env:AUTH_CLIENT_ID")',
21
+ })
22
+
23
+ export const authOptionsSchema = z.object({
24
+ // ─── Issuer URLs ───
25
+ issuer: urlOrEnvMarker,
26
+ issuerInternal: urlOrEnvMarker.optional(),
27
+
28
+ // ─── Client identity ───
29
+ clientId: stringOrEnvMarker.optional(),
30
+ clientSecret: z.string().optional(),
31
+ resource: urlOrEnvMarker.optional(),
32
+
33
+ // ─── Cookie configuration ───
34
+ cookiePrefix: z.string(),
35
+ sessionCookieDomain: z.string().optional(),
36
+
37
+ // ─── Token lifetimes ───
38
+ accessTokenMaxAge: z.number().default(900),
39
+ refreshTokenMaxAge: z.number().default(2592000),
40
+
41
+ // ─── Path configuration ───
42
+ gatedPaths: z.array(z.string()).default([]),
43
+ loginPath: z.string().default('/login'),
44
+ logoutRedirect: z.string().default('/'),
45
+ callbackPath: z.string().default('/api/auth/callback'),
46
+ passwordPath: z.string().default('/password'),
47
+ verifyCodePath: z.string().default('/verify-code'),
48
+ forgotPasswordPath: z.string().default('/forgot-password'),
49
+ resetPasswordPath: z.string().default('/reset-password'),
50
+ passwordVerifyPath: z.string().default('/api/auth/password/verify'),
51
+ codeRequestPath: z.string().default('/api/auth/code/request'),
52
+ codeVerifyPath: z.string().default('/api/auth/code/verify'),
53
+ passwordResetRequestPath: z.string().default('/api/auth/password/reset/request'),
54
+ passwordResetConfirmPath: z.string().default('/api/auth/password/reset/confirm'),
55
+
56
+ // ─── Providers ───
57
+ providers: z
58
+ .array(z.enum(['google', 'password', 'email-code']))
59
+ .default(['google', 'password', 'email-code']),
60
+
61
+ // ─── Login page customization ───
62
+ loginPage: z
63
+ .object({
64
+ title: z.string().default('Sign in'),
65
+ brandName: z.string().optional(),
66
+ logoUrl: z.string().optional(),
67
+ })
68
+ .default({}),
69
+
70
+ // ─── Consumer-owned UI renderers ───
71
+ renderers: z.custom<AuthRenderers>().default({}),
72
+ })
73
+
74
+ export type AuthOptions = z.input<typeof authOptionsSchema>
75
+ export type ResolvedAuthOptions = z.output<typeof authOptionsSchema>
@@ -0,0 +1,182 @@
1
+ import { renderers as bundledRenderers } from 'virtual:growth-labs/auth/renderers'
2
+ import type {
3
+ AuthRendererBrand,
4
+ AuthRendererResult,
5
+ ForgotPasswordRendererPayload,
6
+ LoginRendererPayload,
7
+ PasswordRendererPayload,
8
+ ResetPasswordRendererPayload,
9
+ ResolvedAuthRenderers,
10
+ VerifyCodeRendererPayload,
11
+ } from './types.js'
12
+
13
+ /**
14
+ * Look up the bundled renderer for a surface. After 0.3.7 the lookup is
15
+ * build-time only — renderers are resolved into the virtual module by the
16
+ * Vite plugin via real static `import` statements. The runtime fallback
17
+ * that previously read `options.renderers?.[surface]` is gone; it could
18
+ * never have worked in production (functions captured in `astro.config.mjs`
19
+ * don't survive serialization), and the new `AuthRenderers` shape is a
20
+ * `{ module, export }` spec rather than a function anyway.
21
+ */
22
+ export function getRenderer<K extends keyof ResolvedAuthRenderers>(
23
+ surface: K,
24
+ ): ResolvedAuthRenderers[K] | undefined {
25
+ return bundledRenderers[surface]
26
+ }
27
+
28
+ export async function renderHtmlResponse(result: AuthRendererResult): Promise<Response> {
29
+ const rendered = await result
30
+ if (rendered instanceof Response) {
31
+ return rendered
32
+ }
33
+ return new Response(rendered, {
34
+ headers: { 'Content-Type': 'text/html; charset=utf-8' },
35
+ })
36
+ }
37
+
38
+ export function rendererBrand(options: {
39
+ loginPage: { title: string; brandName?: string; logoUrl?: string }
40
+ }): AuthRendererBrand {
41
+ return {
42
+ title: options.loginPage.title,
43
+ brandName: options.loginPage.brandName ?? '',
44
+ logoUrl: options.loginPage.logoUrl ?? '',
45
+ }
46
+ }
47
+
48
+ export function loginRendererPayload(
49
+ options: {
50
+ loginPage: { title: string; brandName?: string; logoUrl?: string }
51
+ loginPath: string
52
+ passwordPath: string
53
+ verifyCodePath: string
54
+ providers: string[]
55
+ },
56
+ data: {
57
+ redirectPath: string
58
+ error: string | null
59
+ reset: string | null
60
+ useLocalPassword?: boolean
61
+ useLocalVerifyCode?: boolean
62
+ },
63
+ ): LoginRendererPayload {
64
+ const makeLoginStartUrl = (provider: string) =>
65
+ `${options.loginPath}?provider=${encodeURIComponent(provider)}&redirect=${encodeURIComponent(data.redirectPath)}`
66
+ const makeSurfaceUrl = (path: string) =>
67
+ `${path}?redirect=${encodeURIComponent(data.redirectPath)}`
68
+
69
+ return {
70
+ providerUrls: {
71
+ google: options.providers.includes('google') ? makeLoginStartUrl('google') : undefined,
72
+ password: options.providers.includes('password')
73
+ ? data.useLocalPassword
74
+ ? makeSurfaceUrl(options.passwordPath)
75
+ : makeLoginStartUrl('password')
76
+ : undefined,
77
+ emailCode: options.providers.includes('email-code')
78
+ ? data.useLocalVerifyCode
79
+ ? makeSurfaceUrl(options.verifyCodePath)
80
+ : makeLoginStartUrl('email-code')
81
+ : undefined,
82
+ },
83
+ errorCode: data.error ?? undefined,
84
+ reset: data.reset ? true : undefined,
85
+ redirect: data.redirectPath,
86
+ brand: rendererBrand(options),
87
+ }
88
+ }
89
+
90
+ export function forgotPasswordRendererPayload(
91
+ options: {
92
+ loginPage: { title: string; brandName?: string; logoUrl?: string }
93
+ loginPath: string
94
+ passwordResetRequestPath: string
95
+ },
96
+ data: {
97
+ forgotPasswordUrl: string
98
+ error: string | null
99
+ sent: string | null
100
+ },
101
+ ): ForgotPasswordRendererPayload {
102
+ return {
103
+ forgotPasswordUrl: data.forgotPasswordUrl,
104
+ passwordResetRequestUrl: options.passwordResetRequestPath,
105
+ errorCode: data.error ?? undefined,
106
+ sent: data.sent ? true : undefined,
107
+ loginUrl: options.loginPath,
108
+ brand: rendererBrand(options),
109
+ }
110
+ }
111
+
112
+ export function resetPasswordRendererPayload(
113
+ options: {
114
+ loginPage: { title: string; brandName?: string; logoUrl?: string }
115
+ loginPath: string
116
+ passwordResetConfirmPath: string
117
+ },
118
+ data: {
119
+ resetPasswordUrl: string
120
+ error: string | null
121
+ token: string | null
122
+ },
123
+ ): ResetPasswordRendererPayload {
124
+ return {
125
+ resetPasswordUrl: data.resetPasswordUrl,
126
+ passwordResetConfirmUrl: options.passwordResetConfirmPath,
127
+ errorCode: data.error ?? undefined,
128
+ token: data.token ?? undefined,
129
+ loginUrl: options.loginPath,
130
+ brand: rendererBrand(options),
131
+ }
132
+ }
133
+
134
+ export function passwordRendererPayload(
135
+ options: {
136
+ loginPage: { title: string; brandName?: string; logoUrl?: string }
137
+ loginPath: string
138
+ forgotPasswordPath: string
139
+ passwordVerifyPath: string
140
+ },
141
+ data: {
142
+ email: string | null
143
+ error: string | null
144
+ redirectPath: string
145
+ },
146
+ ): PasswordRendererPayload {
147
+ return {
148
+ passwordVerifyUrl: options.passwordVerifyPath,
149
+ forgotPasswordUrl: options.forgotPasswordPath,
150
+ email: data.email ?? undefined,
151
+ errorCode: data.error ?? undefined,
152
+ redirect: data.redirectPath,
153
+ loginUrl: options.loginPath,
154
+ brand: rendererBrand(options),
155
+ }
156
+ }
157
+
158
+ export function verifyCodeRendererPayload(
159
+ options: {
160
+ loginPage: { title: string; brandName?: string; logoUrl?: string }
161
+ loginPath: string
162
+ codeRequestPath: string
163
+ codeVerifyPath: string
164
+ },
165
+ data: {
166
+ email: string | null
167
+ error: string | null
168
+ sent: string | null
169
+ redirectPath: string
170
+ },
171
+ ): VerifyCodeRendererPayload {
172
+ return {
173
+ codeRequestUrl: options.codeRequestPath,
174
+ codeVerifyUrl: options.codeVerifyPath,
175
+ email: data.email ?? undefined,
176
+ errorCode: data.error ?? undefined,
177
+ sent: data.sent ? true : undefined,
178
+ redirect: data.redirectPath,
179
+ loginUrl: options.loginPath,
180
+ brand: rendererBrand(options),
181
+ }
182
+ }