@baseworks/auth 0.2.1 → 0.2.3

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.
@@ -1,3 +1,6 @@
1
+ import {
2
+ parseJwtPayload
3
+ } from "./chunk-OD5XLL3O.js";
1
4
  import {
2
5
  generatePkce
3
6
  } from "./chunk-34E5PYNA.js";
@@ -69,10 +72,6 @@ async function discoverOidc() {
69
72
  if (!response.ok) throw new Error(`Failed to load OIDC discovery document from ${issuer}.`);
70
73
  return await response.json();
71
74
  }
72
- function parseJwtPayload(token) {
73
- const part = token.split(".")[1] ?? "";
74
- return JSON.parse(base64urlDecodeString(part));
75
- }
76
75
  function encodeSessionCookie(session) {
77
76
  return base64urlEncode(new TextEncoder().encode(JSON.stringify(session)));
78
77
  }
@@ -187,7 +186,7 @@ function sessionFromPayload(payload) {
187
186
  }
188
187
  function applyTokenCookies(response, request, tokens) {
189
188
  const options = getCookieOptions(request);
190
- const payload = parseJwtPayload(tokens.id_token);
189
+ const payload = parseJwtPayload(tokens.id_token) ?? {};
191
190
  const expiresAt = payload.exp ?? (tokens.expires_in ? Math.floor(Date.now() / 1e3) + tokens.expires_in : void 0);
192
191
  if (!expiresAt) throw new Error("The OIDC ID token did not include an expiry.");
193
192
  response.cookies.set(oidcCookies.idToken, tokens.id_token, {
@@ -268,7 +267,7 @@ async function handleAuthorizationCallback(request) {
268
267
  redirectUri: getRedirectUri(request),
269
268
  tokenEndpoint: discovery.token_endpoint
270
269
  });
271
- const payload = parseJwtPayload(tokens.id_token);
270
+ const payload = parseJwtPayload(tokens.id_token) ?? {};
272
271
  if (savedNonce && payload.nonce && payload.nonce !== savedNonce) {
273
272
  throw new Error("OIDC nonce mismatch.");
274
273
  }
@@ -289,7 +288,7 @@ async function getSessionFromCookies() {
289
288
  const idToken = cookieStore.get(oidcCookies.idToken)?.value;
290
289
  if (idToken) {
291
290
  try {
292
- return sessionFromPayload(parseJwtPayload(idToken));
291
+ return sessionFromPayload(parseJwtPayload(idToken) ?? {});
293
292
  } catch {
294
293
  }
295
294
  }
@@ -336,7 +335,7 @@ async function buildSessionResponse(_request) {
336
335
  status: 401
337
336
  });
338
337
  }
339
- return NextResponse.json(sessionFromPayload({ ...parseJwtPayload(idToken), exp: expiresAt }));
338
+ return NextResponse.json(sessionFromPayload({ ...parseJwtPayload(idToken) ?? {}, exp: expiresAt }));
340
339
  }
341
340
  async function buildTokenResponse(request) {
342
341
  const cookieStore = await cookies();
@@ -1,5 +1,22 @@
1
1
  // src/jwt.ts
2
2
  import { createHmac, timingSafeEqual } from "crypto";
3
+ import { base64urlDecodeString } from "@baseworks/core";
4
+ function parseJwtPayload(token) {
5
+ try {
6
+ const part = token.split(".")[1];
7
+ if (!part) return null;
8
+ return JSON.parse(base64urlDecodeString(part));
9
+ } catch {
10
+ return null;
11
+ }
12
+ }
13
+ function signHs256Jwt(claims, secret, expiresInSeconds = 86400) {
14
+ const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
15
+ const now = Math.floor(Date.now() / 1e3);
16
+ const payload = Buffer.from(JSON.stringify({ iat: now, exp: now + expiresInSeconds, ...claims })).toString("base64url");
17
+ const sig = createHmac("sha256", secret).update(`${header}.${payload}`).digest("base64url");
18
+ return `${header}.${payload}.${sig}`;
19
+ }
3
20
  function verifyHs256Jwt(token, secret) {
4
21
  const parts = token.split(".");
5
22
  if (parts.length !== 3) return null;
@@ -19,5 +36,7 @@ function verifyHs256Jwt(token, secret) {
19
36
  }
20
37
 
21
38
  export {
39
+ parseJwtPayload,
40
+ signHs256Jwt,
22
41
  verifyHs256Jwt
23
42
  };
package/dist/edge.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  getSessionFromCookies
3
- } from "./chunk-NBKMWUCN.js";
3
+ } from "./chunk-5W4TEXCT.js";
4
+ import {
5
+ parseJwtPayload
6
+ } from "./chunk-OD5XLL3O.js";
4
7
  import "./chunk-34E5PYNA.js";
