@draftlab/auth 0.8.0 → 0.9.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/client.mjs +4 -1
- package/dist/core.d.mts +2 -21
- package/dist/core.mjs +44 -3
- package/dist/provider/oauth2.mjs +7 -0
- package/package.json +3 -3
package/dist/client.mjs
CHANGED
|
@@ -201,7 +201,10 @@ const createClient = (input) => {
|
|
|
201
201
|
},
|
|
202
202
|
async verify(subjects, token, options) {
|
|
203
203
|
try {
|
|
204
|
-
const jwtResult = await jwtVerify(token, await getJWKS(), {
|
|
204
|
+
const jwtResult = await jwtVerify(token, await getJWKS(), {
|
|
205
|
+
issuer: options?.issuer ?? issuer,
|
|
206
|
+
...options?.audience && { audience: options.audience }
|
|
207
|
+
});
|
|
205
208
|
const validated = await subjects[jwtResult.payload.type]?.["~standard"].validate(jwtResult.payload.properties);
|
|
206
209
|
if (!validated?.issues && jwtResult.payload.mode === "access") return {
|
|
207
210
|
success: true,
|
package/dist/core.d.mts
CHANGED
|
@@ -6,6 +6,7 @@ import { StorageAdapter } from "./storage/storage.mjs";
|
|
|
6
6
|
import { Plugin } from "./plugin/types.mjs";
|
|
7
7
|
import { Provider } from "./provider/provider.mjs";
|
|
8
8
|
import { Theme } from "./themes/theme.mjs";
|
|
9
|
+
import { AuthorizationState } from "./types.mjs";
|
|
9
10
|
import { Router } from "@draftlab/auth-router";
|
|
10
11
|
|
|
11
12
|
//#region src/core.d.ts
|
|
@@ -27,26 +28,6 @@ interface OnSuccessResponder<T$1 extends {
|
|
|
27
28
|
subject?: string;
|
|
28
29
|
}): Promise<Response>;
|
|
29
30
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Authorization state for OAuth 2.0 flows.
|
|
32
|
-
*/
|
|
33
|
-
interface AuthorizationState {
|
|
34
|
-
/** OAuth redirect URI */
|
|
35
|
-
redirect_uri: string;
|
|
36
|
-
/** OAuth response type */
|
|
37
|
-
response_type: string;
|
|
38
|
-
/** OAuth state parameter for CSRF protection */
|
|
39
|
-
state: string;
|
|
40
|
-
/** OAuth client identifier */
|
|
41
|
-
client_id: string;
|
|
42
|
-
/** OAuth audience parameter */
|
|
43
|
-
audience: string;
|
|
44
|
-
/** PKCE challenge data for code verification */
|
|
45
|
-
pkce?: {
|
|
46
|
-
challenge: string;
|
|
47
|
-
method: "S256";
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
31
|
/**
|
|
51
32
|
* Main issuer input configuration interface.
|
|
52
33
|
*/
|
|
@@ -129,4 +110,4 @@ declare const issuer: <Providers extends Record<string, Provider<unknown>>, Subj
|
|
|
129
110
|
};
|
|
130
111
|
}>;
|
|
131
112
|
//#endregion
|
|
132
|
-
export {
|
|
113
|
+
export { OnSuccessResponder, issuer };
|
package/dist/core.mjs
CHANGED
|
@@ -139,7 +139,8 @@ const issuer = (input) => {
|
|
|
139
139
|
clientID: value.clientID,
|
|
140
140
|
subject: value.subject,
|
|
141
141
|
ttl: value.ttl,
|
|
142
|
-
nextToken: generateSecureToken()
|
|
142
|
+
nextToken: generateSecureToken(),
|
|
143
|
+
timeUsed: value.timeUsed
|
|
143
144
|
};
|
|
144
145
|
const refreshKey = [
|
|
145
146
|
"oauth:refresh",
|
|
@@ -231,6 +232,7 @@ const issuer = (input) => {
|
|
|
231
232
|
subject,
|
|
232
233
|
redirectURI: authorization.redirect_uri,
|
|
233
234
|
clientID: authorization.client_id,
|
|
235
|
+
scopes: authorization.scopes,
|
|
234
236
|
pkce: authorization.pkce,
|
|
235
237
|
ttl: {
|
|
236
238
|
access: subjectOpts?.ttl?.access ?? ttlAccess,
|
|
@@ -492,13 +494,51 @@ const issuer = (input) => {
|
|
|
492
494
|
credentials: false
|
|
493
495
|
})],
|
|
494
496
|
handler: async (c) => {
|
|
495
|
-
const
|
|
497
|
+
const form = await c.formData();
|
|
498
|
+
const token = form.get("token")?.toString();
|
|
499
|
+
const tokenTypeHint = form.get("token_type_hint")?.toString();
|
|
496
500
|
if (!token) {
|
|
497
501
|
const error$1 = new OauthError("invalid_request", "Missing token parameter");
|
|
498
502
|
return c.json(error$1.toJSON(), { status: 400 });
|
|
499
503
|
}
|
|
500
504
|
try {
|
|
501
|
-
|
|
505
|
+
if (tokenTypeHint === "refresh_token") {
|
|
506
|
+
const splits$1 = token.split(":");
|
|
507
|
+
const tokenPart$1 = splits$1.pop();
|
|
508
|
+
if (tokenPart$1 && splits$1.length > 0) {
|
|
509
|
+
const key = [
|
|
510
|
+
"oauth:refresh",
|
|
511
|
+
splits$1.join(":"),
|
|
512
|
+
tokenPart$1
|
|
513
|
+
];
|
|
514
|
+
if (await Storage.get(storage, key)) {
|
|
515
|
+
await Storage.remove(storage, key);
|
|
516
|
+
const expiresAt$1 = Date.now() + ttlRefreshRetention * 1e3;
|
|
517
|
+
await Revocation.revoke(storage, token, expiresAt$1);
|
|
518
|
+
return c.json({});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
} else if (tokenTypeHint === "access_token") {
|
|
522
|
+
const expiresAt$1 = Date.now() + ttlAccess * 1e3;
|
|
523
|
+
await Revocation.revoke(storage, token, expiresAt$1);
|
|
524
|
+
return c.json({});
|
|
525
|
+
}
|
|
526
|
+
const splits = token.split(":");
|
|
527
|
+
const tokenPart = splits.pop();
|
|
528
|
+
if (tokenPart && splits.length > 0) {
|
|
529
|
+
const key = [
|
|
530
|
+
"oauth:refresh",
|
|
531
|
+
splits.join(":"),
|
|
532
|
+
tokenPart
|
|
533
|
+
];
|
|
534
|
+
if (await Storage.get(storage, key)) {
|
|
535
|
+
await Storage.remove(storage, key);
|
|
536
|
+
const expiresAt$1 = Date.now() + ttlRefreshRetention * 1e3;
|
|
537
|
+
await Revocation.revoke(storage, token, expiresAt$1);
|
|
538
|
+
return c.json({});
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
const expiresAt = Date.now() + ttlAccess * 1e3;
|
|
502
542
|
await Revocation.revoke(storage, token, expiresAt);
|
|
503
543
|
return c.json({});
|
|
504
544
|
} catch (_err) {
|
|
@@ -526,6 +566,7 @@ const issuer = (input) => {
|
|
|
526
566
|
client_id,
|
|
527
567
|
audience,
|
|
528
568
|
scope,
|
|
569
|
+
scopes: scope ? scope.split(" ").filter(Boolean) : void 0,
|
|
529
570
|
...code_challenge && code_challenge_method && { pkce: {
|
|
530
571
|
challenge: code_challenge,
|
|
531
572
|
method: code_challenge_method
|
package/dist/provider/oauth2.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { getRelativeUrl } from "../util.mjs";
|
|
|
2
2
|
import { OauthError } from "../error.mjs";
|
|
3
3
|
import { generatePKCE } from "../pkce.mjs";
|
|
4
4
|
import { generateSecureToken, timingSafeCompare } from "../random.mjs";
|
|
5
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
5
6
|
|
|
6
7
|
//#region src/provider/oauth2.ts
|
|
7
8
|
/**
|
|
@@ -70,6 +71,12 @@ const Oauth2Provider = (config) => {
|
|
|
70
71
|
if (!response.ok) throw new Error(`Token request failed with status ${response.status}`);
|
|
71
72
|
const tokenData = await response.json();
|
|
72
73
|
if (tokenData.error) throw new OauthError(tokenData.error, tokenData.error_description || "");
|
|
74
|
+
if (tokenData.id_token && config.endpoint.jwks) try {
|
|
75
|
+
const jwks = createRemoteJWKSet(new URL(config.endpoint.jwks));
|
|
76
|
+
await jwtVerify(tokenData.id_token, jwks, { issuer: config.endpoint.authorization.split("/").slice(0, 3).join("/") });
|
|
77
|
+
} catch (error) {
|
|
78
|
+
throw new OauthError("invalid_request", `ID token validation failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
79
|
+
}
|
|
73
80
|
return await ctx.success(c, {
|
|
74
81
|
clientID: config.clientID,
|
|
75
82
|
tokenset: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draftlab/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core implementation for @draftlab/auth",
|
|
6
6
|
"author": "Matheus Pergoli",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^24.10.1",
|
|
41
41
|
"@types/qrcode": "^1.5.6",
|
|
42
|
-
"tsdown": "^0.16.
|
|
42
|
+
"tsdown": "^0.16.7",
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"@draftlab/tsconfig": "0.1.0"
|
|
45
45
|
},
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"preact": "^10.27.2",
|
|
64
64
|
"preact-render-to-string": "^6.6.3",
|
|
65
65
|
"qrcode": "^1.5.4",
|
|
66
|
-
"@draftlab/auth-router": "0.
|
|
66
|
+
"@draftlab/auth-router": "0.2.0"
|
|
67
67
|
},
|
|
68
68
|
"engines": {
|
|
69
69
|
"node": ">=18"
|