@draftlab/auth 0.0.2 → 0.0.4
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/dist/allow.d.ts +58 -1
- package/dist/allow.js +61 -2
- package/dist/client.d.ts +2 -3
- package/dist/client.js +2 -2
- package/dist/core.d.ts +128 -8
- package/dist/core.js +496 -12
- package/dist/error.d.ts +242 -1
- package/dist/error.js +235 -1
- package/dist/index.d.ts +1 -8
- package/dist/index.js +1 -12
- package/dist/keys.d.ts +1 -1
- package/dist/keys.js +138 -3
- package/dist/pkce.js +160 -1
- package/dist/provider/code.d.ts +211 -3
- package/dist/provider/code.js +1 -1
- package/dist/provider/facebook.d.ts +2 -3
- package/dist/provider/facebook.js +1 -5
- package/dist/provider/github.d.ts +2 -3
- package/dist/provider/github.js +1 -5
- package/dist/provider/google.d.ts +2 -3
- package/dist/provider/google.js +1 -5
- package/dist/provider/oauth2.d.ts +175 -3
- package/dist/provider/oauth2.js +153 -5
- package/dist/provider/password.d.ts +384 -3
- package/dist/provider/password.js +4 -4
- package/dist/provider/provider.d.ts +226 -2
- package/dist/random.js +85 -1
- package/dist/storage/memory.d.ts +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/storage.d.ts +161 -1
- package/dist/storage/storage.js +60 -1
- package/dist/storage/turso.d.ts +1 -1
- package/dist/storage/turso.js +1 -1
- package/dist/storage/unstorage.d.ts +1 -1
- package/dist/storage/unstorage.js +1 -1
- package/dist/subject.d.ts +61 -2
- package/dist/themes/theme.d.ts +208 -1
- package/dist/themes/theme.js +118 -1
- package/dist/ui/base.js +420 -2
- package/dist/ui/code.d.ts +1 -3
- package/dist/ui/code.js +3 -4
- package/dist/ui/form.js +59 -1
- package/dist/ui/icon.js +190 -1
- package/dist/ui/password.d.ts +1 -3
- package/dist/ui/password.js +2 -3
- package/dist/ui/select.js +278 -4
- package/dist/util.d.ts +71 -1
- package/dist/util.js +106 -1
- package/package.json +2 -4
- package/dist/allow-CixonwTW.d.ts +0 -59
- package/dist/allow-DX5cehSc.js +0 -63
- package/dist/base-DRutbxgL.js +0 -422
- package/dist/code-DJxdFR7p.d.ts +0 -212
- package/dist/core-BZHEAefX.d.ts +0 -129
- package/dist/core-CDM5o4rs.js +0 -498
- package/dist/error-CWAdNAzm.d.ts +0 -243
- package/dist/error-DgAKK7b2.js +0 -237
- package/dist/form-6XKM_cOk.js +0 -61
- package/dist/icon-Ci5uqGB_.js +0 -192
- package/dist/keys-EEfxEGfO.js +0 -140
- package/dist/oauth2-B7-6Z7Lc.js +0 -155
- package/dist/oauth2-CXHukHf2.d.ts +0 -176
- package/dist/password-C4KLmO0O.d.ts +0 -385
- package/dist/pkce-276Za_rZ.js +0 -162
- package/dist/provider-tndlqCzp.d.ts +0 -227
- package/dist/random-SXMYlaVr.js +0 -87
- package/dist/select-BjySLL8I.js +0 -280
- package/dist/storage-BEaqEPNQ.js +0 -62
- package/dist/storage-CxKerLlc.d.ts +0 -162
- package/dist/subject-DMIMVtaT.d.ts +0 -62
- package/dist/theme-C9by7VXf.d.ts +0 -209
- package/dist/theme-CswaLtbW.js +0 -120
- package/dist/util-CSdHUFOo.js +0 -108
- package/dist/util-DbSKG1Xm.d.ts +0 -72
package/dist/icon-Ci5uqGB_.js
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
//#region src/ui/icon.ts
|
|
2
|
-
/**
|
|
3
|
-
* Icon components for Draft Auth UI.
|
|
4
|
-
* Provides SVG icons for various authentication providers and common UI elements.
|
|
5
|
-
*
|
|
6
|
-
* ## Usage
|
|
7
|
-
*
|
|
8
|
-
* ```ts
|
|
9
|
-
* import { ICON_GITHUB, ICON_GOOGLE, ICON_EMAIL } from "./icon"
|
|
10
|
-
*
|
|
11
|
-
* // In provider buttons
|
|
12
|
-
* const buttonHtml = `
|
|
13
|
-
* <button>
|
|
14
|
-
* ${ICON_GITHUB}
|
|
15
|
-
* Continue with GitHub
|
|
16
|
-
* </button>
|
|
17
|
-
* `
|
|
18
|
-
*
|
|
19
|
-
* // In form elements
|
|
20
|
-
* const formHtml = `
|
|
21
|
-
* <div>
|
|
22
|
-
* ${ICON_EMAIL}
|
|
23
|
-
* Email verification
|
|
24
|
-
* </div>
|
|
25
|
-
* `
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* ## Features
|
|
29
|
-
*
|
|
30
|
-
* - **Consistent sizing**: All icons are properly sized and scalable
|
|
31
|
-
* - **Accessibility**: Proper ARIA labels and semantic markup
|
|
32
|
-
* - **Current color**: Icons inherit text color for easy theming
|
|
33
|
-
* - **Optimized SVGs**: Clean, minimal SVG markup for performance
|
|
34
|
-
*
|
|
35
|
-
* @packageDocumentation
|
|
36
|
-
*/
|
|
37
|
-
/**
|
|
38
|
-
* GitHub brand icon with official logo design.
|
|
39
|
-
* Used for GitHub authentication provider buttons and references.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```ts
|
|
43
|
-
* const buttonHtml = `
|
|
44
|
-
* <button data-component="provider-button">
|
|
45
|
-
* ${ICON_GITHUB}
|
|
46
|
-
* Sign in with GitHub
|
|
47
|
-
* </button>
|
|
48
|
-
* `
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
const ICON_GITHUB = `
|
|
52
|
-
<svg
|
|
53
|
-
aria-label="GitHub"
|
|
54
|
-
fill="currentColor"
|
|
55
|
-
height="250"
|
|
56
|
-
preserveAspectRatio="xMidYMid"
|
|
57
|
-
role="img"
|
|
58
|
-
viewBox="0 0 256 250"
|
|
59
|
-
width="256"
|
|
60
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
61
|
-
>
|
|
62
|
-
<path d="M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z" />
|
|
63
|
-
</svg>
|
|
64
|
-
`;
|
|
65
|
-
/**
|
|
66
|
-
* Google brand icon with official multicolor logo design.
|
|
67
|
-
* Used for Google authentication provider buttons and references.
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```ts
|
|
71
|
-
* const buttonHtml = `
|
|
72
|
-
* <button data-component="provider-button">
|
|
73
|
-
* ${ICON_GOOGLE}
|
|
74
|
-
* Continue with Google
|
|
75
|
-
* </button>
|
|
76
|
-
* `
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
const ICON_GOOGLE = `
|
|
80
|
-
<svg
|
|
81
|
-
aria-label="Google"
|
|
82
|
-
height="262"
|
|
83
|
-
preserveAspectRatio="xMidYMid"
|
|
84
|
-
role="img"
|
|
85
|
-
viewBox="0 0 256 262"
|
|
86
|
-
width="256"
|
|
87
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
88
|
-
>
|
|
89
|
-
<path
|
|
90
|
-
d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027"
|
|
91
|
-
fill="#4285F4"
|
|
92
|
-
/>
|
|
93
|
-
<path
|
|
94
|
-
d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055-34.523 0-63.824-22.773-74.269-54.25l-1.531.13-40.298 31.187-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1"
|
|
95
|
-
fill="#34A853"
|
|
96
|
-
/>
|
|
97
|
-
<path
|
|
98
|
-
d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82 0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602l42.356-32.782"
|
|
99
|
-
fill="#FBBC05"
|
|
100
|
-
/>
|
|
101
|
-
<path
|
|
102
|
-
d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0 79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251"
|
|
103
|
-
fill="#EB4335"
|
|
104
|
-
/>
|
|
105
|
-
</svg>
|
|
106
|
-
`;
|
|
107
|
-
/**
|
|
108
|
-
* Email envelope icon for email-related authentication flows.
|
|
109
|
-
* Used in email verification, password reset, and contact forms.
|
|
110
|
-
*
|
|
111
|
-
* @example
|
|
112
|
-
* ```ts
|
|
113
|
-
* const inputGroupHtml = `
|
|
114
|
-
* <div data-component="input-group">
|
|
115
|
-
* ${ICON_EMAIL}
|
|
116
|
-
* <input type="email" placeholder="Enter your email" />
|
|
117
|
-
* </div>
|
|
118
|
-
* `
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
const ICON_EMAIL = `
|
|
122
|
-
<svg
|
|
123
|
-
aria-label="Email"
|
|
124
|
-
fill="none"
|
|
125
|
-
role="img"
|
|
126
|
-
stroke="currentColor"
|
|
127
|
-
stroke-width="1.5"
|
|
128
|
-
viewBox="0 0 24 24"
|
|
129
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
130
|
-
>
|
|
131
|
-
<path
|
|
132
|
-
d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"
|
|
133
|
-
stroke-linecap="round"
|
|
134
|
-
stroke-linejoin="round"
|
|
135
|
-
/>
|
|
136
|
-
</svg>
|
|
137
|
-
`;
|
|
138
|
-
/**
|
|
139
|
-
* Slack brand icon with official logo design.
|
|
140
|
-
* Used for Slack authentication provider buttons and workplace integrations.
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* const buttonHtml = `
|
|
145
|
-
* <button data-component="provider-button">
|
|
146
|
-
* ${ICON_SLACK}
|
|
147
|
-
* Continue with Slack
|
|
148
|
-
* </button>
|
|
149
|
-
* `
|
|
150
|
-
* ```
|
|
151
|
-
*/
|
|
152
|
-
const ICON_SLACK = `
|
|
153
|
-
<svg
|
|
154
|
-
aria-label="Slack"
|
|
155
|
-
fill="none"
|
|
156
|
-
height="24"
|
|
157
|
-
role="img"
|
|
158
|
-
viewBox="0 0 24 24"
|
|
159
|
-
width="24"
|
|
160
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
161
|
-
>
|
|
162
|
-
<g>
|
|
163
|
-
<path
|
|
164
|
-
clip-rule="evenodd"
|
|
165
|
-
d="M8.79948 0C7.47279 0.000978593 6.39909 1.07547 6.40007 2.39951C6.39909 3.72355 7.47377 4.79804 8.80046 4.79902H11.2009V2.40049C11.2018 1.07645 10.1271 0.00195719 8.79948 0ZM8.79948 6.4H2.40039C1.07371 6.40098 -0.000977873 7.47547 2.67973e-06 8.79951C-0.00195842 10.1235 1.07273 11.198 2.39941 11.2H8.79948C10.1262 11.199 11.2009 10.1245 11.1999 8.80049C11.2009 7.47547 10.1262 6.40098 8.79948 6.4Z"
|
|
166
|
-
fill="currentColor"
|
|
167
|
-
fill-rule="evenodd"
|
|
168
|
-
/>
|
|
169
|
-
<path
|
|
170
|
-
clip-rule="evenodd"
|
|
171
|
-
d="M24.0007 8.79951C24.0016 7.47547 22.9269 6.40098 21.6003 6.4C20.2736 6.40098 19.1989 7.47547 19.1999 8.79951V11.2H21.6003C22.9269 11.199 24.0016 10.1245 24.0007 8.79951ZM17.6006 8.79951V2.39951C17.6016 1.07645 16.5279 0.00195719 15.2012 0C13.8745 0.000978593 12.7998 1.07547 12.8008 2.39951V8.79951C12.7988 10.1235 13.8735 11.198 15.2002 11.2C16.5269 11.199 17.6016 10.1245 17.6006 8.79951Z"
|
|
172
|
-
fill="currentColor"
|
|
173
|
-
fill-rule="evenodd"
|
|
174
|
-
/>
|
|
175
|
-
<path
|
|
176
|
-
clip-rule="evenodd"
|
|
177
|
-
d="M15.1992 23.9998C16.5259 23.9988 17.6006 22.9243 17.5996 21.6003C17.6006 20.2763 16.5259 19.2018 15.1992 19.2008H12.7988V21.6003C12.7978 22.9234 13.8725 23.9978 15.1992 23.9998ZM15.1992 17.5988H21.5993C22.926 17.5978 24.0007 16.5234 23.9997 15.1993C24.0016 13.8753 22.927 12.8008 21.6003 12.7988H15.2002C13.8735 12.7998 12.7988 13.8743 12.7998 15.1983C12.7988 16.5234 13.8725 17.5978 15.1992 17.5988Z"
|
|
178
|
-
fill="currentColor"
|
|
179
|
-
fill-rule="evenodd"
|
|
180
|
-
/>
|
|
181
|
-
<path
|
|
182
|
-
clip-rule="evenodd"
|
|
183
|
-
d="M0 15.1993C-0.000979882 16.5234 1.07371 17.5978 2.40039 17.5988C3.72708 17.5978 4.80177 16.5234 4.80079 15.1993V12.7998H2.40039C1.07371 12.8008 -0.000979882 13.8753 0 15.1993ZM6.40007 15.1993V21.5993C6.3981 22.9234 7.47279 23.9978 8.79948 23.9998C10.1262 23.9988 11.2009 22.9243 11.1999 21.6003V15.2013C11.2018 13.8772 10.1271 12.8027 8.80046 12.8008C7.47279 12.8008 6.39909 13.8753 6.40007 15.1993Z"
|
|
184
|
-
fill="currentColor"
|
|
185
|
-
fill-rule="evenodd"
|
|
186
|
-
/>
|
|
187
|
-
</g>
|
|
188
|
-
</svg>
|
|
189
|
-
`;
|
|
190
|
-
|
|
191
|
-
//#endregion
|
|
192
|
-
export { ICON_EMAIL, ICON_GITHUB, ICON_GOOGLE, ICON_SLACK };
|
package/dist/keys-EEfxEGfO.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { generateSecureToken } from "./random-SXMYlaVr.js";
|
|
2
|
-
import { Storage } from "./storage-BEaqEPNQ.js";
|
|
3
|
-
import { exportJWK, exportPKCS8, exportSPKI, generateKeyPair, importPKCS8, importSPKI } from "jose";
|
|
4
|
-
|
|
5
|
-
//#region src/keys.ts
|
|
6
|
-
/**
|
|
7
|
-
* Cryptographic key management for JWT signing and encryption operations.
|
|
8
|
-
* Handles automatic key generation, rotation, and storage for OAuth operations.
|
|
9
|
-
*/
|
|
10
|
-
/** Elliptic Curve algorithm used for JWT signing operations */
|
|
11
|
-
const signingAlg = "ES256";
|
|
12
|
-
/** RSA algorithm used for token encryption operations */
|
|
13
|
-
const encryptionAlg = "RSA-OAEP-512";
|
|
14
|
-
/**
|
|
15
|
-
* Loads or generates signing keys for JWT operations.
|
|
16
|
-
* Returns existing valid keys, or generates new ones if none are available.
|
|
17
|
-
* Keys are automatically sorted by creation date (newest first).
|
|
18
|
-
*
|
|
19
|
-
* @param storage - Storage adapter for persistent key storage
|
|
20
|
-
* @returns Promise resolving to array of available signing key pairs
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```ts
|
|
24
|
-
* const keys = await signingKeys(storage)
|
|
25
|
-
* const currentKey = keys[0] // Most recent key
|
|
26
|
-
*
|
|
27
|
-
* // Use for JWT signing
|
|
28
|
-
* const jwt = await new SignJWT(payload)
|
|
29
|
-
* .setProtectedHeader({ alg: currentKey.alg, kid: currentKey.id })
|
|
30
|
-
* .sign(currentKey.private)
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
const signingKeys = async (storage) => {
|
|
34
|
-
const results = [];
|
|
35
|
-
const scanner = Storage.scan(storage, ["signing:key"]);
|
|
36
|
-
for await (const [, value] of scanner) try {
|
|
37
|
-
const publicKey = await importSPKI(value.publicKey, value.alg, { extractable: true });
|
|
38
|
-
const privateKey = await importPKCS8(value.privateKey, value.alg);
|
|
39
|
-
const jwk$1 = await exportJWK(publicKey);
|
|
40
|
-
jwk$1.kid = value.id;
|
|
41
|
-
jwk$1.use = "sig";
|
|
42
|
-
results.push({
|
|
43
|
-
id: value.id,
|
|
44
|
-
alg: signingAlg,
|
|
45
|
-
created: new Date(value.created),
|
|
46
|
-
expired: value.expired ? new Date(value.expired) : void 0,
|
|
47
|
-
public: publicKey,
|
|
48
|
-
private: privateKey,
|
|
49
|
-
jwk: jwk$1
|
|
50
|
-
});
|
|
51
|
-
} catch {}
|
|
52
|
-
results.sort((a, b) => b.created.getTime() - a.created.getTime());
|
|
53
|
-
if (results.filter((item) => !item.expired).length) return results;
|
|
54
|
-
const key = await generateKeyPair(signingAlg, { extractable: true });
|
|
55
|
-
const serialized = {
|
|
56
|
-
id: generateSecureToken(16),
|
|
57
|
-
publicKey: await exportSPKI(key.publicKey),
|
|
58
|
-
privateKey: await exportPKCS8(key.privateKey),
|
|
59
|
-
created: Date.now(),
|
|
60
|
-
alg: signingAlg
|
|
61
|
-
};
|
|
62
|
-
await Storage.set(storage, ["signing:key", serialized.id], serialized);
|
|
63
|
-
const jwk = await exportJWK(key.publicKey);
|
|
64
|
-
jwk.kid = serialized.id;
|
|
65
|
-
jwk.use = "sig";
|
|
66
|
-
const newKeyPair = {
|
|
67
|
-
id: serialized.id,
|
|
68
|
-
alg: signingAlg,
|
|
69
|
-
created: new Date(serialized.created),
|
|
70
|
-
expired: serialized.expired ? new Date(serialized.expired) : void 0,
|
|
71
|
-
public: key.publicKey,
|
|
72
|
-
private: key.privateKey,
|
|
73
|
-
jwk
|
|
74
|
-
};
|
|
75
|
-
return [newKeyPair, ...results];
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Loads or generates encryption keys for token encryption operations.
|
|
79
|
-
* Returns existing valid keys, or generates new ones if none are available.
|
|
80
|
-
* Keys are automatically sorted by creation date (newest first).
|
|
81
|
-
*
|
|
82
|
-
* @param storage - Storage adapter for persistent key storage
|
|
83
|
-
* @returns Promise resolving to array of available encryption key pairs
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```ts
|
|
87
|
-
* const keys = await encryptionKeys(storage)
|
|
88
|
-
* const currentKey = keys[0] // Most recent key
|
|
89
|
-
*
|
|
90
|
-
* // Use for token encryption
|
|
91
|
-
* const encrypted = await new EncryptJWT(payload)
|
|
92
|
-
* .setProtectedHeader({ alg: 'RSA-OAEP-512', enc: 'A256GCM' })
|
|
93
|
-
* .encrypt(currentKey.public)
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
const encryptionKeys = async (storage) => {
|
|
97
|
-
const results = [];
|
|
98
|
-
const scanner = Storage.scan(storage, ["encryption:key"]);
|
|
99
|
-
for await (const [, value] of scanner) try {
|
|
100
|
-
const publicKey = await importSPKI(value.publicKey, value.alg, { extractable: true });
|
|
101
|
-
const privateKey = await importPKCS8(value.privateKey, value.alg);
|
|
102
|
-
const jwk$1 = await exportJWK(publicKey);
|
|
103
|
-
jwk$1.kid = value.id;
|
|
104
|
-
results.push({
|
|
105
|
-
id: value.id,
|
|
106
|
-
alg: encryptionAlg,
|
|
107
|
-
created: new Date(value.created),
|
|
108
|
-
expired: value.expired ? new Date(value.expired) : void 0,
|
|
109
|
-
public: publicKey,
|
|
110
|
-
private: privateKey,
|
|
111
|
-
jwk: jwk$1
|
|
112
|
-
});
|
|
113
|
-
} catch {}
|
|
114
|
-
results.sort((a, b) => b.created.getTime() - a.created.getTime());
|
|
115
|
-
if (results.filter((item) => !item.expired).length) return results;
|
|
116
|
-
const key = await generateKeyPair(encryptionAlg, { extractable: true });
|
|
117
|
-
const serialized = {
|
|
118
|
-
id: generateSecureToken(16),
|
|
119
|
-
publicKey: await exportSPKI(key.publicKey),
|
|
120
|
-
privateKey: await exportPKCS8(key.privateKey),
|
|
121
|
-
created: Date.now(),
|
|
122
|
-
alg: encryptionAlg
|
|
123
|
-
};
|
|
124
|
-
await Storage.set(storage, ["encryption:key", serialized.id], serialized);
|
|
125
|
-
const jwk = await exportJWK(key.publicKey);
|
|
126
|
-
jwk.kid = serialized.id;
|
|
127
|
-
const newKeyPair = {
|
|
128
|
-
id: serialized.id,
|
|
129
|
-
alg: encryptionAlg,
|
|
130
|
-
created: new Date(serialized.created),
|
|
131
|
-
expired: serialized.expired ? new Date(serialized.expired) : void 0,
|
|
132
|
-
public: key.publicKey,
|
|
133
|
-
private: key.privateKey,
|
|
134
|
-
jwk
|
|
135
|
-
};
|
|
136
|
-
return [newKeyPair, ...results];
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
//#endregion
|
|
140
|
-
export { encryptionKeys, signingKeys };
|
package/dist/oauth2-B7-6Z7Lc.js
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { getRelativeUrl } from "./util-CSdHUFOo.js";
|
|
2
|
-
import { OauthError } from "./error-DgAKK7b2.js";
|
|
3
|
-
import { generatePKCE } from "./pkce-276Za_rZ.js";
|
|
4
|
-
import { generateSecureToken, timingSafeCompare } from "./random-SXMYlaVr.js";
|
|
5
|
-
|
|
6
|
-
//#region src/provider/oauth2.ts
|
|
7
|
-
/**
|
|
8
|
-
* Creates an OAuth 2.0 authentication provider.
|
|
9
|
-
* Implements the Authorization Code Grant flow with optional PKCE support.
|
|
10
|
-
*
|
|
11
|
-
* @param config - OAuth 2.0 provider configuration
|
|
12
|
-
* @returns Provider instance implementing OAuth 2.0 authentication
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts
|
|
16
|
-
* // GitHub provider with basic configuration
|
|
17
|
-
* const githubProvider = Oauth2Provider({
|
|
18
|
-
* clientID: process.env.GITHUB_CLIENT_ID,
|
|
19
|
-
* clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
20
|
-
* endpoint: {
|
|
21
|
-
* authorization: "https://github.com/login/oauth/authorize",
|
|
22
|
-
* token: "https://github.com/login/oauth/access_token"
|
|
23
|
-
* },
|
|
24
|
-
* scopes: ["user:email", "read:user"]
|
|
25
|
-
* })
|
|
26
|
-
*
|
|
27
|
-
* // Provider with PKCE and custom parameters
|
|
28
|
-
* const customProvider = Oauth2Provider({
|
|
29
|
-
* clientID: "my-client-id",
|
|
30
|
-
* clientSecret: "my-client-secret",
|
|
31
|
-
* endpoint: {
|
|
32
|
-
* authorization: "https://provider.com/oauth/authorize",
|
|
33
|
-
* token: "https://provider.com/oauth/token",
|
|
34
|
-
* jwks: "https://provider.com/.well-known/jwks.json"
|
|
35
|
-
* },
|
|
36
|
-
* scopes: ["read", "write"],
|
|
37
|
-
* pkce: true,
|
|
38
|
-
* query: {
|
|
39
|
-
* prompt: "consent",
|
|
40
|
-
* access_type: "offline"
|
|
41
|
-
* }
|
|
42
|
-
* })
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
const Oauth2Provider = (config) => {
|
|
46
|
-
const authQuery = config.query || {};
|
|
47
|
-
/**
|
|
48
|
-
* Handles the OAuth 2.0 callback logic for both GET and POST requests.
|
|
49
|
-
* Exchanges the authorization code for tokens and processes the response.
|
|
50
|
-
*/
|
|
51
|
-
const handleCallbackLogic = async (c, ctx, provider, code) => {
|
|
52
|
-
if (!(provider && code)) return c.redirect(getRelativeUrl(c, "./authorize"));
|
|
53
|
-
const tokenRequestBody = new URLSearchParams({
|
|
54
|
-
client_id: config.clientID,
|
|
55
|
-
client_secret: config.clientSecret,
|
|
56
|
-
code,
|
|
57
|
-
grant_type: "authorization_code",
|
|
58
|
-
redirect_uri: provider.redirect,
|
|
59
|
-
...provider.codeVerifier ? { code_verifier: provider.codeVerifier } : {}
|
|
60
|
-
});
|
|
61
|
-
try {
|
|
62
|
-
const response = await fetch(config.endpoint.token, {
|
|
63
|
-
method: "POST",
|
|
64
|
-
headers: {
|
|
65
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
66
|
-
Accept: "application/json"
|
|
67
|
-
},
|
|
68
|
-
body: tokenRequestBody.toString()
|
|
69
|
-
});
|
|
70
|
-
if (!response.ok) throw new Error(`Token request failed with status ${response.status}`);
|
|
71
|
-
const tokenData = await response.json();
|
|
72
|
-
if (tokenData.error) throw new OauthError(tokenData.error, tokenData.error_description || "");
|
|
73
|
-
return await ctx.success(c, {
|
|
74
|
-
clientID: config.clientID,
|
|
75
|
-
tokenset: {
|
|
76
|
-
get access() {
|
|
77
|
-
return tokenData.access_token;
|
|
78
|
-
},
|
|
79
|
-
get refresh() {
|
|
80
|
-
return tokenData.refresh_token || "";
|
|
81
|
-
},
|
|
82
|
-
get expiry() {
|
|
83
|
-
return tokenData.expires_in || 0;
|
|
84
|
-
},
|
|
85
|
-
get raw() {
|
|
86
|
-
return tokenData;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
} catch (error) {
|
|
91
|
-
if (error instanceof OauthError) throw error;
|
|
92
|
-
throw new OauthError("server_error", `Token exchange failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
return {
|
|
96
|
-
type: config.type || "oauth2",
|
|
97
|
-
init(routes, ctx) {
|
|
98
|
-
/**
|
|
99
|
-
* Initiates OAuth 2.0 authorization flow.
|
|
100
|
-
* Redirects user to the provider's authorization endpoint with proper parameters.
|
|
101
|
-
*/
|
|
102
|
-
routes.get("/authorize", async (c) => {
|
|
103
|
-
const state = generateSecureToken();
|
|
104
|
-
const pkce = config.pkce ? await generatePKCE() : void 0;
|
|
105
|
-
await ctx.set(c, "provider", 60 * 10, {
|
|
106
|
-
state,
|
|
107
|
-
redirect: getRelativeUrl(c, "./callback"),
|
|
108
|
-
codeVerifier: pkce?.verifier
|
|
109
|
-
});
|
|
110
|
-
const authorizationUrl = new URL(config.endpoint.authorization);
|
|
111
|
-
authorizationUrl.searchParams.set("client_id", config.clientID);
|
|
112
|
-
authorizationUrl.searchParams.set("redirect_uri", getRelativeUrl(c, "./callback"));
|
|
113
|
-
authorizationUrl.searchParams.set("response_type", "code");
|
|
114
|
-
authorizationUrl.searchParams.set("state", state);
|
|
115
|
-
authorizationUrl.searchParams.set("scope", config.scopes.join(" "));
|
|
116
|
-
if (pkce) {
|
|
117
|
-
authorizationUrl.searchParams.set("code_challenge", pkce.challenge);
|
|
118
|
-
authorizationUrl.searchParams.set("code_challenge_method", pkce.method);
|
|
119
|
-
}
|
|
120
|
-
for (const [key, value] of Object.entries(authQuery)) authorizationUrl.searchParams.set(key, value);
|
|
121
|
-
return c.redirect(authorizationUrl.toString());
|
|
122
|
-
});
|
|
123
|
-
/**
|
|
124
|
-
* Handles OAuth 2.0 callback via query parameters (GET request).
|
|
125
|
-
* Standard OAuth 2.0 callback method for most providers.
|
|
126
|
-
*/
|
|
127
|
-
routes.get("/callback", async (c) => {
|
|
128
|
-
const provider = await ctx.get(c, "provider");
|
|
129
|
-
const code = c.query("code");
|
|
130
|
-
const state = c.query("state");
|
|
131
|
-
const error = c.query("error");
|
|
132
|
-
if (error) throw new OauthError(error, c.query("error_description") || "");
|
|
133
|
-
if (!(provider && code) || provider.state && !timingSafeCompare(state || "", provider.state)) return c.redirect(getRelativeUrl(c, "./authorize"));
|
|
134
|
-
return await handleCallbackLogic(c, ctx, provider, code);
|
|
135
|
-
});
|
|
136
|
-
/**
|
|
137
|
-
* Handles OAuth 2.0 callback via form data (POST request).
|
|
138
|
-
* Alternative callback method supported by some providers.
|
|
139
|
-
*/
|
|
140
|
-
routes.post("/callback", async (c) => {
|
|
141
|
-
const provider = await ctx.get(c, "provider");
|
|
142
|
-
const formData = await c.formData();
|
|
143
|
-
const code = formData.get("code")?.toString();
|
|
144
|
-
const state = formData.get("state")?.toString();
|
|
145
|
-
const error = formData.get("error")?.toString();
|
|
146
|
-
if (error) throw new OauthError(error, formData.get("error_description")?.toString() || "");
|
|
147
|
-
if (!(provider && code) || provider.state && !timingSafeCompare(state || "", provider.state)) return c.redirect(getRelativeUrl(c, "./authorize"));
|
|
148
|
-
return await handleCallbackLogic(c, ctx, provider, code);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
//#endregion
|
|
155
|
-
export { Oauth2Provider };
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { Provider } from "./provider-tndlqCzp.js";
|
|
2
|
-
|
|
3
|
-
//#region src/provider/oauth2.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Configuration options for the OAuth 2.0 provider.
|
|
7
|
-
*/
|
|
8
|
-
interface Oauth2Config {
|
|
9
|
-
/**
|
|
10
|
-
* Provider type identifier for internal use.
|
|
11
|
-
* @internal
|
|
12
|
-
* @default "oauth2"
|
|
13
|
-
*/
|
|
14
|
-
readonly type?: string;
|
|
15
|
-
/**
|
|
16
|
-
* The client ID registered with the OAuth 2.0 provider.
|
|
17
|
-
* This public identifier is used in authorization requests.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```ts
|
|
21
|
-
* {
|
|
22
|
-
* clientID: "github-app-12345"
|
|
23
|
-
* }
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
readonly clientID: string;
|
|
27
|
-
/**
|
|
28
|
-
* The client secret for authenticating with the OAuth 2.0 provider.
|
|
29
|
-
* This private credential must be kept secure and not exposed to clients.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```ts
|
|
33
|
-
* {
|
|
34
|
-
* clientSecret: process.env.OAUTH_CLIENT_SECRET
|
|
35
|
-
* }
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
readonly clientSecret: string;
|
|
39
|
-
/**
|
|
40
|
-
* OAuth 2.0 endpoint URLs for the authorization and token flows.
|
|
41
|
-
*/
|
|
42
|
-
readonly endpoint: {
|
|
43
|
-
/**
|
|
44
|
-
* The authorization endpoint where users are redirected for authentication.
|
|
45
|
-
*
|
|
46
|
-
* @example "https://github.com/login/oauth/authorize"
|
|
47
|
-
*/
|
|
48
|
-
readonly authorization: string;
|
|
49
|
-
/**
|
|
50
|
-
* The token endpoint for exchanging authorization codes for access tokens.
|
|
51
|
-
*
|
|
52
|
-
* @example "https://github.com/login/oauth/access_token"
|
|
53
|
-
*/
|
|
54
|
-
readonly token: string;
|
|
55
|
-
/**
|
|
56
|
-
* Optional JWKS endpoint for verifying ID tokens.
|
|
57
|
-
* Required only if the provider returns ID tokens that need verification.
|
|
58
|
-
*
|
|
59
|
-
* @example "https://provider.com/.well-known/jwks.json"
|
|
60
|
-
*/
|
|
61
|
-
readonly jwks?: string;
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* OAuth 2.0 scopes to request during authorization.
|
|
65
|
-
* Scopes define the level of access being requested.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```ts
|
|
69
|
-
* {
|
|
70
|
-
* scopes: ["user:email", "read:user", "repo"]
|
|
71
|
-
* }
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
readonly scopes: string[];
|
|
75
|
-
/**
|
|
76
|
-
* Whether to use PKCE (Proof Key for Code Exchange) for enhanced security.
|
|
77
|
-
* Recommended for public clients and required by some providers.
|
|
78
|
-
*
|
|
79
|
-
* @default false
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```ts
|
|
83
|
-
* {
|
|
84
|
-
* pkce: true // Required for Twitter/X, recommended for mobile apps
|
|
85
|
-
* }
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
readonly pkce?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
* Additional query parameters to include in the authorization request.
|
|
91
|
-
* Useful for provider-specific parameters or customizing the auth flow.
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```ts
|
|
95
|
-
* {
|
|
96
|
-
* query: {
|
|
97
|
-
* access_type: "offline", // Request refresh token
|
|
98
|
-
* prompt: "consent", // Force consent screen
|
|
99
|
-
* hd: "mycompany.com" // Google Workspace domain
|
|
100
|
-
* }
|
|
101
|
-
* }
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
readonly query?: Record<string, string>;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* OAuth 2.0 configuration without endpoint-specific fields.
|
|
108
|
-
* Used internally for provider wrapping.
|
|
109
|
-
* @internal
|
|
110
|
-
*/
|
|
111
|
-
type Oauth2WrappedConfig = Omit<Oauth2Config, "endpoint" | "name">;
|
|
112
|
-
/**
|
|
113
|
-
* OAuth 2.0 token response containing access tokens and metadata.
|
|
114
|
-
* Provides a structured interface for token data with lazy property access.
|
|
115
|
-
* @internal
|
|
116
|
-
*/
|
|
117
|
-
interface Oauth2Token {
|
|
118
|
-
/** Access token for making authenticated API requests */
|
|
119
|
-
readonly access: string;
|
|
120
|
-
/** Refresh token for obtaining new access tokens (if provided) */
|
|
121
|
-
readonly refresh: string;
|
|
122
|
-
/** Token expiration time in seconds (if provided) */
|
|
123
|
-
readonly expiry: number;
|
|
124
|
-
/** Raw token response from the provider */
|
|
125
|
-
readonly raw: Record<string, unknown>;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* User data returned by successful OAuth 2.0 authentication.
|
|
129
|
-
*/
|
|
130
|
-
interface Oauth2UserData {
|
|
131
|
-
/** Token set containing access token, refresh token, and metadata */
|
|
132
|
-
readonly tokenset: Oauth2Token;
|
|
133
|
-
/** Client ID used for this authentication */
|
|
134
|
-
readonly clientID: string;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Creates an OAuth 2.0 authentication provider.
|
|
138
|
-
* Implements the Authorization Code Grant flow with optional PKCE support.
|
|
139
|
-
*
|
|
140
|
-
* @param config - OAuth 2.0 provider configuration
|
|
141
|
-
* @returns Provider instance implementing OAuth 2.0 authentication
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```ts
|
|
145
|
-
* // GitHub provider with basic configuration
|
|
146
|
-
* const githubProvider = Oauth2Provider({
|
|
147
|
-
* clientID: process.env.GITHUB_CLIENT_ID,
|
|
148
|
-
* clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
149
|
-
* endpoint: {
|
|
150
|
-
* authorization: "https://github.com/login/oauth/authorize",
|
|
151
|
-
* token: "https://github.com/login/oauth/access_token"
|
|
152
|
-
* },
|
|
153
|
-
* scopes: ["user:email", "read:user"]
|
|
154
|
-
* })
|
|
155
|
-
*
|
|
156
|
-
* // Provider with PKCE and custom parameters
|
|
157
|
-
* const customProvider = Oauth2Provider({
|
|
158
|
-
* clientID: "my-client-id",
|
|
159
|
-
* clientSecret: "my-client-secret",
|
|
160
|
-
* endpoint: {
|
|
161
|
-
* authorization: "https://provider.com/oauth/authorize",
|
|
162
|
-
* token: "https://provider.com/oauth/token",
|
|
163
|
-
* jwks: "https://provider.com/.well-known/jwks.json"
|
|
164
|
-
* },
|
|
165
|
-
* scopes: ["read", "write"],
|
|
166
|
-
* pkce: true,
|
|
167
|
-
* query: {
|
|
168
|
-
* prompt: "consent",
|
|
169
|
-
* access_type: "offline"
|
|
170
|
-
* }
|
|
171
|
-
* })
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
declare const Oauth2Provider: (config: Oauth2Config) => Provider<Oauth2UserData>;
|
|
175
|
-
//#endregion
|
|
176
|
-
export { Oauth2Config, Oauth2Provider, Oauth2Token, Oauth2UserData, Oauth2WrappedConfig };
|