5
8
  import {
6
9
  buildPublicUrl,
@@ -10,20 +13,6 @@ import {
10
13
  // src/edge.ts
11
14
  import { headers } from "next/headers";
12
15
  import { redirect } from "next/navigation";
13
-
14
- // src/_internal.ts
15
- import { base64urlDecodeString } from "@baseworks/core";
16
- function parseJwtPayload(token) {
17
- try {
18
- const part = token.split(".")[1];
19
- if (!part) return null;
20
- return JSON.parse(base64urlDecodeString(part));
21
- } catch {
22
- return null;
23
- }
24
- }
25
-
26
- // src/edge.ts
27
16
  function firstHeader(headerStore, names) {
28
17
  for (const name of names) {
29
18
  const value = headerStore.get(name);
package/dist/hono.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  verifyHs256Jwt
3
- } from "./chunk-TXDBQMTY.js";
3
+ } from "./chunk-OD5XLL3O.js";
4
4
 
5
5
  // src/hono.ts
6
6
  async function requireAuth(c, next) {
package/dist/index.js CHANGED
@@ -1,6 +1,3 @@
1
- import {
2
- verifyHs256Jwt
3
- } from "./chunk-TXDBQMTY.js";
4
1
  import {
5
2
  createOidcHumanResolver
6
3
  } from "./chunk-6TUNNS2B.js";
@@ -16,6 +13,9 @@ import {
16
13
  looksLikeJwt,
17
14
  stripBearer
18
15
  } from "./chunk-VBIQJKUU.js";
16
+ import {
17
+ verifyHs256Jwt
18
+ } from "./chunk-OD5XLL3O.js";
19
19
  import {
20
20
  buildOidcAuthUrl,
21
21
  generatePkce
package/dist/jwt.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /** Decode a JWT payload without signature verification. Returns null on malformed input. */
2
+ declare function parseJwtPayload(token: string): Record<string, unknown> | null;
1
3
  interface JwtClaims {
2
4
  sub?: string;
3
5
  exp?: number;
@@ -7,6 +9,8 @@ interface JwtClaims {
7
9
  type?: string;
8
10
  [key: string]: unknown;
9
11
  }
12
+ /** Sign an HS256 JWT. Runtime: Node.js only. */
13
+ declare function signHs256Jwt(claims: JwtClaims, secret: string, expiresInSeconds?: number): string;
10
14
  /**
11
15
  * Verify an HS256 JWT using Node.js crypto.
12
16
  * Returns decoded claims on success, null on any failure.
@@ -14,4 +18,4 @@ interface JwtClaims {
14
18
  */
15
19
  declare function verifyHs256Jwt(token: string, secret: string): JwtClaims | null;
16
20
 
17
- export { type JwtClaims, verifyHs256Jwt };
21
+ export { type JwtClaims, parseJwtPayload, signHs256Jwt, verifyHs256Jwt };
package/dist/jwt.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import {
2
+ parseJwtPayload,
3
+ signHs256Jwt,
2
4
  verifyHs256Jwt
3
- } from "./chunk-TXDBQMTY.js";
5
+ } from "./chunk-OD5XLL3O.js";
4
6
  export {
7
+ parseJwtPayload,
8
+ signHs256Jwt,
5
9
  verifyHs256Jwt
6
10
  };
package/dist/session.js CHANGED
@@ -9,7 +9,8 @@ import {
9
9
  handleAuthorizationCallback,
10
10
  hasServerOidcSession,
11
11
  oidcCookies
12
- } from "./chunk-NBKMWUCN.js";
12
+ } from "./chunk-5W4TEXCT.js";
13
+ import "./chunk-OD5XLL3O.js";
13
14
  import "./chunk-34E5PYNA.js";
14
15
  import "./chunk-3NJASEF4.js";
15
16
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baseworks/auth",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  "typecheck": "tsc --noEmit"
25
25
  },
26
26
  "dependencies": {
27
- "@baseworks/core": "workspace:*",
27
+ "@baseworks/core": "^0.2.1",
28
28
  "jose": "^6.2.3"
29
29
  },
30
30
  "peerDependencies": {
package/src/edge.ts CHANGED
@@ -5,7 +5,7 @@ import { headers } from "next/headers";
5
5
  import { redirect } from "next/navigation";
6
6
  import { getSessionFromCookies, type OidcSession } from "./session";
7
7
  import { buildPublicUrl, normalizeUrlLike } from "./url-helpers";
8
- import { parseJwtPayload } from "./_internal.js";
8
+ import { parseJwtPayload } from "./jwt.js";
9
9
 
10
10
  export type EdgeAuthProvider = "anonymous" | "cookie" | "pomerium";
11
11
 
package/src/jwt.ts CHANGED
@@ -1,4 +1,16 @@
1
1
  import { createHmac, timingSafeEqual } from 'crypto'
2
+ import { base64urlDecodeString } from '@baseworks/core'
3
+
4
+ /** Decode a JWT payload without signature verification. Returns null on malformed input. */
5
+ export function parseJwtPayload(token: string): Record<string, unknown> | null {
6
+ try {
7
+ const part = token.split('.')[1]
8
+ if (!part) return null
9
+ return JSON.parse(base64urlDecodeString(part)) as Record<string, unknown>
10
+ } catch {
11
+ return null
12
+ }
13
+ }
2
14
 
3
15
  export interface JwtClaims {
4
16
  sub?: string
@@ -10,6 +22,15 @@ export interface JwtClaims {
10
22
  [key: string]: unknown
11
23
  }
12
24
 
25
+ /** Sign an HS256 JWT. Runtime: Node.js only. */
26
+ export function signHs256Jwt(claims: JwtClaims, secret: string, expiresInSeconds = 86400): string {
27
+ const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url')
28
+ const now = Math.floor(Date.now() / 1000)
29
+ const payload = Buffer.from(JSON.stringify({ iat: now, exp: now + expiresInSeconds, ...claims })).toString('base64url')
30
+ const sig = createHmac('sha256', secret).update(`${header}.${payload}`).digest('base64url')
31
+ return `${header}.${payload}.${sig}`
32
+ }
33
+
13
34
  /**
14
35
  * Verify an HS256 JWT using Node.js crypto.
15
36
  * Returns decoded claims on success, null on any failure.
package/src/session.ts CHANGED
@@ -7,6 +7,7 @@ import { NextResponse } from "next/server";
7
7
  import { base64urlEncode, base64urlDecodeString } from "@baseworks/core";
8
8
  import { getAuthPublicUrl, normalizeUrlLike } from "./url-helpers";
9
9
  import { generatePkce } from "./pkce.js";
10
+ import { parseJwtPayload } from "./jwt.js";
10
11
 
11
12
  type DiscoveryDocument = {
12
13
  authorization_endpoint: string;
@@ -130,10 +131,6 @@ async function discoverOidc() {
130
131
  return (await response.json()) as DiscoveryDocument;
131
132
  }
132
133
 
133
- function parseJwtPayload(token: string): JwtPayload {
134
- const part = token.split(".")[1] ?? "";
135
- return JSON.parse(base64urlDecodeString(part)) as JwtPayload;
136
- }
137
134
 
138
135
  function encodeSessionCookie(session: OidcSession) {
139
136
  return base64urlEncode(new TextEncoder().encode(JSON.stringify(session)));
@@ -285,7 +282,7 @@ function sessionFromPayload(payload: JwtPayload): OidcSession {
285
282
 
286
283
  function applyTokenCookies(response: NextResponse, request: NextRequest, tokens: TokenResponse) {
287
284
  const options = getCookieOptions(request);
288
- const payload = parseJwtPayload(tokens.id_token!);
285
+ const payload = (parseJwtPayload(tokens.id_token!) ?? {}) as JwtPayload;
289
286
  const expiresAt =
290
287
  payload.exp ??
291
288
  (tokens.expires_in ? Math.floor(Date.now() / 1_000) + tokens.expires_in : undefined);
@@ -388,7 +385,7 @@ export async function handleAuthorizationCallback(request: NextRequest) {
388
385
  redirectUri: getRedirectUri(request),
389
386
  tokenEndpoint: discovery.token_endpoint,
390
387
  });
391
- const payload = parseJwtPayload(tokens.id_token!);
388
+ const payload = (parseJwtPayload(tokens.id_token!) ?? {}) as JwtPayload;
392
389
  if (savedNonce && payload.nonce && payload.nonce !== savedNonce) {
393
390
  throw new Error("OIDC nonce mismatch.");
394
391
  }
@@ -410,7 +407,7 @@ export async function getSessionFromCookies(): Promise<OidcSession> {
410
407
  const idToken = cookieStore.get(oidcCookies.idToken)?.value;
411
408
  if (idToken) {
412
409
  try {
413
- return sessionFromPayload(parseJwtPayload(idToken));
410
+ return sessionFromPayload((parseJwtPayload(idToken) ?? {}) as JwtPayload);
414
411
  } catch {
415
412
  // fall through to compact session cookie
416
413
  }
@@ -467,7 +464,7 @@ export async function buildSessionResponse(_request?: NextRequest) {
467
464
  status: 401,
468
465
  });
469
466
  }
470
- return NextResponse.json(sessionFromPayload({ ...parseJwtPayload(idToken), exp: expiresAt }));
467
+ return NextResponse.json(sessionFromPayload({ ...(parseJwtPayload(idToken) ?? {}), exp: expiresAt } as JwtPayload));
471
468
  }
472
469
 
473
470
  export async function buildTokenResponse(request: NextRequest) {
package/src/_internal.ts DELETED
@@ -1,14 +0,0 @@
1
- /**
2
- * Shared internal utilities — not exported from package public API.
3
- */
4
- import { base64urlDecodeString } from '@baseworks/core'
5
-
6
- export function parseJwtPayload(token: string): Record<string, unknown> | null {
7
- try {
8
- const part = token.split('.')[1]
9
- if (!part) return null
10
- return JSON.parse(base64urlDecodeString(part)) as Record<string, unknown>
11
- } catch {
12
- return null
13
- }
14
- }