peta-auth 0.1.3 → 0.2.1
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 +93 -185
- package/dist/crypto-DR-ETdLZ.d.mts +35 -0
- package/dist/crypto-WcFV83Nz.mjs +84 -0
- package/dist/csrf.d.mts +31 -2
- package/dist/csrf.mjs +34 -2
- package/dist/elysia.d.mts +22 -1
- package/dist/elysia.mjs +16 -7
- package/dist/errors-DxJ-WUJL.mjs +17 -0
- package/dist/hono.d.mts +22 -1
- package/dist/hono.mjs +13 -3
- package/dist/index.d.mts +59 -5
- package/dist/index.mjs +56 -8
- package/dist/jwt.d.mts +23 -2
- package/dist/jwt.mjs +29 -9
- package/dist/nuxt.d.mts +26 -3
- package/dist/nuxt.mjs +18 -6
- package/dist/oauth/github.d.mts +18 -5
- package/dist/oauth/github.mjs +62 -71
- package/dist/oauth/google.d.mts +20 -7
- package/dist/oauth/google.mjs +65 -75
- package/dist/session-0bF8_7Ui.d.mts +53 -0
- package/dist/session-BGCQ1Z1Q.mjs +87 -0
- package/dist/utils-CKT3C1Lq.mjs +174 -0
- package/package.json +11 -7
- package/dist/crypto-Ln_Mj_zp.d.mts +0 -19
- package/dist/oauth/index.d.mts +0 -25
- package/dist/oauth/index.mjs +0 -103
- package/dist/session-DSwf3XPH.mjs +0 -119
- package/dist/session-z20gaFVT.d.mts +0 -23
package/dist/elysia.d.mts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { r as SessionOptions, t as IronSession } from "./session-
|
|
1
|
+
import { r as SessionOptions, t as IronSession } from "./session-0bF8_7Ui.mjs";
|
|
2
2
|
import { Elysia } from "elysia";
|
|
3
3
|
|
|
4
4
|
//#region src/elysia.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Elysia plugin that provides a session via the `session` store property.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* app.use(session({ password: "...", cookieName: "my-session" }))
|
|
11
|
+
* app.get("/me", ({ session }) => session)
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
5
14
|
declare function session<T extends Record<string, unknown> = Record<string, unknown>>(options: SessionOptions): Elysia<"", {
|
|
6
15
|
decorator: {};
|
|
7
16
|
store: {};
|
|
@@ -34,6 +43,18 @@ declare function session<T extends Record<string, unknown> = Record<string, unkn
|
|
|
34
43
|
standaloneSchema: {};
|
|
35
44
|
response: {};
|
|
36
45
|
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Elysia guard (onBeforeHandle) that requires session data.
|
|
48
|
+
*
|
|
49
|
+
* Returns 401 when the session is empty.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* app.guard({ beforeHandle: requireSession() }, (app) =>
|
|
54
|
+
* app.get("/admin", () => "ok")
|
|
55
|
+
* )
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
37
58
|
declare function requireSession(): (app: Elysia) => Elysia;
|
|
38
59
|
declare function requireSession<K extends string>(key: K): (app: Elysia) => Elysia;
|
|
39
60
|
//#endregion
|
package/dist/elysia.mjs
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import { t as createSessionFromAdapter } from "./session-
|
|
1
|
+
import { n as sessionHasData, t as createSessionFromAdapter } from "./session-BGCQ1Z1Q.mjs";
|
|
2
2
|
import { parse } from "cookie";
|
|
3
3
|
import { Elysia } from "elysia";
|
|
4
4
|
//#region src/elysia.ts
|
|
5
|
+
/**
|
|
6
|
+
* Elysia plugin that provides a session via the `session` store property.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* app.use(session({ password: "...", cookieName: "my-session" }))
|
|
11
|
+
* app.get("/me", ({ session }) => session)
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
5
14
|
function session(options) {
|
|
6
|
-
return new Elysia({ name: "peta-auth" }).derive({ as: "scoped" }, async ({ headers
|
|
7
|
-
const
|
|
15
|
+
return new Elysia({ name: "peta-auth" }).derive({ as: "scoped" }, async ({ headers, set }) => {
|
|
16
|
+
const cookieString = headers instanceof Headers ? headers.get("cookie") ?? "" : headers.cookie ?? "";
|
|
8
17
|
return { session: await createSessionFromAdapter({
|
|
9
|
-
getCookie: (name) => parse(
|
|
10
|
-
setCookie: (
|
|
11
|
-
set.headers["Set-Cookie"] =
|
|
18
|
+
getCookie: (name) => parse(cookieString)[name],
|
|
19
|
+
setCookie: (value) => {
|
|
20
|
+
set.headers["Set-Cookie"] = value;
|
|
12
21
|
}
|
|
13
22
|
}, options) };
|
|
14
23
|
});
|
|
@@ -16,7 +25,7 @@ function session(options) {
|
|
|
16
25
|
function requireSession(key) {
|
|
17
26
|
return (app) => app.onBeforeHandle((context) => {
|
|
18
27
|
const session = context.session;
|
|
19
|
-
if (!(
|
|
28
|
+
if (!sessionHasData(session, key)) return new Response(JSON.stringify({ error: "unauthorized" }), {
|
|
20
29
|
status: 401,
|
|
21
30
|
headers: { "Content-Type": "application/json" }
|
|
22
31
|
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* Typed error for peta-auth.
|
|
4
|
+
*
|
|
5
|
+
* Carries a machine-readable `code` and a human-readable `message`.
|
|
6
|
+
* Thrown instead of raw `new Error(...)` throughout the library.
|
|
7
|
+
*/
|
|
8
|
+
var PetaAuthError = class extends Error {
|
|
9
|
+
code;
|
|
10
|
+
constructor(code, message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "PetaAuthError";
|
|
13
|
+
this.code = code;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { PetaAuthError as t };
|
package/dist/hono.d.mts
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
|
-
import { r as SessionOptions, t as IronSession } from "./session-
|
|
1
|
+
import { r as SessionOptions, t as IronSession } from "./session-0bF8_7Ui.mjs";
|
|
2
2
|
import { MiddlewareHandler } from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/hono.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Hono middleware that creates a session and makes it available
|
|
7
|
+
* via `c.var.session`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* app.use("*", session({ password: "...", cookieName: "my-session" }))
|
|
12
|
+
* app.get("/me", (c) => c.json(c.var.session))
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
5
15
|
declare function session<T extends Record<string, unknown> = Record<string, unknown>>(options: SessionOptions): MiddlewareHandler<{
|
|
6
16
|
Variables: {
|
|
7
17
|
session: T & IronSession;
|
|
8
18
|
};
|
|
9
19
|
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Hono middleware that guards a route by requiring session data.
|
|
22
|
+
*
|
|
23
|
+
* Returns 401 when the session is empty.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* app.use("/admin", requireSession())
|
|
28
|
+
* app.use("/admin", requireSession("role"))
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
10
31
|
declare function requireSession(): MiddlewareHandler;
|
|
11
32
|
declare function requireSession<K extends string>(key: K): MiddlewareHandler;
|
|
12
33
|
//#endregion
|
package/dist/hono.mjs
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
import { t as createSessionFromAdapter } from "./session-
|
|
1
|
+
import { n as sessionHasData, t as createSessionFromAdapter } from "./session-BGCQ1Z1Q.mjs";
|
|
2
2
|
import { parse } from "cookie";
|
|
3
3
|
import { createMiddleware } from "hono/factory";
|
|
4
4
|
//#region src/hono.ts
|
|
5
|
+
/**
|
|
6
|
+
* Hono middleware that creates a session and makes it available
|
|
7
|
+
* via `c.var.session`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* app.use("*", session({ password: "...", cookieName: "my-session" }))
|
|
12
|
+
* app.get("/me", (c) => c.json(c.var.session))
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
5
15
|
function session(options) {
|
|
6
16
|
return createMiddleware(async (c, next) => {
|
|
7
17
|
c.set("session", await createSessionFromAdapter({
|
|
8
18
|
getCookie: (name) => parse(c.req.header("cookie") ?? "")[name],
|
|
9
|
-
setCookie: (
|
|
19
|
+
setCookie: (value) => c.res.headers.append("Set-Cookie", value)
|
|
10
20
|
}, options));
|
|
11
21
|
await next();
|
|
12
22
|
});
|
|
@@ -14,7 +24,7 @@ function session(options) {
|
|
|
14
24
|
function requireSession(key) {
|
|
15
25
|
return createMiddleware(async (c, next) => {
|
|
16
26
|
const s = c.var.session;
|
|
17
|
-
if (!(
|
|
27
|
+
if (!sessionHasData(s, key)) return c.json({ error: "unauthorized" }, 401);
|
|
18
28
|
await next();
|
|
19
29
|
});
|
|
20
30
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,27 +1,81 @@
|
|
|
1
|
-
import { n as sealData, r as unsealData, t as Password } from "./crypto-
|
|
2
|
-
import { i as createSessionFromAdapter, n as SessionAdapter, r as SessionOptions, t as IronSession } from "./session-
|
|
1
|
+
import { n as sealData, r as unsealData, t as Password } from "./crypto-DR-ETdLZ.mjs";
|
|
2
|
+
import { i as createSessionFromAdapter, n as SessionAdapter, r as SessionOptions, t as IronSession } from "./session-0bF8_7Ui.mjs";
|
|
3
3
|
import { CSRFOptions, generateCsrf, validateCsrf } from "./csrf.mjs";
|
|
4
4
|
import { JWTOptions, signJWT, verifyJWT } from "./jwt.mjs";
|
|
5
5
|
|
|
6
|
+
//#region src/errors.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Typed error for peta-auth.
|
|
9
|
+
*
|
|
10
|
+
* Carries a machine-readable `code` and a human-readable `message`.
|
|
11
|
+
* Thrown instead of raw `new Error(...)` throughout the library.
|
|
12
|
+
*/
|
|
13
|
+
declare class PetaAuthError extends Error {
|
|
14
|
+
readonly code: string;
|
|
15
|
+
constructor(code: string, message: string);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
6
18
|
//#region src/password.d.ts
|
|
7
19
|
interface HashOptions {
|
|
8
|
-
cost
|
|
20
|
+
/** Memory cost in KiB (default: 19456 = 19 MiB). */
|
|
21
|
+
memoryCost?: number;
|
|
22
|
+
/** Time cost (iterations) (default: 2). */
|
|
23
|
+
timeCost?: number;
|
|
24
|
+
/** Parallelism (default: 1). */
|
|
25
|
+
parallelism?: number;
|
|
9
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Hash a password with argon2id.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const hash = await hashPassword("my-password")
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
10
35
|
declare function hashPassword(password: string, options?: HashOptions): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Verify a password against an argon2id hash.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* const ok = await verifyPassword(hash, "my-password")
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
11
44
|
declare function verifyPassword(hash: string, password: string): Promise<boolean>;
|
|
12
45
|
//#endregion
|
|
13
46
|
//#region src/reset-password.d.ts
|
|
47
|
+
/** Options for password reset token generation. */
|
|
14
48
|
interface PasswordResetOptions {
|
|
49
|
+
/** Password(s) used to sign the reset token. */
|
|
15
50
|
password: Password;
|
|
16
|
-
|
|
51
|
+
/** Token lifetime in seconds (default 1 hour). */
|
|
52
|
+
expiresIn?: number;
|
|
17
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a password-reset token for a user.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const token = await createPasswordResetToken(userId, { password: "..." })
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
18
62
|
declare function createPasswordResetToken(userId: string, options: PasswordResetOptions): Promise<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Verify a password-reset token.
|
|
65
|
+
*
|
|
66
|
+
* Returns the user ID when the token is valid, or `null` if expired/invalid.
|
|
67
|
+
*/
|
|
19
68
|
declare function verifyPasswordResetToken(token: string, password: Password): Promise<{
|
|
20
69
|
userId: string;
|
|
21
70
|
} | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Verify a password-reset token and apply the new password.
|
|
73
|
+
*
|
|
74
|
+
* Returns `{ userId, hash }` on success, or `null` if the token is invalid.
|
|
75
|
+
*/
|
|
22
76
|
declare function resetPassword(token: string, newPassword: string, password: Password): Promise<{
|
|
23
77
|
userId: string;
|
|
24
78
|
hash: string;
|
|
25
79
|
} | null>;
|
|
26
80
|
//#endregion
|
|
27
|
-
export { type CSRFOptions, type IronSession, type JWTOptions, type Password, type PasswordResetOptions, type SessionAdapter, type SessionOptions, createPasswordResetToken, createSessionFromAdapter, generateCsrf, hashPassword, resetPassword, sealData, signJWT, unsealData, validateCsrf, verifyJWT, verifyPassword, verifyPasswordResetToken };
|
|
81
|
+
export { type CSRFOptions, type IronSession, type JWTOptions, type Password, type PasswordResetOptions, PetaAuthError, type SessionAdapter, type SessionOptions, createPasswordResetToken, createSessionFromAdapter, generateCsrf, hashPassword, resetPassword, sealData, signJWT, unsealData, validateCsrf, verifyJWT, verifyPassword, verifyPasswordResetToken };
|
package/dist/index.mjs
CHANGED
|
@@ -1,31 +1,79 @@
|
|
|
1
|
-
import { n as sealData, r as unsealData
|
|
1
|
+
import { n as sealData, r as unsealData } from "./crypto-WcFV83Nz.mjs";
|
|
2
2
|
import { generateCsrf, validateCsrf } from "./csrf.mjs";
|
|
3
|
+
import { t as PetaAuthError } from "./errors-DxJ-WUJL.mjs";
|
|
3
4
|
import { signJWT, verifyJWT } from "./jwt.mjs";
|
|
4
|
-
import {
|
|
5
|
+
import { t as createSessionFromAdapter } from "./session-BGCQ1Z1Q.mjs";
|
|
6
|
+
import { hash, verify } from "@node-rs/argon2";
|
|
5
7
|
//#region src/password.ts
|
|
8
|
+
const ARGON2_MEMORY_COST = 19456;
|
|
9
|
+
const ARGON2_TIME_COST = 2;
|
|
10
|
+
const ARGON2_PARALLELISM = 1;
|
|
11
|
+
/**
|
|
12
|
+
* Hash a password with argon2id.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const hash = await hashPassword("my-password")
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
6
19
|
async function hashPassword(password, options = {}) {
|
|
7
|
-
return
|
|
20
|
+
return hash(password, {
|
|
21
|
+
algorithm: 2,
|
|
22
|
+
memoryCost: options.memoryCost ?? ARGON2_MEMORY_COST,
|
|
23
|
+
timeCost: options.timeCost ?? ARGON2_TIME_COST,
|
|
24
|
+
parallelism: options.parallelism ?? ARGON2_PARALLELISM
|
|
25
|
+
});
|
|
8
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Verify a password against an argon2id hash.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const ok = await verifyPassword(hash, "my-password")
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
9
35
|
async function verifyPassword(hash, password) {
|
|
10
|
-
|
|
36
|
+
try {
|
|
37
|
+
return await verify(hash, password);
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
11
41
|
}
|
|
12
42
|
//#endregion
|
|
13
43
|
//#region src/reset-password.ts
|
|
14
|
-
const
|
|
44
|
+
const DEFAULT_EXPIRES_IN = 3600;
|
|
45
|
+
/**
|
|
46
|
+
* Create a password-reset token for a user.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const token = await createPasswordResetToken(userId, { password: "..." })
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
15
53
|
async function createPasswordResetToken(userId, options) {
|
|
16
54
|
return signJWT({
|
|
17
55
|
userId,
|
|
18
56
|
purpose: "password-reset"
|
|
19
57
|
}, {
|
|
20
58
|
password: options.password,
|
|
21
|
-
|
|
59
|
+
expiresIn: options.expiresIn ?? DEFAULT_EXPIRES_IN
|
|
22
60
|
});
|
|
23
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Verify a password-reset token.
|
|
64
|
+
*
|
|
65
|
+
* Returns the user ID when the token is valid, or `null` if expired/invalid.
|
|
66
|
+
*/
|
|
24
67
|
async function verifyPasswordResetToken(token, password) {
|
|
25
68
|
const payload = await verifyJWT(token, { password });
|
|
26
|
-
if (
|
|
69
|
+
if (payload?.purpose !== "password-reset") return null;
|
|
27
70
|
return { userId: payload.userId };
|
|
28
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Verify a password-reset token and apply the new password.
|
|
74
|
+
*
|
|
75
|
+
* Returns `{ userId, hash }` on success, or `null` if the token is invalid.
|
|
76
|
+
*/
|
|
29
77
|
async function resetPassword(token, newPassword, password) {
|
|
30
78
|
const payload = await verifyPasswordResetToken(token, password);
|
|
31
79
|
if (!payload) return null;
|
|
@@ -35,4 +83,4 @@ async function resetPassword(token, newPassword, password) {
|
|
|
35
83
|
};
|
|
36
84
|
}
|
|
37
85
|
//#endregion
|
|
38
|
-
export { createPasswordResetToken, createSessionFromAdapter, generateCsrf, hashPassword, resetPassword, sealData, signJWT, unsealData, validateCsrf, verifyJWT, verifyPassword, verifyPasswordResetToken };
|
|
86
|
+
export { PetaAuthError, createPasswordResetToken, createSessionFromAdapter, generateCsrf, hashPassword, resetPassword, sealData, signJWT, unsealData, validateCsrf, verifyJWT, verifyPassword, verifyPasswordResetToken };
|
package/dist/jwt.d.mts
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
|
-
import { t as Password } from "./crypto-
|
|
1
|
+
import { t as Password } from "./crypto-DR-ETdLZ.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/jwt.d.ts
|
|
4
|
+
/** Options for JWT sign / verify operations. */
|
|
4
5
|
interface JWTOptions {
|
|
6
|
+
/** Password used to sign the JWT. */
|
|
5
7
|
password: Password;
|
|
6
|
-
|
|
8
|
+
/** Time-to-live in seconds from now. */
|
|
9
|
+
expiresIn?: number;
|
|
7
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Sign a JWT payload.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const token = await signJWT({ userId: "abc" }, { password: "my-32-char-secret...", expiresIn: 3600 })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
8
19
|
declare function signJWT(payload: Record<string, unknown>, options: JWTOptions): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Verify and decode a JWT.
|
|
22
|
+
*
|
|
23
|
+
* Returns `null` when the token is invalid or expired.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const payload = await verifyJWT<{ userId: string }>(token, { password: "my-32-char-secret..." })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
9
30
|
declare function verifyJWT<T = Record<string, unknown>>(token: string, options: JWTOptions): Promise<T | null>;
|
|
10
31
|
//#endregion
|
|
11
32
|
export { JWTOptions, signJWT, verifyJWT };
|
package/dist/jwt.mjs
CHANGED
|
@@ -1,28 +1,48 @@
|
|
|
1
|
+
import { t as normalizePassword } from "./crypto-WcFV83Nz.mjs";
|
|
2
|
+
import { t as PetaAuthError } from "./errors-DxJ-WUJL.mjs";
|
|
1
3
|
import * as jose from "jose";
|
|
2
4
|
//#region src/jwt.ts
|
|
3
|
-
function toPasswordMap(password) {
|
|
4
|
-
return typeof password === "string" ? { 1: password } : password;
|
|
5
|
-
}
|
|
6
5
|
function toKey(secret) {
|
|
7
6
|
return new TextEncoder().encode(secret);
|
|
8
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Sign a JWT payload.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const token = await signJWT({ userId: "abc" }, { password: "my-32-char-secret...", expiresIn: 3600 })
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
9
16
|
async function signJWT(payload, options) {
|
|
10
|
-
const map =
|
|
17
|
+
const map = normalizePassword(options.password);
|
|
11
18
|
const secret = map[Math.max(...Object.keys(map).map(Number)).toString()];
|
|
12
|
-
if (!secret || secret.length < 32) throw new
|
|
19
|
+
if (!secret || secret.length < 32) throw new PetaAuthError("JWT_PASSWORD_TOO_SHORT", "peta-auth/jwt: password must be at least 32 characters");
|
|
13
20
|
const jwt = new jose.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt();
|
|
14
|
-
|
|
21
|
+
const ttl = options.expiresIn ?? 86400;
|
|
22
|
+
jwt.setExpirationTime(Math.floor(Date.now() / 1e3) + ttl);
|
|
15
23
|
return jwt.sign(toKey(secret));
|
|
16
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Verify and decode a JWT.
|
|
27
|
+
*
|
|
28
|
+
* Returns `null` when the token is invalid or expired.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const payload = await verifyJWT<{ userId: string }>(token, { password: "my-32-char-secret..." })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
17
35
|
async function verifyJWT(token, options) {
|
|
18
|
-
|
|
36
|
+
let result = null;
|
|
37
|
+
const passwords = normalizePassword(options.password);
|
|
38
|
+
for (const secret of Object.values(passwords)) {
|
|
19
39
|
if (!secret) continue;
|
|
20
40
|
try {
|
|
21
41
|
const { payload } = await jose.jwtVerify(token, toKey(secret));
|
|
22
|
-
|
|
42
|
+
if (!result) result = payload;
|
|
23
43
|
} catch {}
|
|
24
44
|
}
|
|
25
|
-
return
|
|
45
|
+
return result;
|
|
26
46
|
}
|
|
27
47
|
//#endregion
|
|
28
48
|
export { signJWT, verifyJWT };
|
package/dist/nuxt.d.mts
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
-
import { r as SessionOptions, t as IronSession } from "./session-
|
|
1
|
+
import { r as SessionOptions, t as IronSession } from "./session-0bF8_7Ui.mjs";
|
|
2
2
|
import { H3Event } from "h3";
|
|
3
3
|
|
|
4
4
|
//#region src/nuxt.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Create a session from an h3 event (Nuxt / h3).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // In a Nuxt server handler:
|
|
11
|
+
* const session = await useSession(event, { password: process.env.NUXT_SESSION_PASSWORD })
|
|
12
|
+
* session.userId = 42
|
|
13
|
+
* await session.save()
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
5
16
|
declare function useSession<T extends Record<string, unknown> = Record<string, unknown>>(event: H3Event, options: SessionOptions): Promise<T & IronSession>;
|
|
6
|
-
|
|
7
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Guard that requires session data.
|
|
19
|
+
*
|
|
20
|
+
* Throws a 401 h3 error when the session is empty.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const session = await useSession(event, options)
|
|
25
|
+
* requireSession(event, session)
|
|
26
|
+
* requireSession(event, session, "role") // require specific key
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function requireSession(event: H3Event, session: IronSession): void;
|
|
30
|
+
declare function requireSession<K extends string>(event: H3Event, session: IronSession, key: K): void;
|
|
8
31
|
//#endregion
|
|
9
32
|
export { requireSession, useSession };
|
package/dist/nuxt.mjs
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { t as PetaAuthError } from "./errors-DxJ-WUJL.mjs";
|
|
2
|
+
import { n as sessionHasData, t as createSessionFromAdapter } from "./session-BGCQ1Z1Q.mjs";
|
|
2
3
|
import { appendHeader, createError, getCookie } from "h3";
|
|
3
4
|
//#region src/nuxt.ts
|
|
5
|
+
/**
|
|
6
|
+
* Create a session from an h3 event (Nuxt / h3).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // In a Nuxt server handler:
|
|
11
|
+
* const session = await useSession(event, { password: process.env.NUXT_SESSION_PASSWORD })
|
|
12
|
+
* session.userId = 42
|
|
13
|
+
* await session.save()
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
4
16
|
function useSession(event, options) {
|
|
5
17
|
const password = options.password ?? process.env.NUXT_SESSION_PASSWORD;
|
|
6
|
-
if (!password) throw new
|
|
18
|
+
if (!password) throw new PetaAuthError("MISSING_PASSWORD", "peta-auth/nuxt: NUXT_SESSION_PASSWORD is required");
|
|
7
19
|
return createSessionFromAdapter({
|
|
8
20
|
getCookie: (name) => getCookie(event, name),
|
|
9
21
|
setCookie: (value) => appendHeader(event, "Set-Cookie", value)
|
|
10
22
|
}, {
|
|
11
23
|
password,
|
|
12
|
-
cookieName: options
|
|
13
|
-
|
|
14
|
-
cookieOptions: options
|
|
24
|
+
cookieName: options.cookieName ?? "nuxt-session",
|
|
25
|
+
timeToLive: options.timeToLive,
|
|
26
|
+
cookieOptions: options.cookieOptions
|
|
15
27
|
});
|
|
16
28
|
}
|
|
17
29
|
function requireSession(_event, session, key) {
|
|
18
|
-
if (!(
|
|
30
|
+
if (!sessionHasData(session, key)) throw createError({
|
|
19
31
|
statusCode: 401,
|
|
20
32
|
statusMessage: "unauthorized"
|
|
21
33
|
});
|
package/dist/oauth/github.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//#region src/oauth/github.d.ts
|
|
2
|
+
/** Configuration for GitHub OAuth. */
|
|
2
3
|
interface OAuthGitHubConfig {
|
|
3
4
|
clientId?: string;
|
|
4
5
|
clientSecret?: string;
|
|
@@ -10,6 +11,11 @@ interface OAuthGitHubConfig {
|
|
|
10
11
|
authorizationParams?: Record<string, string>;
|
|
11
12
|
redirectURL?: string;
|
|
12
13
|
}
|
|
14
|
+
interface GitHubTokens {
|
|
15
|
+
access_token: string;
|
|
16
|
+
scope: string;
|
|
17
|
+
token_type: string;
|
|
18
|
+
}
|
|
13
19
|
interface GitHubUser {
|
|
14
20
|
login: string;
|
|
15
21
|
id: number;
|
|
@@ -19,11 +25,18 @@ interface GitHubUser {
|
|
|
19
25
|
email: string | null;
|
|
20
26
|
email_verified?: boolean;
|
|
21
27
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Define a GitHub OAuth event handler.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const handle = defineOAuthGitHubEventHandler({
|
|
34
|
+
* onSuccess: async ({ user, tokens }) =>
|
|
35
|
+
* new Response(`Welcome ${user.login}!`),
|
|
36
|
+
* })
|
|
37
|
+
* serve(handle)
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
27
40
|
declare function defineOAuthGitHubEventHandler(options: {
|
|
28
41
|
config?: OAuthGitHubConfig;
|
|
29
42
|
onSuccess: (event: {
|