@draftlab/auth 0.15.0 → 0.16.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.
- package/dist/esm/allow.js +26 -0
- package/dist/esm/client.js +254 -0
- package/dist/esm/core.js +597 -0
- package/dist/esm/css.d.js +0 -0
- package/dist/esm/error.js +88 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/keys.js +126 -0
- package/dist/esm/mutex.js +53 -0
- package/dist/esm/pkce.js +87 -0
- package/dist/esm/provider/apple.js +15 -0
- package/dist/esm/provider/code.js +62 -0
- package/dist/esm/provider/discord.js +15 -0
- package/dist/esm/provider/facebook.js +15 -0
- package/dist/esm/provider/github.js +15 -0
- package/dist/esm/provider/gitlab.js +15 -0
- package/dist/esm/provider/google.js +16 -0
- package/dist/esm/provider/linkedin.js +15 -0
- package/dist/esm/provider/magiclink.js +83 -0
- package/dist/esm/provider/microsoft.js +15 -0
- package/dist/esm/provider/oauth2.js +130 -0
- package/dist/esm/provider/password.js +331 -0
- package/dist/esm/provider/provider.js +18 -0
- package/dist/esm/provider/reddit.js +15 -0
- package/dist/esm/provider/slack.js +15 -0
- package/dist/esm/provider/spotify.js +15 -0
- package/dist/esm/provider/twitch.js +15 -0
- package/dist/esm/provider/vercel.js +17 -0
- package/dist/esm/random.js +40 -0
- package/dist/esm/revocation.js +27 -0
- package/dist/esm/storage/memory.js +110 -0
- package/dist/esm/storage/storage.js +56 -0
- package/dist/esm/storage/turso.js +93 -0
- package/dist/esm/storage/unstorage.js +78 -0
- package/dist/esm/subject.js +7 -0
- package/dist/esm/themes/theme.js +115 -0
- package/dist/esm/toolkit/client.js +119 -0
- package/dist/esm/toolkit/index.js +25 -0
- package/dist/esm/toolkit/providers/facebook.js +11 -0
- package/dist/esm/toolkit/providers/github.js +11 -0
- package/dist/esm/toolkit/providers/google.js +11 -0
- package/dist/esm/toolkit/providers/strategy.js +0 -0
- package/dist/esm/toolkit/storage.js +81 -0
- package/dist/esm/toolkit/utils.js +18 -0
- package/dist/esm/types.js +0 -0
- package/dist/esm/ui/base.js +478 -0
- package/dist/esm/ui/code.js +186 -0
- package/dist/esm/ui/form.js +46 -0
- package/dist/esm/ui/icon.js +242 -0
- package/dist/esm/ui/magiclink.js +158 -0
- package/dist/esm/ui/password.js +435 -0
- package/dist/esm/ui/select.js +102 -0
- package/dist/esm/util.js +59 -0
- package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
- package/dist/types/allow.d.ts.map +1 -0
- package/dist/types/client.d.ts +462 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/core.d.ts +113 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/{error.d.mts → types/error.d.ts} +95 -97
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{keys.d.mts → types/keys.d.ts} +20 -24
- package/dist/types/keys.d.ts.map +1 -0
- package/dist/types/mutex.d.ts +42 -0
- package/dist/types/mutex.d.ts.map +1 -0
- package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
- package/dist/types/pkce.d.ts.map +1 -0
- package/dist/types/provider/apple.d.ts +197 -0
- package/dist/types/provider/apple.d.ts.map +1 -0
- package/dist/types/provider/code.d.ts +288 -0
- package/dist/types/provider/code.d.ts.map +1 -0
- package/dist/types/provider/discord.d.ts +206 -0
- package/dist/types/provider/discord.d.ts.map +1 -0
- package/dist/types/provider/facebook.d.ts +200 -0
- package/dist/types/provider/facebook.d.ts.map +1 -0
- package/dist/types/provider/github.d.ts +220 -0
- package/dist/types/provider/github.d.ts.map +1 -0
- package/dist/types/provider/gitlab.d.ts +180 -0
- package/dist/types/provider/gitlab.d.ts.map +1 -0
- package/dist/types/provider/google.d.ts +158 -0
- package/dist/types/provider/google.d.ts.map +1 -0
- package/dist/types/provider/linkedin.d.ts +190 -0
- package/dist/types/provider/linkedin.d.ts.map +1 -0
- package/dist/types/provider/magiclink.d.ts +141 -0
- package/dist/types/provider/magiclink.d.ts.map +1 -0
- package/dist/types/provider/microsoft.d.ts +247 -0
- package/dist/types/provider/microsoft.d.ts.map +1 -0
- package/dist/types/provider/oauth2.d.ts +229 -0
- package/dist/types/provider/oauth2.d.ts.map +1 -0
- package/dist/types/provider/password.d.ts +408 -0
- package/dist/types/provider/password.d.ts.map +1 -0
- package/dist/types/provider/provider.d.ts +226 -0
- package/dist/types/provider/provider.d.ts.map +1 -0
- package/dist/types/provider/reddit.d.ts +159 -0
- package/dist/types/provider/reddit.d.ts.map +1 -0
- package/dist/types/provider/slack.d.ts +171 -0
- package/dist/types/provider/slack.d.ts.map +1 -0
- package/dist/types/provider/spotify.d.ts +168 -0
- package/dist/types/provider/spotify.d.ts.map +1 -0
- package/dist/types/provider/twitch.d.ts +163 -0
- package/dist/types/provider/twitch.d.ts.map +1 -0
- package/dist/types/provider/vercel.d.ts +294 -0
- package/dist/types/provider/vercel.d.ts.map +1 -0
- package/dist/{random.d.mts → types/random.d.ts} +4 -6
- package/dist/types/random.d.ts.map +1 -0
- package/dist/types/revocation.d.ts +76 -0
- package/dist/types/revocation.d.ts.map +1 -0
- package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -21
- package/dist/types/storage/memory.d.ts.map +1 -0
- package/dist/types/storage/storage.d.ts +177 -0
- package/dist/types/storage/storage.d.ts.map +1 -0
- package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -8
- package/dist/types/storage/turso.d.ts.map +1 -0
- package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
- package/dist/types/storage/unstorage.d.ts.map +1 -0
- package/dist/types/subject.d.ts +115 -0
- package/dist/types/subject.d.ts.map +1 -0
- package/dist/types/themes/theme.d.ts +207 -0
- package/dist/types/themes/theme.d.ts.map +1 -0
- package/dist/types/toolkit/client.d.ts +235 -0
- package/dist/types/toolkit/client.d.ts.map +1 -0
- package/dist/types/toolkit/index.d.ts +45 -0
- package/dist/types/toolkit/index.d.ts.map +1 -0
- package/dist/types/toolkit/providers/facebook.d.ts +8 -0
- package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
- package/dist/types/toolkit/providers/github.d.ts +8 -0
- package/dist/types/toolkit/providers/github.d.ts.map +1 -0
- package/dist/types/toolkit/providers/google.d.ts +8 -0
- package/dist/types/toolkit/providers/google.d.ts.map +1 -0
- package/dist/types/toolkit/providers/strategy.d.ts +38 -0
- package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
- package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
- package/dist/types/toolkit/storage.d.ts.map +1 -0
- package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
- package/dist/types/toolkit/utils.d.ts.map +1 -0
- package/dist/types/types.d.ts +92 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/ui/base.d.ts +18 -0
- package/dist/types/ui/base.d.ts.map +1 -0
- package/dist/types/ui/code.d.ts +43 -0
- package/dist/types/ui/code.d.ts.map +1 -0
- package/dist/types/ui/form.d.ts +24 -0
- package/dist/types/ui/form.d.ts.map +1 -0
- package/dist/types/ui/icon.d.ts +60 -0
- package/dist/types/ui/icon.d.ts.map +1 -0
- package/dist/types/ui/magiclink.d.ts +41 -0
- package/dist/types/ui/magiclink.d.ts.map +1 -0
- package/dist/types/ui/password.d.ts +43 -0
- package/dist/types/ui/password.d.ts.map +1 -0
- package/dist/types/ui/select.d.ts +33 -0
- package/dist/types/ui/select.d.ts.map +1 -0
- package/dist/{util.d.mts → types/util.d.ts} +11 -13
- package/dist/types/util.d.ts.map +1 -0
- package/package.json +10 -16
- package/dist/adapters/node.d.mts +0 -18
- package/dist/adapters/node.mjs +0 -69
- package/dist/allow.mjs +0 -63
- package/dist/client.d.mts +0 -456
- package/dist/client.mjs +0 -283
- package/dist/core.d.mts +0 -110
- package/dist/core.mjs +0 -595
- package/dist/error.mjs +0 -237
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -3
- package/dist/keys.mjs +0 -146
- package/dist/mutex.d.mts +0 -44
- package/dist/mutex.mjs +0 -110
- package/dist/pkce.mjs +0 -157
- package/dist/provider/apple.d.mts +0 -111
- package/dist/provider/apple.mjs +0 -164
- package/dist/provider/code.d.mts +0 -228
- package/dist/provider/code.mjs +0 -246
- package/dist/provider/discord.d.mts +0 -146
- package/dist/provider/discord.mjs +0 -156
- package/dist/provider/facebook.d.mts +0 -142
- package/dist/provider/facebook.mjs +0 -150
- package/dist/provider/github.d.mts +0 -140
- package/dist/provider/github.mjs +0 -169
- package/dist/provider/gitlab.d.mts +0 -106
- package/dist/provider/gitlab.mjs +0 -147
- package/dist/provider/google.d.mts +0 -112
- package/dist/provider/google.mjs +0 -109
- package/dist/provider/linkedin.d.mts +0 -132
- package/dist/provider/linkedin.mjs +0 -142
- package/dist/provider/magiclink.d.mts +0 -89
- package/dist/provider/magiclink.mjs +0 -143
- package/dist/provider/microsoft.d.mts +0 -178
- package/dist/provider/microsoft.mjs +0 -177
- package/dist/provider/oauth2.d.mts +0 -176
- package/dist/provider/oauth2.mjs +0 -222
- package/dist/provider/passkey.d.mts +0 -104
- package/dist/provider/passkey.mjs +0 -320
- package/dist/provider/password.d.mts +0 -412
- package/dist/provider/password.mjs +0 -363
- package/dist/provider/provider.d.mts +0 -227
- package/dist/provider/provider.mjs +0 -44
- package/dist/provider/reddit.d.mts +0 -107
- package/dist/provider/reddit.mjs +0 -127
- package/dist/provider/slack.d.mts +0 -114
- package/dist/provider/slack.mjs +0 -138
- package/dist/provider/spotify.d.mts +0 -113
- package/dist/provider/spotify.mjs +0 -135
- package/dist/provider/totp.d.mts +0 -112
- package/dist/provider/totp.mjs +0 -191
- package/dist/provider/twitch.d.mts +0 -108
- package/dist/provider/twitch.mjs +0 -131
- package/dist/provider/vercel.d.mts +0 -177
- package/dist/provider/vercel.mjs +0 -230
- package/dist/random.mjs +0 -86
- package/dist/revocation.d.mts +0 -55
- package/dist/revocation.mjs +0 -63
- package/dist/router/context.d.mts +0 -21
- package/dist/router/context.mjs +0 -193
- package/dist/router/cookies.d.mts +0 -8
- package/dist/router/cookies.mjs +0 -13
- package/dist/router/index.d.mts +0 -21
- package/dist/router/index.mjs +0 -107
- package/dist/router/matcher.d.mts +0 -15
- package/dist/router/matcher.mjs +0 -76
- package/dist/router/middleware/cors.d.mts +0 -15
- package/dist/router/middleware/cors.mjs +0 -114
- package/dist/router/safe-request.d.mts +0 -52
- package/dist/router/safe-request.mjs +0 -160
- package/dist/router/types.d.mts +0 -67
- package/dist/router/types.mjs +0 -1
- package/dist/router/variables.d.mts +0 -12
- package/dist/router/variables.mjs +0 -20
- package/dist/storage/memory.mjs +0 -125
- package/dist/storage/storage.d.mts +0 -179
- package/dist/storage/storage.mjs +0 -104
- package/dist/storage/turso.mjs +0 -117
- package/dist/storage/unstorage.mjs +0 -103
- package/dist/subject.d.mts +0 -62
- package/dist/subject.mjs +0 -36
- package/dist/themes/theme.d.mts +0 -209
- package/dist/themes/theme.mjs +0 -120
- package/dist/toolkit/client.d.mts +0 -169
- package/dist/toolkit/client.mjs +0 -209
- package/dist/toolkit/index.d.mts +0 -9
- package/dist/toolkit/index.mjs +0 -9
- package/dist/toolkit/providers/facebook.d.mts +0 -12
- package/dist/toolkit/providers/facebook.mjs +0 -16
- package/dist/toolkit/providers/github.d.mts +0 -12
- package/dist/toolkit/providers/github.mjs +0 -16
- package/dist/toolkit/providers/google.d.mts +0 -12
- package/dist/toolkit/providers/google.mjs +0 -20
- package/dist/toolkit/providers/strategy.d.mts +0 -40
- package/dist/toolkit/providers/strategy.mjs +0 -1
- package/dist/toolkit/storage.mjs +0 -157
- package/dist/toolkit/utils.mjs +0 -30
- package/dist/types.d.mts +0 -94
- package/dist/types.mjs +0 -1
- package/dist/ui/base.d.mts +0 -30
- package/dist/ui/base.mjs +0 -407
- package/dist/ui/code.d.mts +0 -43
- package/dist/ui/code.mjs +0 -173
- package/dist/ui/form.d.mts +0 -32
- package/dist/ui/form.mjs +0 -49
- package/dist/ui/icon.d.mts +0 -58
- package/dist/ui/icon.mjs +0 -247
- package/dist/ui/magiclink.d.mts +0 -41
- package/dist/ui/magiclink.mjs +0 -152
- package/dist/ui/passkey.d.mts +0 -27
- package/dist/ui/passkey.mjs +0 -323
- package/dist/ui/password.d.mts +0 -42
- package/dist/ui/password.mjs +0 -402
- package/dist/ui/select.d.mts +0 -34
- package/dist/ui/select.mjs +0 -98
- package/dist/ui/totp.d.mts +0 -34
- package/dist/ui/totp.mjs +0 -270
- package/dist/util.mjs +0 -128
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { Provider } from "./provider.mjs";
|
|
2
|
-
import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/provider/vercel.d.ts
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Configuration options for Vercel OAuth 2.0 + OpenID Connect provider.
|
|
8
|
-
* Extends the base OAuth 2.0 configuration with Vercel-specific documentation.
|
|
9
|
-
*/
|
|
10
|
-
interface VercelConfig extends Oauth2WrappedConfig {
|
|
11
|
-
/**
|
|
12
|
-
* Vercel OAuth App client ID.
|
|
13
|
-
* Found in your Vercel App settings under the Authentication tab.
|
|
14
|
-
*
|
|
15
|
-
* To create an app:
|
|
16
|
-
* 1. Go to Team Settings → Apps → Create
|
|
17
|
-
* 2. Configure app details and callback URLs
|
|
18
|
-
* 3. Copy the Client ID from the Authentication tab
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```ts
|
|
22
|
-
* {
|
|
23
|
-
* clientID: "oac_abc123xyz789" // Vercel OAuth App Client ID
|
|
24
|
-
* }
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
readonly clientID: string;
|
|
28
|
-
/**
|
|
29
|
-
* Vercel OAuth App client secret.
|
|
30
|
-
* Generated in your Vercel App settings under the Authentication tab.
|
|
31
|
-
* Keep this secure and never expose it to client-side code.
|
|
32
|
-
*
|
|
33
|
-
* To generate:
|
|
34
|
-
* 1. Go to your app's Authentication tab
|
|
35
|
-
* 2. Click "Generate Client Secret"
|
|
36
|
-
* 3. Copy and store securely (shown only once)
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* {
|
|
41
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET
|
|
42
|
-
* }
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
readonly clientSecret: string;
|
|
46
|
-
/**
|
|
47
|
-
* OpenID Connect scopes to request.
|
|
48
|
-
* Controls what user information is included in the ID Token.
|
|
49
|
-
*
|
|
50
|
-
* Available scopes (must be enabled in Vercel App dashboard first):
|
|
51
|
-
* - `openid`: Required for ID Token issuance
|
|
52
|
-
* - `email`: User's email address
|
|
53
|
-
* - `profile`: Name, username, and avatar
|
|
54
|
-
* - `offline_access`: Refresh token for long-lived access (optional)
|
|
55
|
-
*
|
|
56
|
-
* **Important**: Enable scopes in: Vercel App → Permissions page
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```ts
|
|
60
|
-
* {
|
|
61
|
-
* // Basic scopes (usually sufficient)
|
|
62
|
-
* scopes: ["openid", "email", "profile"]
|
|
63
|
-
*
|
|
64
|
-
* // With refresh token support (enable offline_access in dashboard first)
|
|
65
|
-
* scopes: ["openid", "email", "profile", "offline_access"]
|
|
66
|
-
* }
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
readonly scopes: string[];
|
|
70
|
-
/**
|
|
71
|
-
* Additional query parameters for Vercel OAuth authorization.
|
|
72
|
-
* Useful for customizing the authorization flow.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```ts
|
|
76
|
-
* {
|
|
77
|
-
* query: {
|
|
78
|
-
* prompt: "consent" // Force consent screen every time
|
|
79
|
-
* }
|
|
80
|
-
* }
|
|
81
|
-
* ```
|
|
82
|
-
*/
|
|
83
|
-
readonly query?: Record<string, string>;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Creates a Vercel OAuth 2.0 + OpenID Connect authentication provider.
|
|
87
|
-
* Implements "Sign in with Vercel" for user authentication.
|
|
88
|
-
*
|
|
89
|
-
* This provider uses the standard OAuth 2.0 Authorization Code Grant flow
|
|
90
|
-
* with PKCE (Proof Key for Code Exchange) for enhanced security.
|
|
91
|
-
*
|
|
92
|
-
* @param config - Vercel OAuth 2.0 configuration
|
|
93
|
-
* @returns OAuth 2.0 provider configured for Vercel
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```ts
|
|
97
|
-
* // Basic Vercel authentication (email + profile)
|
|
98
|
-
* const basicVercel = VercelProvider({
|
|
99
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
100
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
101
|
-
* scopes: ["openid", "email", "profile"]
|
|
102
|
-
* })
|
|
103
|
-
*
|
|
104
|
-
* // Vercel with refresh token support
|
|
105
|
-
* const vercelWithRefresh = VercelProvider({
|
|
106
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
107
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
108
|
-
* scopes: ["openid", "email", "profile", "offline_access"]
|
|
109
|
-
* })
|
|
110
|
-
*
|
|
111
|
-
* // Minimal setup (only user ID in ID Token)
|
|
112
|
-
* const minimalVercel = VercelProvider({
|
|
113
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
114
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
115
|
-
* scopes: ["openid"] // Only sub claim in ID Token
|
|
116
|
-
* })
|
|
117
|
-
*
|
|
118
|
-
* // Using the tokens in your app
|
|
119
|
-
* export default issuer({
|
|
120
|
-
* providers: { vercel: vercelWithRefresh },
|
|
121
|
-
* success: async (ctx, value) => {
|
|
122
|
-
* if (value.provider === "vercel") {
|
|
123
|
-
* const idToken = value.tokenset.raw.id_token as string | undefined
|
|
124
|
-
* const accessToken = value.tokenset.access
|
|
125
|
-
* const refreshToken = value.tokenset.refresh
|
|
126
|
-
*
|
|
127
|
-
* if (idToken) {
|
|
128
|
-
* // Decode ID Token to access user claims
|
|
129
|
-
* // (Already validated by oauth2.ts - signature, issuer, audience, exp)
|
|
130
|
-
* const claims = JSON.parse(
|
|
131
|
-
* Buffer.from(idToken.split('.')[1], 'base64').toString()
|
|
132
|
-
* )
|
|
133
|
-
*
|
|
134
|
-
* // Claims available (depending on scopes):
|
|
135
|
-
* // - sub: Vercel user ID (always present)
|
|
136
|
-
* // - email: user@example.com (if email scope)
|
|
137
|
-
* // - name: "John Doe" (if profile scope)
|
|
138
|
-
* // - picture: "https://..." (if profile scope)
|
|
139
|
-
* // - preferred_username: "johndoe" (if profile scope)
|
|
140
|
-
*
|
|
141
|
-
* // Optionally call Vercel API for more data
|
|
142
|
-
* const userRes = await fetch('https://api.vercel.com/v2/user', {
|
|
143
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
144
|
-
* })
|
|
145
|
-
* const user = await userRes.json()
|
|
146
|
-
*
|
|
147
|
-
* // Get user's teams
|
|
148
|
-
* const teamsRes = await fetch('https://api.vercel.com/v2/teams', {
|
|
149
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
150
|
-
* })
|
|
151
|
-
* const teams = await teamsRes.json()
|
|
152
|
-
*
|
|
153
|
-
* return ctx.subject("user", {
|
|
154
|
-
* vercelId: claims.sub,
|
|
155
|
-
* email: claims.email,
|
|
156
|
-
* name: claims.name,
|
|
157
|
-
* username: claims.preferred_username,
|
|
158
|
-
* avatar: claims.picture,
|
|
159
|
-
* teamCount: teams.teams?.length || 0
|
|
160
|
-
* })
|
|
161
|
-
* }
|
|
162
|
-
* }
|
|
163
|
-
* }
|
|
164
|
-
* })
|
|
165
|
-
* ```
|
|
166
|
-
*
|
|
167
|
-
* @remarks
|
|
168
|
-
* - Requires creating a Vercel App in Team Settings → Apps
|
|
169
|
-
* - PKCE is enabled by default for enhanced security
|
|
170
|
-
* - ID Token is automatically validated (signature, issuer, audience, expiration)
|
|
171
|
-
* - Access tokens expire after 1 hour
|
|
172
|
-
* - Refresh tokens rotate on each use and last 30 days
|
|
173
|
-
* - The `openid` scope is required for ID Token issuance
|
|
174
|
-
*/
|
|
175
|
-
declare const VercelProvider: (config: VercelConfig) => Provider<Oauth2UserData>;
|
|
176
|
-
//#endregion
|
|
177
|
-
export { VercelConfig, VercelProvider };
|
package/dist/provider/vercel.mjs
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { Oauth2Provider } from "./oauth2.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/provider/vercel.ts
|
|
4
|
-
/**
|
|
5
|
-
* Vercel OAuth 2.0 + OpenID Connect authentication provider for Draft Auth.
|
|
6
|
-
* Implements "Sign in with Vercel" for user authentication.
|
|
7
|
-
*
|
|
8
|
-
* ## Quick Setup
|
|
9
|
-
*
|
|
10
|
-
* ```ts
|
|
11
|
-
* import { VercelProvider } from "@draftlab/auth/provider/vercel"
|
|
12
|
-
*
|
|
13
|
-
* export default issuer({
|
|
14
|
-
* basePath: "/auth", // Important for callback URL
|
|
15
|
-
* providers: {
|
|
16
|
-
* vercel: VercelProvider({
|
|
17
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
18
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
19
|
-
* scopes: ["openid", "email", "profile"]
|
|
20
|
-
* })
|
|
21
|
-
* }
|
|
22
|
-
* })
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
|
|
26
|
-
* - Example: `http://localhost:3000/auth/vercel/callback`
|
|
27
|
-
* - Production: `https://yourapp.com/auth/vercel/callback`
|
|
28
|
-
*
|
|
29
|
-
* ## Creating a Vercel App
|
|
30
|
-
*
|
|
31
|
-
* Before using this provider, create a Vercel App in your dashboard:
|
|
32
|
-
*
|
|
33
|
-
* 1. Go to **Team Settings** → **Apps** → **Create**
|
|
34
|
-
* 2. Fill in app name, description, and logo
|
|
35
|
-
* 3. Add **Authorization Callback URLs**:
|
|
36
|
-
* - Development: `http://localhost:3000/auth/vercel/callback`
|
|
37
|
-
* - Production: `https://yourapp.com/auth/vercel/callback`
|
|
38
|
-
* - Pattern: `{baseURL}{basePath}/{provider}/callback`
|
|
39
|
-
* 4. Configure **Scopes** in the app's Permissions page:
|
|
40
|
-
* - ✅ openid (Required)
|
|
41
|
-
* - ✅ email
|
|
42
|
-
* - ✅ profile
|
|
43
|
-
* - ✅ offline_access (optional, for refresh tokens)
|
|
44
|
-
* 5. Generate a **Client Secret** in the Authentication tab
|
|
45
|
-
* 6. Copy the **Client ID** and **Client Secret**
|
|
46
|
-
*
|
|
47
|
-
* **Important**: You must enable the scopes in the Vercel App dashboard before requesting them!
|
|
48
|
-
*
|
|
49
|
-
* ## Available Scopes
|
|
50
|
-
*
|
|
51
|
-
* - `openid` - **Required**. Enables ID Token issuance for user identification
|
|
52
|
-
* - `email` - Access user's email address in ID Token
|
|
53
|
-
* - `profile` - Access user's name, username, and avatar in ID Token
|
|
54
|
-
* - `offline_access` - Issue a Refresh Token for long-lived access (30 days)
|
|
55
|
-
*
|
|
56
|
-
* ## Tokens Returned
|
|
57
|
-
*
|
|
58
|
-
* - **ID Token**: Signed JWT with user identity claims (verified automatically)
|
|
59
|
-
* - **Access Token**: Bearer token for Vercel API calls (1 hour duration)
|
|
60
|
-
* - **Refresh Token**: Rotates on each use (30 days, requires offline_access scope)
|
|
61
|
-
*
|
|
62
|
-
* ## User Data Access
|
|
63
|
-
*
|
|
64
|
-
* ```ts
|
|
65
|
-
* success: async (ctx, value) => {
|
|
66
|
-
* if (value.provider === "vercel") {
|
|
67
|
-
* // ID Token is automatically validated (signature, issuer, audience, expiration)
|
|
68
|
-
* const idToken = value.tokenset.raw.id_token as string | undefined
|
|
69
|
-
* const accessToken = value.tokenset.access
|
|
70
|
-
* const refreshToken = value.tokenset.refresh
|
|
71
|
-
*
|
|
72
|
-
* // Decode ID Token to access user claims
|
|
73
|
-
* if (idToken) {
|
|
74
|
-
* const claims = JSON.parse(
|
|
75
|
-
* Buffer.from(idToken.split('.')[1], 'base64').toString()
|
|
76
|
-
* )
|
|
77
|
-
*
|
|
78
|
-
* // Claims available (depending on scopes):
|
|
79
|
-
* // - sub: Unique Vercel user ID (always present)
|
|
80
|
-
* // - email: User's email (if email scope granted)
|
|
81
|
-
* // - name: User's full name (if profile scope granted)
|
|
82
|
-
* // - picture: Avatar URL (if profile scope granted)
|
|
83
|
-
* // - preferred_username: Vercel username (if profile scope granted)
|
|
84
|
-
*
|
|
85
|
-
* return ctx.subject("user", {
|
|
86
|
-
* email: claims.email || claims.sub
|
|
87
|
-
* })
|
|
88
|
-
* }
|
|
89
|
-
* }
|
|
90
|
-
* }
|
|
91
|
-
* ```
|
|
92
|
-
*
|
|
93
|
-
* ## Calling Vercel API
|
|
94
|
-
*
|
|
95
|
-
* Use the access token to call Vercel's REST API:
|
|
96
|
-
*
|
|
97
|
-
* ```ts
|
|
98
|
-
* // Get user information
|
|
99
|
-
* const userRes = await fetch('https://api.vercel.com/v2/user', {
|
|
100
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
101
|
-
* })
|
|
102
|
-
*
|
|
103
|
-
* // Get user's teams
|
|
104
|
-
* const teamsRes = await fetch('https://api.vercel.com/v2/teams', {
|
|
105
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
106
|
-
* })
|
|
107
|
-
*
|
|
108
|
-
* // Get projects (requires appropriate permissions)
|
|
109
|
-
* const projectsRes = await fetch('https://api.vercel.com/v9/projects', {
|
|
110
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
111
|
-
* })
|
|
112
|
-
* ```
|
|
113
|
-
*
|
|
114
|
-
* ## Consent Page
|
|
115
|
-
*
|
|
116
|
-
* The first time a user signs in, Vercel shows a consent page with:
|
|
117
|
-
* - Your app's name and logo
|
|
118
|
-
* - Requested scopes and permissions
|
|
119
|
-
* - Allow/Cancel buttons
|
|
120
|
-
*
|
|
121
|
-
* If the user grants access, they're redirected back with an authorization code.
|
|
122
|
-
* If they cancel, they're redirected with an error parameter.
|
|
123
|
-
*
|
|
124
|
-
* @packageDocumentation
|
|
125
|
-
*/
|
|
126
|
-
/**
|
|
127
|
-
* Creates a Vercel OAuth 2.0 + OpenID Connect authentication provider.
|
|
128
|
-
* Implements "Sign in with Vercel" for user authentication.
|
|
129
|
-
*
|
|
130
|
-
* This provider uses the standard OAuth 2.0 Authorization Code Grant flow
|
|
131
|
-
* with PKCE (Proof Key for Code Exchange) for enhanced security.
|
|
132
|
-
*
|
|
133
|
-
* @param config - Vercel OAuth 2.0 configuration
|
|
134
|
-
* @returns OAuth 2.0 provider configured for Vercel
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* ```ts
|
|
138
|
-
* // Basic Vercel authentication (email + profile)
|
|
139
|
-
* const basicVercel = VercelProvider({
|
|
140
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
141
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
142
|
-
* scopes: ["openid", "email", "profile"]
|
|
143
|
-
* })
|
|
144
|
-
*
|
|
145
|
-
* // Vercel with refresh token support
|
|
146
|
-
* const vercelWithRefresh = VercelProvider({
|
|
147
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
148
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
149
|
-
* scopes: ["openid", "email", "profile", "offline_access"]
|
|
150
|
-
* })
|
|
151
|
-
*
|
|
152
|
-
* // Minimal setup (only user ID in ID Token)
|
|
153
|
-
* const minimalVercel = VercelProvider({
|
|
154
|
-
* clientID: process.env.VERCEL_CLIENT_ID,
|
|
155
|
-
* clientSecret: process.env.VERCEL_CLIENT_SECRET,
|
|
156
|
-
* scopes: ["openid"] // Only sub claim in ID Token
|
|
157
|
-
* })
|
|
158
|
-
*
|
|
159
|
-
* // Using the tokens in your app
|
|
160
|
-
* export default issuer({
|
|
161
|
-
* providers: { vercel: vercelWithRefresh },
|
|
162
|
-
* success: async (ctx, value) => {
|
|
163
|
-
* if (value.provider === "vercel") {
|
|
164
|
-
* const idToken = value.tokenset.raw.id_token as string | undefined
|
|
165
|
-
* const accessToken = value.tokenset.access
|
|
166
|
-
* const refreshToken = value.tokenset.refresh
|
|
167
|
-
*
|
|
168
|
-
* if (idToken) {
|
|
169
|
-
* // Decode ID Token to access user claims
|
|
170
|
-
* // (Already validated by oauth2.ts - signature, issuer, audience, exp)
|
|
171
|
-
* const claims = JSON.parse(
|
|
172
|
-
* Buffer.from(idToken.split('.')[1], 'base64').toString()
|
|
173
|
-
* )
|
|
174
|
-
*
|
|
175
|
-
* // Claims available (depending on scopes):
|
|
176
|
-
* // - sub: Vercel user ID (always present)
|
|
177
|
-
* // - email: user@example.com (if email scope)
|
|
178
|
-
* // - name: "John Doe" (if profile scope)
|
|
179
|
-
* // - picture: "https://..." (if profile scope)
|
|
180
|
-
* // - preferred_username: "johndoe" (if profile scope)
|
|
181
|
-
*
|
|
182
|
-
* // Optionally call Vercel API for more data
|
|
183
|
-
* const userRes = await fetch('https://api.vercel.com/v2/user', {
|
|
184
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
185
|
-
* })
|
|
186
|
-
* const user = await userRes.json()
|
|
187
|
-
*
|
|
188
|
-
* // Get user's teams
|
|
189
|
-
* const teamsRes = await fetch('https://api.vercel.com/v2/teams', {
|
|
190
|
-
* headers: { Authorization: `Bearer ${accessToken}` }
|
|
191
|
-
* })
|
|
192
|
-
* const teams = await teamsRes.json()
|
|
193
|
-
*
|
|
194
|
-
* return ctx.subject("user", {
|
|
195
|
-
* vercelId: claims.sub,
|
|
196
|
-
* email: claims.email,
|
|
197
|
-
* name: claims.name,
|
|
198
|
-
* username: claims.preferred_username,
|
|
199
|
-
* avatar: claims.picture,
|
|
200
|
-
* teamCount: teams.teams?.length || 0
|
|
201
|
-
* })
|
|
202
|
-
* }
|
|
203
|
-
* }
|
|
204
|
-
* }
|
|
205
|
-
* })
|
|
206
|
-
* ```
|
|
207
|
-
*
|
|
208
|
-
* @remarks
|
|
209
|
-
* - Requires creating a Vercel App in Team Settings → Apps
|
|
210
|
-
* - PKCE is enabled by default for enhanced security
|
|
211
|
-
* - ID Token is automatically validated (signature, issuer, audience, expiration)
|
|
212
|
-
* - Access tokens expire after 1 hour
|
|
213
|
-
* - Refresh tokens rotate on each use and last 30 days
|
|
214
|
-
* - The `openid` scope is required for ID Token issuance
|
|
215
|
-
*/
|
|
216
|
-
const VercelProvider = (config) => {
|
|
217
|
-
return Oauth2Provider({
|
|
218
|
-
...config,
|
|
219
|
-
type: "vercel",
|
|
220
|
-
endpoint: {
|
|
221
|
-
authorization: "https://vercel.com/oauth/authorize",
|
|
222
|
-
token: "https://api.vercel.com/login/oauth/token",
|
|
223
|
-
jwks: "https://vercel.com/.well-known/jwks.json"
|
|
224
|
-
},
|
|
225
|
-
pkce: true
|
|
226
|
-
});
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
//#endregion
|
|
230
|
-
export { VercelProvider };
|
package/dist/random.mjs
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { timingSafeEqual } from "node:crypto";
|
|
2
|
-
|
|
3
|
-
//#region src/random.ts
|
|
4
|
-
/**
|
|
5
|
-
* Cryptographic utilities for secure random generation and comparison operations.
|
|
6
|
-
* These functions are designed to prevent timing attacks and provide unbiased randomness.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Generates a cryptographically secure token with enhanced entropy.
|
|
10
|
-
* Uses Web Crypto API and provides 256 bits of entropy
|
|
11
|
-
*
|
|
12
|
-
* @param length - Length of random data in bytes (default: 32 for 256-bit security)
|
|
13
|
-
* @returns Base64url-encoded secure token
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```ts
|
|
17
|
-
* const authCode = generateSecureToken()
|
|
18
|
-
* // Returns: "7B8kJ9mN3pQ2rS5tU8vW0xY1zA3bC6dE9fG2hI5jK8lM" (example)
|
|
19
|
-
*
|
|
20
|
-
* const refreshToken = generateSecureToken(24) // 192-bit token
|
|
21
|
-
* // Returns: "4A7bC9dF2gH5iJ8kL1mN4pQ7rS0tU" (example)
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
const generateSecureToken = (length = 32) => {
|
|
25
|
-
if (length <= 0 || !Number.isInteger(length)) throw new RangeError("Token length must be a positive integer");
|
|
26
|
-
const randomBytes$1 = new Uint8Array(length);
|
|
27
|
-
crypto.getRandomValues(randomBytes$1);
|
|
28
|
-
return btoa(String.fromCharCode.apply(null, Array.from(randomBytes$1))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Generates a cryptographically secure string of random digits without modulo bias.
|
|
32
|
-
* Uses rejection sampling to ensure each digit (0-9) has an equal probability of being selected.
|
|
33
|
-
*
|
|
34
|
-
* @param length - Number of digits to generate (must be positive)
|
|
35
|
-
* @returns String containing exactly the specified number of random digits
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const pinCode = generateUnbiasedDigits(6)
|
|
40
|
-
* // Returns: "492847" (example - actual result is random)
|
|
41
|
-
*
|
|
42
|
-
* const shortCode = generateUnbiasedDigits(4)
|
|
43
|
-
* // Returns: "7291" (example - actual result is random)
|
|
44
|
-
* ```
|
|
45
|
-
*
|
|
46
|
-
* @throws {RangeError} If length is not a positive number
|
|
47
|
-
*/
|
|
48
|
-
const generateUnbiasedDigits = (length) => {
|
|
49
|
-
if (length <= 0 || !Number.isInteger(length)) throw new RangeError("Length must be a positive integer");
|
|
50
|
-
const result = [];
|
|
51
|
-
while (result.length < length) {
|
|
52
|
-
const buffer = crypto.getRandomValues(new Uint8Array(length * 2));
|
|
53
|
-
for (const byte of buffer) if (byte < 250 && result.length < length) result.push(byte % 10);
|
|
54
|
-
}
|
|
55
|
-
return result.join("");
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* Performs a timing-safe comparison of two strings to prevent timing attacks.
|
|
59
|
-
* Always takes the same amount of time regardless of where the strings differ,
|
|
60
|
-
* making it safe for comparing sensitive values like tokens or passwords.
|
|
61
|
-
*
|
|
62
|
-
* @param a - First string to compare
|
|
63
|
-
* @param b - Second string to compare
|
|
64
|
-
* @returns True if strings are identical, false otherwise
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* ```ts
|
|
68
|
-
* // Safe for comparing sensitive values
|
|
69
|
-
* const isValidToken = timingSafeCompare(userToken, expectedToken)
|
|
70
|
-
*
|
|
71
|
-
* // Safe for password verification
|
|
72
|
-
* const isValidPassword = timingSafeCompare(hashedInput, storedHash)
|
|
73
|
-
*
|
|
74
|
-
* // Returns false for different types or lengths
|
|
75
|
-
* timingSafeCompare("abc", 123 as any) // false
|
|
76
|
-
* timingSafeCompare("abc", "abcd") // false
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
const timingSafeCompare = (a, b) => {
|
|
80
|
-
if (typeof a !== "string" || typeof b !== "string") return false;
|
|
81
|
-
if (a.length !== b.length) return false;
|
|
82
|
-
return timingSafeEqual(Buffer.from(a), Buffer.from(b));
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
//#endregion
|
|
86
|
-
export { generateSecureToken, generateUnbiasedDigits, timingSafeCompare };
|
package/dist/revocation.d.mts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { StorageAdapter } from "./storage/storage.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/revocation.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Data stored for a revoked token.
|
|
7
|
-
* Tracks when the token was revoked and when it naturally expires.
|
|
8
|
-
*/
|
|
9
|
-
interface RevocationRecord {
|
|
10
|
-
/** Timestamp when the token was revoked (milliseconds) */
|
|
11
|
-
revokedAt: number;
|
|
12
|
-
/** Timestamp when the token naturally expires (milliseconds) */
|
|
13
|
-
expiresAt: number;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Token revocation manager.
|
|
17
|
-
* Provides methods to revoke tokens and check if a token has been revoked.
|
|
18
|
-
*/
|
|
19
|
-
declare const Revocation: {
|
|
20
|
-
/**
|
|
21
|
-
* Revokes a token, preventing it from being used even if not yet expired.
|
|
22
|
-
*
|
|
23
|
-
* @param storage - Storage adapter to use
|
|
24
|
-
* @param token - The token to revoke (access or refresh token)
|
|
25
|
-
* @param expiresAt - When the token naturally expires (milliseconds since epoch)
|
|
26
|
-
* @returns Promise that resolves when revocation is stored
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```ts
|
|
30
|
-
* // Revoke a refresh token on logout
|
|
31
|
-
* await Revocation.revoke(storage, refreshToken, expiresAt)
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
readonly revoke: (storage: StorageAdapter, token: string, expiresAt: number) => Promise<void>;
|
|
35
|
-
/**
|
|
36
|
-
* Checks if a token has been revoked.
|
|
37
|
-
* Returns false if token is not in revocation list (never revoked or already expired).
|
|
38
|
-
*
|
|
39
|
-
* @param storage - Storage adapter to use
|
|
40
|
-
* @param token - The token to check
|
|
41
|
-
* @returns Promise resolving to true if token is revoked, false otherwise
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* // Check if token was revoked before using it
|
|
46
|
-
* const isRevoked = await Revocation.isRevoked(storage, accessToken)
|
|
47
|
-
* if (isRevoked) {
|
|
48
|
-
* throw new InvalidAccessTokenError()
|
|
49
|
-
* }
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
readonly isRevoked: (storage: StorageAdapter, token: string) => Promise<boolean>;
|
|
53
|
-
};
|
|
54
|
-
//#endregion
|
|
55
|
-
export { Revocation, RevocationRecord };
|
package/dist/revocation.mjs
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Storage } from "./storage/storage.mjs";
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
|
-
|
|
4
|
-
//#region src/revocation.ts
|
|
5
|
-
/**
|
|
6
|
-
* Token revocation management for Draft Auth.
|
|
7
|
-
* Handles blacklisting of revoked tokens to prevent their use.
|
|
8
|
-
*
|
|
9
|
-
* ## Overview
|
|
10
|
-
*
|
|
11
|
-
* Revocation allows users to invalidate specific tokens before their natural expiration.
|
|
12
|
-
* This is essential for logout functionality and security in case of token compromise.
|
|
13
|
-
*
|
|
14
|
-
* ## Storage Structure
|
|
15
|
-
*
|
|
16
|
-
* Revoked tokens are stored with their expiration time to allow automatic cleanup:
|
|
17
|
-
* ```
|
|
18
|
-
* revocation:token:{tokenHash} → { revokedAt: timestamp, expiresAt: timestamp }
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* ## Security Considerations
|
|
22
|
-
*
|
|
23
|
-
* - Revoked tokens are checked on every use
|
|
24
|
-
* - Storage automatically cleans up expired revocations
|
|
25
|
-
* - Hash tokens for storage to reduce memory usage
|
|
26
|
-
* - Use constant-time comparison for hash verification
|
|
27
|
-
*
|
|
28
|
-
* @packageDocumentation
|
|
29
|
-
*/
|
|
30
|
-
/**
|
|
31
|
-
* Hashes a token for storage.
|
|
32
|
-
* Uses SHA-256 to reduce storage size and prevent exposure of full token value.
|
|
33
|
-
*
|
|
34
|
-
* @param token - The token to hash
|
|
35
|
-
* @returns SHA-256 hash of the token
|
|
36
|
-
*
|
|
37
|
-
* @internal
|
|
38
|
-
*/
|
|
39
|
-
const hashToken = (token) => {
|
|
40
|
-
return createHash("sha256").update(token).digest("hex");
|
|
41
|
-
};
|
|
42
|
-
/**
|
|
43
|
-
* Token revocation manager.
|
|
44
|
-
* Provides methods to revoke tokens and check if a token has been revoked.
|
|
45
|
-
*/
|
|
46
|
-
const Revocation = {
|
|
47
|
-
revoke: async (storage, token, expiresAt) => {
|
|
48
|
-
const key = ["revocation:token", hashToken(token)];
|
|
49
|
-
const record = {
|
|
50
|
-
revokedAt: Date.now(),
|
|
51
|
-
expiresAt
|
|
52
|
-
};
|
|
53
|
-
const ttlSeconds = Math.ceil((expiresAt - Date.now()) / 1e3);
|
|
54
|
-
await Storage.set(storage, key, record, Math.max(1, ttlSeconds));
|
|
55
|
-
},
|
|
56
|
-
isRevoked: async (storage, token) => {
|
|
57
|
-
const key = ["revocation:token", hashToken(token)];
|
|
58
|
-
return !!await Storage.get(storage, key);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
//#endregion
|
|
63
|
-
export { Revocation };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { RouterContext, VariableMap } from "./types.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/router/context.d.ts
|
|
4
|
-
declare class ContextBuilder<TVariables extends VariableMap = VariableMap> {
|
|
5
|
-
private readonly request;
|
|
6
|
-
private readonly matchedParams;
|
|
7
|
-
private readonly searchParams;
|
|
8
|
-
private readonly cookies;
|
|
9
|
-
private readonly variableManager;
|
|
10
|
-
private readonly responseHeaders;
|
|
11
|
-
private status;
|
|
12
|
-
private finalized;
|
|
13
|
-
private cachedFormData;
|
|
14
|
-
private formDataPromise;
|
|
15
|
-
private bodyText;
|
|
16
|
-
constructor(request: Request, matchedParams: Record<string, string>, initialVariables?: Partial<TVariables>);
|
|
17
|
-
build<TParams extends Record<string, string>>(): RouterContext<TParams, TVariables>;
|
|
18
|
-
newResponse(body?: BodyInit, init?: ResponseInit): Response;
|
|
19
|
-
}
|
|
20
|
-
//#endregion
|
|
21
|
-
export { ContextBuilder };
|