@growth-labs/auth 0.1.3 → 0.2.0

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 (40) hide show
  1. package/README.md +132 -34
  2. package/dist/client/login-page.d.ts +16 -1
  3. package/dist/client/login-page.d.ts.map +1 -1
  4. package/dist/client/login-page.js +20 -1
  5. package/dist/client/login-page.js.map +1 -1
  6. package/dist/middleware/auth.js +2 -2
  7. package/dist/middleware/auth.js.map +1 -1
  8. package/dist/routes/callback.d.ts.map +1 -1
  9. package/dist/routes/callback.js +27 -4
  10. package/dist/routes/callback.js.map +1 -1
  11. package/dist/routes/forgot-password.d.ts +12 -1
  12. package/dist/routes/forgot-password.d.ts.map +1 -1
  13. package/dist/routes/forgot-password.js +14 -54
  14. package/dist/routes/forgot-password.js.map +1 -1
  15. package/dist/routes/login.d.ts.map +1 -1
  16. package/dist/routes/login.js +21 -27
  17. package/dist/routes/login.js.map +1 -1
  18. package/dist/routes/reset-password.d.ts +10 -0
  19. package/dist/routes/reset-password.d.ts.map +1 -1
  20. package/dist/routes/reset-password.js +12 -44
  21. package/dist/routes/reset-password.js.map +1 -1
  22. package/dist/types.d.ts +18 -14
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/utils/cookies.d.ts +18 -0
  25. package/dist/utils/cookies.d.ts.map +1 -1
  26. package/dist/utils/cookies.js +27 -0
  27. package/dist/utils/cookies.js.map +1 -1
  28. package/dist/utils/index.d.ts +4 -2
  29. package/dist/utils/index.d.ts.map +1 -1
  30. package/dist/utils/index.js +3 -1
  31. package/dist/utils/index.js.map +1 -1
  32. package/dist/utils/openauth.d.ts +50 -5
  33. package/dist/utils/openauth.d.ts.map +1 -1
  34. package/dist/utils/openauth.js +70 -18
  35. package/dist/utils/openauth.js.map +1 -1
  36. package/dist/utils/tokens.d.ts +5 -8
  37. package/dist/utils/tokens.d.ts.map +1 -1
  38. package/dist/utils/tokens.js +54 -24
  39. package/dist/utils/tokens.js.map +1 -1
  40. package/package.json +74 -58
@@ -1,27 +1,49 @@
1
- import { createLocalJWKSet, jwtVerify } from 'jose';
1
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
2
2
  const jwksCache = new Map();
