unjwt 0.5.22 → 0.5.24

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 CHANGED
@@ -603,18 +603,18 @@ console.log(rsaPublicSpki);
603
603
 
604
604
  ### Adapters
605
605
 
606
- #### H3 (Nuxt, Nitro)
606
+ #### H3 v1 (Nuxt v4, Nitro v2)
607
607
 
608
- The `h3` adapter bundles session helpers that store data inside signed or encrypted JWTs.
608
+ The `h3v1` adapter bundles session helpers that store data inside signed or encrypted JWTs.
609
609
 
610
610
  - `useJWESession(event, config)` encrypts the session payload with the provided `secret` (password string or private/symmetric JWK). Use this when session data must remain confidential. (cookie's `httpOnly: true` by default)
611
611
  - `useJWSSession(event, config)` signs, but does not encrypt, the session payload with `config.key`. Use this when clients may read the session content but you still need tamper protection. (cookie's `httpOnly: false` by default)
612
612
 
613
- Both helpers expose the same API: read `session.id` / `session.data`, call `session.update()` to patch values, and `session.clear()` to invalidate the cookie. When setting `maxAge`, `exp` claim is automatically managed and validated.
613
+ Both helpers expose the same API: read `session.id` / `session.data`, call `session.update()` to patch values, and `session.clear()` to invalidate the cookie. When setting `maxAge`, `exp` claim is automatically managed and validated. They also support a number of `hooks` in the config for custom logic (e.g. logging, refreshing, etc).
614
614
 
615
615
  ```ts
616
616
  import { defineEventHandler } from "h3";
617
- import { useJWESession, useJWSSession, generateJWK } from "unjwt/adapters/h3";
617
+ import { useJWESession, useJWSSession, generateJWK } from "unjwt/adapters/h3v1";
618
618
 
619
619
  const keys = await generateJWK("RS256");
620
620
 
@@ -641,6 +641,121 @@ export default defineEventHandler(async (event) => {
641
641
  });
642
642
  ```
643
643
 
644
+ #### H3 v2 (Nuxt v5, Nitro v3)
645
+
646
+ The `h3v2` adapter bundles session helpers that store data inside signed or encrypted JWTs.
647
+
648
+ - `useJWESession(event, config)` encrypts the session payload with the provided `secret` (password string or private/symmetric JWK). Use this when session data must remain confidential. (cookie's `httpOnly: true` by default)
649
+ - `useJWSSession(event, config)` signs, but does not encrypt, the session payload with `config.key`. Use this when clients may read the session content but you still need tamper protection. (cookie's `httpOnly: false` by default)
650
+
651
+ Both helpers expose the same API: read `session.id` / `session.data`, call `session.update()` to patch values, and `session.clear()` to invalidate the cookie. When setting `maxAge`, `exp` claim is automatically managed and validated. They also support a number of `hooks` in the config for custom logic (e.g. logging, refreshing, etc).
652
+
653
+ ```ts
654
+ import { H3, HTTPError, serve } from "h3v2";
655
+
656
+ import {
657
+ type SessionConfigJWE,
658
+ type SessionConfigJWS,
659
+ useJWESession,
660
+ useJWSSession,
661
+ getJWESession,
662
+ updateJWSSession,
663
+ generateJWK,
664
+ } from "unjwt/adapters/h3v2";
665
+
666
+ const atJwk = await generateJWK("RS256");
667
+
668
+ const jweOptions = {
669
+ key: "refresh_token_secret",
670
+ name: "refresh_token",
671
+ } satisfies SessionConfigJWE;
672
+
673
+ const jwsOptions = {
674
+ key: atJwk,
675
+ name: "access_token",
676
+ maxAge: 15 * 60, // 15 minutes
677
+ hooks: {
678
+ async onExpire(event, _error, config) {
679
+ const refreshSession = await getJWESession(event, jweOptions);
680
+ if (!refreshSession.data.sub) {
681
+ // no valid refresh session, nothing to do
682
+ return;
683
+ }
684
+
685
+ console.log("Access token expired, refreshing...");
686
+
687
+ // refresh the access token
688
+ await updateJWSSession(event, config, {
689
+ sub: refreshSession.data.sub,
690
+ scope: refreshSession.data.scope,
691
+ });
692
+ },
693
+ },
694
+ } satisfies SessionConfigJWS;
695
+
696
+ const app = new H3();
697
+
698
+ app.post("/login", async (event) => {
699
+ const refreshSession = await useJWESession(event, jweOptions);
700
+ const accessSession = await useJWSSession(event, jwsOptions);
701
+
702
+ if (accessSession.data.sub) {
703
+ // user already logged in, return existing info
704
+ return {
705
+ accessToken: {
706
+ id: accessSession.id,
707
+ createdAt: accessSession.createdAt,
708
+ expiresAt: accessSession.expiresAt,
709
+ data: accessSession.data,
710
+ },
711
+ refreshSession: {
712
+ id: refreshSession.id,
713
+ createdAt: refreshSession.createdAt,
714
+ expiresAt: refreshSession.expiresAt,
715
+ data: refreshSession.data,
716
+ },
717
+ };
718
+ }
719
+
720
+ const data = (await event.req.json()) as {
721
+ username?: string;
722
+ password?: string;
723
+ };
724
+
725
+ if (!data.username || !data.password) {
726
+ throw new HTTPError("Username and password are required", { status: 400 });
727
+ }
728
+
729
+ // validate user credentials here
730
+
731
+ const claims = {
732
+ sub: data.username,
733
+ scope: ["read:profile"],
734
+ };
735
+
736
+ await accessSession.update(claims);
737
+
738
+ await refreshSession.update(claims);
739
+
740
+ return {
741
+ accessToken: {
742
+ id: accessSession.id,
743
+ createdAt: accessSession.createdAt,
744
+ expiresAt: accessSession.expiresAt,
745
+ data: accessSession.data,
746
+ },
747
+ refreshSession: {
748
+ id: refreshSession.id,
749
+ createdAt: refreshSession.createdAt,
750
+ expiresAt: refreshSession.expiresAt,
751
+ data: refreshSession.data,
752
+ },
753
+ };
754
+ });
755
+
756
+ serve(app);
757
+ ```
758
+
644
759
  ---
645
760
 
646
761
  ### Utility Functions
@@ -1,15 +1,15 @@
1
- import { b as JWEEncryptOptions } from './shared/unjwt.9mL1vSFP.mjs';
2
- export { d as JWEDecryptOptions, e as JWEDecryptResult, J as JWEHeaderParameters, c as JWEKeyLookupFunction, a as JWEKeyManagementHeaderParameters } from './shared/unjwt.9mL1vSFP.mjs';
3
- import { X as JWTClaims, r as JWK_Symmetric, u as JWK_Private, t as JWK_Public, Z as JWTClaimValidationOptions, w as JWKSet } from './shared/unjwt.CtHrClHc.mjs';
4
- export { C as CompositeKey, f as ContentEncryptionAlgorithm, D as DeriveKeyOptions, e as DeriveKeyReturn, c as GenerateJWKOptions, d as GenerateJWKReturn, G as GenerateKeyAlgorithm, a as GenerateKeyOptions, b as GenerateKeyReturn, v as JWK, S as JWKAlgorithm, T as JWKPEMAlgorithm, J as JWKParameters, I as JWK_AES_CBC_HMAC, L as JWK_AES_GCM, H as JWK_AES_GCM_KW, F as JWK_AES_KW, s as JWK_Asymmetric, R as JWK_Asymmetric_Algorithm, j as JWK_EC, O as JWK_ECDH_ES, A as JWK_ECDSA, i as JWK_EC_Private, h as JWK_EC_Public, x as JWK_HMAC, p as JWK_OKP, o as JWK_OKP_Private, n as JWK_OKP_Public, P as JWK_OKP_SIGN, N as JWK_PBES2, m as JWK_RSA, B as JWK_RSA_ENC, z as JWK_RSA_PSS, l as JWK_RSA_Private, k as JWK_RSA_Public, y as JWK_RSA_SIGN, Q as JWK_Symmetric_Algorithm, q as JWK_oct, Y as JWT, V as JoseHeaderParameters, K as KeyManagementAlgorithm, U as UnwrapKeyOptions, W as WrapKeyOptions, g as WrapKeyResult } from './shared/unjwt.CtHrClHc.mjs';
1
+ import { b as JWEEncryptOptions } from '../shared/unjwt.9mL1vSFP.mjs';
2
+ export { d as JWEDecryptOptions, e as JWEDecryptResult, J as JWEHeaderParameters, c as JWEKeyLookupFunction, a as JWEKeyManagementHeaderParameters } from '../shared/unjwt.9mL1vSFP.mjs';
3
+ import { X as JWTClaims, r as JWK_Symmetric, u as JWK_Private, t as JWK_Public, Z as JWTClaimValidationOptions, w as JWKSet } from '../shared/unjwt.CtHrClHc.mjs';
4
+ export { C as CompositeKey, f as ContentEncryptionAlgorithm, D as DeriveKeyOptions, e as DeriveKeyReturn, c as GenerateJWKOptions, d as GenerateJWKReturn, G as GenerateKeyAlgorithm, a as GenerateKeyOptions, b as GenerateKeyReturn, v as JWK, S as JWKAlgorithm, T as JWKPEMAlgorithm, J as JWKParameters, I as JWK_AES_CBC_HMAC, L as JWK_AES_GCM, H as JWK_AES_GCM_KW, F as JWK_AES_KW, s as JWK_Asymmetric, R as JWK_Asymmetric_Algorithm, j as JWK_EC, O as JWK_ECDH_ES, A as JWK_ECDSA, i as JWK_EC_Private, h as JWK_EC_Public, x as JWK_HMAC, p as JWK_OKP, o as JWK_OKP_Private, n as JWK_OKP_Public, P as JWK_OKP_SIGN, N as JWK_PBES2, m as JWK_RSA, B as JWK_RSA_ENC, z as JWK_RSA_PSS, l as JWK_RSA_Private, k as JWK_RSA_Public, y as JWK_RSA_SIGN, Q as JWK_Symmetric_Algorithm, q as JWK_oct, Y as JWT, V as JoseHeaderParameters, K as KeyManagementAlgorithm, U as UnwrapKeyOptions, W as WrapKeyOptions, g as WrapKeyResult } from '../shared/unjwt.CtHrClHc.mjs';
5
5
  import { CookieSerializeOptions } from 'cookie-es';
6
6
  import { H3Event } from 'h3';
7
- import { c as JWSSignOptions } from './shared/unjwt.BsLgL0DQ.mjs';
8
- export { d as deriveJWKFromPassword, e as exportJWKToPEM, g as generateJWK, i as importJWKFromPEM } from './shared/unjwt.BjP_dGnX.mjs';
7
+ import { c as JWSSignOptions } from '../shared/unjwt.BsLgL0DQ.mjs';
8
+ export { d as deriveJWKFromPassword, e as exportJWKToPEM, g as generateJWK, i as importJWKFromPEM } from '../shared/unjwt.BjP_dGnX.mjs';
9
9
 
10
10
  /**
11
11
  * This is a fork of h3 library's session utility functions.
12
- * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/test/session.test.ts
12
+ * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
13
13
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
14
14
  */
15
15
 
@@ -24,11 +24,11 @@ interface SessionJWE<T extends SessionDataT$1 = SessionDataT$1> {
24
24
  [kGetSessionPromise$1]?: Promise<SessionJWE<T>>;
25
25
  }
26
26
  interface SessionHooksJWE {
27
- onRead?: (session: SessionJWE, event: H3Event) => void | Promise<void>;
28
- onUpdate?: (session: SessionJWE, event: H3Event) => void | Promise<void>;
29
- onClear?: (event: H3Event) => void | Promise<void>;
30
- onExpire?: (event: H3Event, error: any | undefined) => void | Promise<void>;
31
- onError?: (event: H3Event, error: any) => void | Promise<void>;
27
+ onRead?: (session: SessionJWE, event: H3Event, config: SessionConfigJWE) => void | Promise<void>;
28
+ onUpdate?: (session: SessionJWE, event: H3Event, config: SessionConfigJWE) => void | Promise<void>;
29
+ onClear?: (event: H3Event, config: Partial<SessionConfigJWE>) => void | Promise<void>;
30
+ onExpire?: (event: H3Event, error: any | undefined, config: SessionConfigJWE) => void | Promise<void>;
31
+ onError?: (event: H3Event, error: any, config: SessionConfigJWE) => void | Promise<void>;
32
32
  }
33
33
  interface SessionManager<T extends SessionDataT$1 = SessionDataT$1> {
34
34
  readonly id: string | undefined;
@@ -39,8 +39,13 @@ interface SessionManager<T extends SessionDataT$1 = SessionDataT$1> {
39
39
  clear: () => Promise<SessionManager<T>>;
40
40
  }
41
41
  interface SessionConfigJWE {
42
- /** Shared secret used, string for PBES2 or Json Web Key (JWK) */
43
- secret: string | JWK_Symmetric | {
42
+ /** @deprecated use `key` instead */
43
+ secret?: string | JWK_Symmetric | {
44
+ privateKey: JWK_Private | JWK_Symmetric;
45
+ publicKey?: JWK_Public;
46
+ };
47
+ /** Shared key used, string for PBES2 or Json Web Key (JWK) */
48
+ key: string | JWK_Symmetric | JWK_Private | {
44
49
  privateKey: JWK_Private | JWK_Symmetric;
45
50
  publicKey?: JWK_Public;
46
51
  };
@@ -52,8 +57,6 @@ interface SessionConfigJWE {
52
57
  cookie?: false | CookieSerializeOptions;
53
58
  /** Default is x-h3-session / x-{name}-session */
54
59
  sessionHeader?: false | string;
55
- /** Optional WebCrypto implementation override */
56
- crypto?: Crypto;
57
60
  /** Default is crypto.randomUUID */
58
61
  generateId?: () => string;
59
62
  /** JWE configuration overrides */
@@ -111,7 +114,7 @@ declare function clearJWESession(event: H3Event, config: Partial<SessionConfigJW
111
114
 
112
115
  /**
113
116
  * This is a fork of h3 library's session utility functions.
114
- * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/test/session.test.ts
117
+ * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
115
118
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
116
119
  */
117
120
 
@@ -125,11 +128,11 @@ interface SessionJWS<T extends SessionDataT = SessionDataT> {
125
128
  [kGetSessionPromise]?: Promise<SessionJWS<T>>;
126
129
  }
127
130
  interface SessionHooksJWS {
128
- onRead?: (session: SessionJWS, event: H3Event) => void | Promise<void>;
129
- onUpdate?: (session: SessionJWS, event: H3Event) => void | Promise<void>;
130
- onClear?: (event: H3Event) => void | Promise<void>;
131
- onExpire?: (event: H3Event, error: any | undefined) => void | Promise<void>;
132
- onError?: (event: H3Event, error: any) => void | Promise<void>;
131
+ onRead?: (session: SessionJWS, event: H3Event, config: SessionConfigJWS) => void | Promise<void>;
132
+ onUpdate?: (session: SessionJWS, event: H3Event, config: SessionConfigJWS) => void | Promise<void>;
133
+ onClear?: (event: H3Event, config: Partial<SessionConfigJWS>) => void | Promise<void>;
134
+ onExpire?: (event: H3Event, error: any | undefined, config: SessionConfigJWS) => void | Promise<void>;
135
+ onError?: (event: H3Event, error: any, config: SessionConfigJWS) => void | Promise<void>;
133
136
  }
134
137
  interface SessionConfigJWS {
135
138
  /**
@@ -147,8 +150,6 @@ interface SessionConfigJWS {
147
150
  cookie?: false | CookieSerializeOptions;
148
151
  /** Custom header (false to disable header lookup) */
149
152
  sessionHeader?: false | string;
150
- /** Provide a custom WebCrypto (if needed for algorithm operations) */
151
- crypto?: Crypto;
152
153
  /** Custom ID generator (defaults to crypto.randomUUID) */
153
154
  generateId?: () => string;
154
155
  /** JWS customization */