3
- async function getJWKS(issuer) {
3
+ function getJWKS(issuer) {
4
4
  let jwks = jwksCache.get(issuer);
5
5
  if (jwks)
6
6
  return jwks;
7
- const response = await fetch(`${issuer}/.well-known/jwks.json`);
8
- if (!response.ok)
9
- throw new Error(`JWKS fetch failed: ${response.status}`);
10
- const data = (await response.json());
11
- jwks = createLocalJWKSet(data);
7
+ const jwksUrl = new URL('/.well-known/jwks.json', issuer);
8
+ jwks = createRemoteJWKSet(jwksUrl);
12
9
  jwksCache.set(issuer, jwks);
13
10
  return jwks;
14
11
  }
12
+ /**
13
+ * Extract subject claims from an OpenAuth-issued JWT payload.
14
+ *
15
+ * OpenAuth places the subject payload (defined by the issuer's `subjects`
16
+ * schema) under `properties` in the access token. The standalone
17
+ * identity-platform issuer's subject contains:
18
+ * - userId, email, name, image, isNewUser
19
+ *
20
+ * The JWT's top-level `sub` is `{type}:{sha1-prefix}` (an OpenAuth-internal
21
+ * subject hash, NOT the user ID). Always read the user ID from
22
+ * `properties.userId`.
23
+ */
24
+ function extractClaims(payload) {
25
+ const propsCandidate = payload.properties;
26
+ const props = propsCandidate && typeof propsCandidate === 'object'
27
+ ? propsCandidate
28
+ : {};
29
+ const userId = typeof props.userId === 'string' ? props.userId : null;
30
+ const email = typeof props.email === 'string' ? props.email : null;
31
+ if (!userId || !email) {
32
+ return null;
33
+ }
34
+ return {
35
+ userId,
36
+ email,
37
+ name: typeof props.name === 'string' ? props.name : undefined,
38
+ image: typeof props.image === 'string' ? props.image : undefined,
39
+ isNewUser: typeof props.isNewUser === 'boolean' ? props.isNewUser : undefined,
40
+ };
41
+ }
15
42
  export async function verifyAccessToken(issuer, token) {
16
43
  try {
17
- const jwks = await getJWKS(issuer);
44
+ const jwks = getJWKS(issuer);
18
45
  const { payload } = await jwtVerify(token, jwks, { issuer });
19
- return {
20
- sub: payload.sub,
21
- email: payload.email,
22
- name: payload.name,
23
- image: payload.image,
24
- };
46
+ return extractClaims(payload);
25
47
  }
26
48
  catch (err) {
27
49
  console.error('verifyAccessToken error:', err);
@@ -36,7 +58,8 @@ export async function refreshTokens(issuer, refreshToken, clientId) {
36
58
  });
37
59
  if (clientId)
38
60
  params.set('client_id', clientId);
39
- const response = await fetch(`${issuer}/token`, {
61
+ const tokenUrl = new URL('/token', issuer).toString();
62
+ const response = await fetch(tokenUrl, {
40
63
  method: 'POST',
41
64
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
42
65
  body: params.toString(),
@@ -44,16 +67,15 @@ export async function refreshTokens(issuer, refreshToken, clientId) {
44
67
  if (!response.ok)
45
68
  return null;
46
69
  const data = (await response.json());
47
- const claims = decodeJwtPayload(data.access_token);
70
+ if (!data.access_token || !data.refresh_token)
71
+ return null;
72
+ const claims = extractClaims(decodeJwtPayload(data.access_token));
73
+ if (!claims)
74
+ return null;
48
75
  return {
49
76
  accessToken: data.access_token,
50
77
  refreshToken: data.refresh_token,
51
- claims: {
52
- sub: claims.sub,
53
- email: claims.email,
54
- name: claims.name,
55
- image: claims.image,
56
- },
78
+ claims,
57
79
  };
58
80
  }
59
81
  catch {
@@ -64,9 +86,17 @@ export function decodeJwtPayload(jwt) {
64
86
  const parts = jwt.split('.');
65
87
  if (parts.length !== 3)
66
88
  return {};
67
- const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
68
- return JSON.parse(atob(payload));
89
+ const padded = parts[1].replace(/-/g, '+').replace(/_/g, '/');
90
+ try {
91
+ return JSON.parse(atob(padded));
92
+ }
93
+ catch {
94
+ return {};
95
+ }
69
96
  }
97
+ /**
98
+ * Exposed for tests so cached JWKS sets can be reset between cases.
99
+ */
70
100
  export function _resetJwksCache() {
71
101
  jwksCache.clear();
72
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,59 +1,75 @@
1
1
  {
2
- "name": "@growth-labs/auth",
3
- "version": "0.1.3",
4
- "type": "module",
5
- "exports": {
6
- ".": {
7
- "types": "./dist/index.d.ts",
8
- "import": "./dist/index.js"
9
- },
10
- "./utils": {
11
- "types": "./dist/utils/index.d.ts",
12
- "import": "./dist/utils/index.js"
13
- },
14
- "./middleware/*": {
15
- "types": "./dist/middleware/*.d.ts",
16
- "import": "./dist/middleware/*.js"
17
- },
18
- "./routes/*": {
19
- "types": "./dist/routes/*.d.ts",
20
- "import": "./dist/routes/*.js"
21
- },
22
- "./types": {
23
- "types": "./dist/types.d.ts",
24
- "import": "./dist/types.js"
25
- }
26
- },
27
- "files": [
28
- "dist",
29
- "README.md"
30
- ],
31
- "publishConfig": {
32
- "access": "public",
33
- "registry": "https://registry.npmjs.org/"
34
- },
35
- "scripts": {
36
- "build": "tsc",
37
- "test": "vitest run",
38
- "test:watch": "vitest"
39
- },
40
- "peerDependencies": {
41
- "astro": "^6.0.0",
42
- "@growth-labs/analytics": "^0.1.0"
43
- },
44
- "peerDependenciesMeta": {
45
- "@growth-labs/analytics": {
46
- "optional": true
47
- }
48
- },
49
- "dependencies": {
50
- "zod": "^3.23.0",
51
- "jose": "^6.0.0"
52
- },
53
- "devDependencies": {
54
- "@growth-labs/analytics": "workspace:*",
55
- "astro": "^6.0.0",
56
- "typescript": "^5.8.0",
57
- "vitest": "^3.0.0"
58
- }
59
- }
2
+ "name": "@growth-labs/auth",
3
+ "version": "0.2.0",
4
+ "description": "OpenAuth client package for Astro + Cloudflare. Verifies JWTs, manages session cookies, gates protected paths, and injects login/logout/callback routes.",
5
+ "keywords": [
6
+ "astro",
7
+ "astro-integration",
8
+ "openauth",
9
+ "oauth",
10
+ "cloudflare-workers",
11
+ "auth"
12
+ ],
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/growth-labs/platform.git",
17
+ "directory": "packages/auth"
18
+ },
19
+ "homepage": "https://github.com/growth-labs/platform/tree/main/packages/auth#readme",
20
+ "publishConfig": {
21
+ "access": "public",
22
+ "registry": "https://registry.npmjs.org/"
23
+ },
24
+ "type": "module",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js"
29
+ },
30
+ "./utils": {
31
+ "types": "./dist/utils/index.d.ts",
32
+ "import": "./dist/utils/index.js"
33
+ },
34
+ "./middleware/*": {
35
+ "types": "./dist/middleware/*.d.ts",
36
+ "import": "./dist/middleware/*.js"
37
+ },
38
+ "./routes/*": {
39
+ "types": "./dist/routes/*.d.ts",
40
+ "import": "./dist/routes/*.js"
41
+ },
42
+ "./types": {
43
+ "types": "./dist/types.d.ts",
44
+ "import": "./dist/types.js"
45
+ }
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "README.md"
50
+ ],
51
+ "peerDependencies": {
52
+ "astro": "^6.0.0",
53
+ "@growth-labs/analytics": "^0.1.0"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@growth-labs/analytics": {
57
+ "optional": true
58
+ }
59
+ },
60
+ "dependencies": {
61
+ "zod": "^3.23.0",
62
+ "jose": "^6.0.0"
63
+ },
64
+ "devDependencies": {
65
+ "astro": "^6.0.0",
66
+ "typescript": "^5.8.0",
67
+ "vitest": "^3.0.0",
68
+ "@growth-labs/analytics": "0.1.3"
69
+ },
70
+ "scripts": {
71
+ "build": "tsc",
72
+ "test": "vitest run",
73
+ "test:watch": "vitest"
74
+ }
75
+ }