@kamod-ch/otok-auth 2.0.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/LICENSE +21 -0
- package/README.md +230 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/kysely.d.ts +12 -0
- package/dist/adapters/kysely.d.ts.map +1 -0
- package/dist/adapters/kysely.js +52 -0
- package/dist/adapters/kysely.js.map +1 -0
- package/dist/adapters/memory.d.ts +26 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js +72 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/context.d.ts +36 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +68 -0
- package/dist/context.js.map +1 -0
- package/dist/crypto.d.ts +5 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +33 -0
- package/dist/crypto.js.map +1 -0
- package/dist/csrf.d.ts +19 -0
- package/dist/csrf.d.ts.map +1 -0
- package/dist/csrf.js +53 -0
- package/dist/csrf.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +24 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +30 -0
- package/dist/loader.js.map +1 -0
- package/dist/middleware/api-guard.d.ts +3 -0
- package/dist/middleware/api-guard.d.ts.map +1 -0
- package/dist/middleware/api-guard.js +4 -0
- package/dist/middleware/api-guard.js.map +1 -0
- package/dist/middleware/csrf.d.ts +4 -0
- package/dist/middleware/csrf.d.ts.map +1 -0
- package/dist/middleware/csrf.js +22 -0
- package/dist/middleware/csrf.js.map +1 -0
- package/dist/middleware/index.d.ts +5 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +5 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rbac.d.ts +26 -0
- package/dist/middleware/rbac.d.ts.map +1 -0
- package/dist/middleware/rbac.js +63 -0
- package/dist/middleware/rbac.js.map +1 -0
- package/dist/middleware/require-auth.d.ts +11 -0
- package/dist/middleware/require-auth.d.ts.map +1 -0
- package/dist/middleware/require-auth.js +20 -0
- package/dist/middleware/require-auth.js.map +1 -0
- package/dist/password-webcrypto.d.ts +11 -0
- package/dist/password-webcrypto.d.ts.map +1 -0
- package/dist/password-webcrypto.js +65 -0
- package/dist/password-webcrypto.js.map +1 -0
- package/dist/password.d.ts +3 -0
- package/dist/password.d.ts.map +1 -0
- package/dist/password.js +8 -0
- package/dist/password.js.map +1 -0
- package/dist/plugin.d.ts +19 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +132 -0
- package/dist/plugin.js.map +1 -0
- package/dist/redirect.d.ts +8 -0
- package/dist/redirect.d.ts.map +1 -0
- package/dist/redirect.js +21 -0
- package/dist/redirect.js.map +1 -0
- package/dist/registry.d.ts +22 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +28 -0
- package/dist/registry.js.map +1 -0
- package/dist/session/index.d.ts +3 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +2 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +3 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +120 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +41 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +2 -0
- package/dist/session/types.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +110 -0
package/dist/csrf.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { getCookie, setCookie } from "hono/cookie";
|
|
3
|
+
import { fail } from "@kamod-ch/otok/server";
|
|
4
|
+
import { randomToken } from "./crypto.js";
|
|
5
|
+
export const CSRF_FIELD = "_csrf";
|
|
6
|
+
export const DEFAULT_CSRF_COOKIE = "otok_csrf";
|
|
7
|
+
function resolveSecure(c, secure) {
|
|
8
|
+
if (typeof secure === "function")
|
|
9
|
+
return secure(c);
|
|
10
|
+
if (typeof secure === "boolean")
|
|
11
|
+
return secure;
|
|
12
|
+
return process.env.NODE_ENV === "production";
|
|
13
|
+
}
|
|
14
|
+
export function createCsrfToken() {
|
|
15
|
+
return randomToken(24);
|
|
16
|
+
}
|
|
17
|
+
/** Ensure a CSRF cookie exists on safe requests (GET/HEAD). */
|
|
18
|
+
export function ensureCsrfCookie(c, options = {}) {
|
|
19
|
+
const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE;
|
|
20
|
+
const existing = getCookie(c, cookieName);
|
|
21
|
+
if (existing)
|
|
22
|
+
return existing;
|
|
23
|
+
const token = createCsrfToken();
|
|
24
|
+
setCookie(c, cookieName, token, {
|
|
25
|
+
httpOnly: false,
|
|
26
|
+
sameSite: options.sameSite ?? "Lax",
|
|
27
|
+
path: options.path ?? "/",
|
|
28
|
+
secure: resolveSecure(c, options.secure),
|
|
29
|
+
maxAge: options.maxAge,
|
|
30
|
+
});
|
|
31
|
+
return token;
|
|
32
|
+
}
|
|
33
|
+
export function verifyCsrf(c, formToken, options = {}) {
|
|
34
|
+
const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE;
|
|
35
|
+
const cookie = getCookie(c, cookieName);
|
|
36
|
+
if (!cookie || !formToken)
|
|
37
|
+
return false;
|
|
38
|
+
const a = Buffer.from(cookie);
|
|
39
|
+
const b = Buffer.from(formToken);
|
|
40
|
+
return a.length === b.length && timingSafeEqual(a, b);
|
|
41
|
+
}
|
|
42
|
+
/** Reject mutating form posts when the cookie and form field do not match. */
|
|
43
|
+
export function assertCsrf(c, formData, options = {}) {
|
|
44
|
+
const submitted = String(formData?.get(CSRF_FIELD) ?? "");
|
|
45
|
+
if (!verifyCsrf(c, submitted, options)) {
|
|
46
|
+
fail(403, { message: "Invalid CSRF token" });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Hidden input snippet for progressive-enhancement forms. */
|
|
50
|
+
export function csrfHiddenInput(token) {
|
|
51
|
+
return `<input type="hidden" name="${CSRF_FIELD}" value="${token}" />`;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=csrf.js.map
|
package/dist/csrf.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.js","sourceRoot":"","sources":["../src/csrf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC;AAClC,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAU/C,SAAS,aAAa,CAAC,CAAU,EAAE,MAA4C;IAC7E,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,OAAO,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,gBAAgB,CAAC,CAAU,EAAE,UAAuB,EAAE;IACpE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IAC7D,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE;QAC9B,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;QACnC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,GAAG;QACzB,MAAM,EAAE,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,CAAU,EACV,SAAyB,EACzB,UAA2C,EAAE;IAE7C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CACxB,CAAU,EACV,QAA8B,EAC9B,UAA2C,EAAE;IAE7C,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,8BAA8B,UAAU,YAAY,KAAK,MAAM,CAAC;AACzE,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type AuthErrorCode = "unauthenticated" | "forbidden" | "invalid_session" | "csrf_invalid" | "unsafe_redirect";
|
|
2
|
+
export declare class AuthError extends Error {
|
|
3
|
+
readonly code: AuthErrorCode;
|
|
4
|
+
readonly status: number;
|
|
5
|
+
constructor(code: AuthErrorCode, message?: string, status?: number);
|
|
6
|
+
static defaultStatus(code: AuthErrorCode): number;
|
|
7
|
+
/** Safe for client responses — no secrets or internal details. */
|
|
8
|
+
toJSON(): {
|
|
9
|
+
code: AuthErrorCode;
|
|
10
|
+
message: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,WAAW,GACX,iBAAiB,GACjB,cAAc,GACd,iBAAiB,CAAC;AAEtB,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAOlE,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAejD,kEAAkE;IAClE,MAAM,IAAI;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CAGnD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class AuthError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
constructor(code, message, status) {
|
|
5
|
+
super(message ?? code);
|
|
6
|
+
this.name = "AuthError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.status = status ?? AuthError.defaultStatus(code);
|
|
9
|
+
}
|
|
10
|
+
static defaultStatus(code) {
|
|
11
|
+
switch (code) {
|
|
12
|
+
case "unauthenticated":
|
|
13
|
+
case "invalid_session":
|
|
14
|
+
return 401;
|
|
15
|
+
case "forbidden":
|
|
16
|
+
case "csrf_invalid":
|
|
17
|
+
return 403;
|
|
18
|
+
case "unsafe_redirect":
|
|
19
|
+
return 400;
|
|
20
|
+
default:
|
|
21
|
+
return 401;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Safe for client responses — no secrets or internal details. */
|
|
25
|
+
toJSON() {
|
|
26
|
+
return { code: this.code, message: this.message };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAgB;IACpB,MAAM,CAAS;IAExB,YAAY,IAAmB,EAAE,OAAgB,EAAE,MAAe;QAChE,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,IAAmB;QACtC,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,iBAAiB,CAAC;YACvB,KAAK,iBAAiB;gBACpB,OAAO,GAAG,CAAC;YACb,KAAK,WAAW,CAAC;YACjB,KAAK,cAAc;gBACjB,OAAO,GAAG,CAAC;YACb,KAAK,iBAAiB;gBACpB,OAAO,GAAG,CAAC;YACb;gBACE,OAAO,GAAG,CAAC;QACf,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,MAAM;QACJ,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IACpD,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { randomToken, sha256, sha256Async } from "./crypto.js";
|
|
2
|
+
export { assertCsrf, createCsrfToken, CSRF_FIELD, csrfHiddenInput, DEFAULT_CSRF_COOKIE, ensureCsrfCookie, verifyCsrf, type CsrfOptions, } from "./csrf.js";
|
|
3
|
+
export { AuthError, type AuthErrorCode } from "./errors.js";
|
|
4
|
+
export { createAuthHelpers, authFromOtokContext, readContextUser, toAuthSession, type AuthHelpers, type AuthBoundHelpers, type AuthHelpersOptions, } from "./context.js";
|
|
5
|
+
export { defineLoader, defineAction } from "./loader.js";
|
|
6
|
+
export { safeRedirectPath, safeNextPath } from "./redirect.js";
|
|
7
|
+
export { getAuthRuntime, tryGetAuthRuntime, registerAuthRuntime, getSession, requireUser, requireRole, type AuthRuntime, } from "./registry.js";
|
|
8
|
+
export { default, createAuthRuntime, configureAuthApp } from "./plugin.js";
|
|
9
|
+
export { createApiGuard, createCsrfMiddleware, createRequireAuthMiddleware, composeMiddleware, createRequireRoleMiddleware, createSessionContextMiddleware, createTenantMiddleware, type RequireAuthOptions, type RequireRoleMiddlewareOptions, type SessionContextMiddlewareOptions, type TenantMiddlewareOptions, } from "./middleware/index.js";
|
|
10
|
+
export { createSessionManager, type CreateSessionRecordInput, type ResolvedSessionRecord, type SessionAdapter, type SessionConfig, type SessionManager, } from "./session/index.js";
|
|
11
|
+
export { hashPassword, verifyPassword } from "./password.js";
|
|
12
|
+
export { hashPasswordWebCrypto, verifyPasswordWebCrypto } from "./password-webcrypto.js";
|
|
13
|
+
export { createMemorySessionAdapter, type MemorySessionAdapterOptions, type MemorySessionPersistence, type MemorySessionRecord, } from "./adapters/index.js";
|
|
14
|
+
export { createKyselySessionAdapter, SESSION_TABLE_MIGRATION_SQL, type KyselySessionAdapterOptions, } from "./adapters/kysely.js";
|
|
15
|
+
export type { AuthUser, AuthSession, AuthPluginOptions, AuthPluginSessionOptions } from "./types.js";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EACL,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,WAAW,EACX,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EACL,0BAA0B,EAC1B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,KAAK,2BAA2B,GACjC,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { randomToken, sha256, sha256Async } from "./crypto.js";
|
|
2
|
+
export { assertCsrf, createCsrfToken, CSRF_FIELD, csrfHiddenInput, DEFAULT_CSRF_COOKIE, ensureCsrfCookie, verifyCsrf, } from "./csrf.js";
|
|
3
|
+
export { AuthError } from "./errors.js";
|
|
4
|
+
export { createAuthHelpers, authFromOtokContext, readContextUser, toAuthSession, } from "./context.js";
|
|
5
|
+
export { defineLoader, defineAction } from "./loader.js";
|
|
6
|
+
export { safeRedirectPath, safeNextPath } from "./redirect.js";
|
|
7
|
+
export { getAuthRuntime, tryGetAuthRuntime, registerAuthRuntime, getSession, requireUser, requireRole, } from "./registry.js";
|
|
8
|
+
export { default, createAuthRuntime, configureAuthApp } from "./plugin.js";
|
|
9
|
+
export { createApiGuard, createCsrfMiddleware, createRequireAuthMiddleware, composeMiddleware, createRequireRoleMiddleware, createSessionContextMiddleware, createTenantMiddleware, } from "./middleware/index.js";
|
|
10
|
+
export { createSessionManager, } from "./session/index.js";
|
|
11
|
+
export { hashPassword, verifyPassword } from "./password.js";
|
|
12
|
+
export { hashPasswordWebCrypto, verifyPasswordWebCrypto } from "./password-webcrypto.js";
|
|
13
|
+
export { createMemorySessionAdapter, } from "./adapters/index.js";
|
|
14
|
+
export { createKyselySessionAdapter, SESSION_TABLE_MIGRATION_SQL, } from "./adapters/kysely.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EACL,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,GAEX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAsB,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,aAAa,GAId,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,WAAW,GAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,GAKvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,GAMrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EACL,0BAA0B,GAI3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAE5B,MAAM,sBAAsB,CAAC"}
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LoaderResult, OtokActionContext, OtokContext, OtokLoader } from "@kamod-ch/otok/server";
|
|
2
|
+
import type { AuthBoundHelpers } from "./context.js";
|
|
3
|
+
import type { AuthUser } from "./types.js";
|
|
4
|
+
type LoaderAuthContext<TUser extends AuthUser = AuthUser> = {
|
|
5
|
+
auth: AuthBoundHelpers<TUser>;
|
|
6
|
+
};
|
|
7
|
+
type ActionAuthContext<TUser extends AuthUser = AuthUser> = LoaderAuthContext<TUser>;
|
|
8
|
+
/**
|
|
9
|
+
* Wrap a loader with typed `auth` helpers from the registered otok-auth runtime.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* export const loader = defineLoader(async ({ auth }) => {
|
|
13
|
+
* const user = await auth.requireUser();
|
|
14
|
+
* return { user };
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function defineLoader<Data extends LoaderResult>(handler: (ctx: OtokContext & LoaderAuthContext) => Data | Promise<Data>): OtokLoader<Data>;
|
|
19
|
+
/**
|
|
20
|
+
* Wrap an action with typed `auth` helpers from the registered otok-auth runtime.
|
|
21
|
+
*/
|
|
22
|
+
export declare function defineAction<Result>(handler: (ctx: OtokActionContext & ActionAuthContext) => Result | Promise<Result>): (context: OtokActionContext) => Result | Promise<Result>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,KAAK,iBAAiB,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,IAAI;IAC1D,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC;AAEF,KAAK,iBAAiB,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAarF;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,SAAS,YAAY,EACpD,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACtE,UAAU,CAAC,IAAI,CAAC,CAElB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EACjC,OAAO,EAAE,CAAC,GAAG,EAAE,iBAAiB,GAAG,iBAAiB,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAChF,CAAC,OAAO,EAAE,iBAAiB,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1D"}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { authFromOtokContext } from "./context.js";
|
|
2
|
+
import { tryGetAuthRuntime } from "./registry.js";
|
|
3
|
+
function resolveAuth(hono) {
|
|
4
|
+
const runtime = tryGetAuthRuntime();
|
|
5
|
+
if (!runtime) {
|
|
6
|
+
throw new Error("otok-auth: defineLoader requires auth() plugin or registerAuthRuntime(). " +
|
|
7
|
+
"Use loader: ({ hono }) => ... with getSession(hono) for manual wiring.");
|
|
8
|
+
}
|
|
9
|
+
return authFromOtokContext(hono, runtime.helpers);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Wrap a loader with typed `auth` helpers from the registered otok-auth runtime.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* export const loader = defineLoader(async ({ auth }) => {
|
|
16
|
+
* const user = await auth.requireUser();
|
|
17
|
+
* return { user };
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function defineLoader(handler) {
|
|
22
|
+
return (context) => handler({ ...context, auth: resolveAuth(context.hono) });
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Wrap an action with typed `auth` helpers from the registered otok-auth runtime.
|
|
26
|
+
*/
|
|
27
|
+
export function defineAction(handler) {
|
|
28
|
+
return (context) => handler({ ...context, auth: resolveAuth(context.hono) });
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AASlD,SAAS,WAAW,CAAyB,IAAyB;IACpE,MAAM,OAAO,GAAG,iBAAiB,EAAS,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,2EAA2E;YACzE,wEAAwE,CAC3E,CAAC;IACJ,CAAC;IACD,OAAO,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAuE;IAEvE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAiF;IAEjF,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-guard.d.ts","sourceRoot":"","sources":["../../src/middleware/api-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,wBAAgB,cAAc,CAAC,KAAK,EAClC,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GAC7C,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAEvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-guard.js","sourceRoot":"","sources":["../../src/middleware/api-guard.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAC5B,OAA8C;IAE9C,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.d.ts","sourceRoot":"","sources":["../../src/middleware/csrf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5E,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,WAAgB,GAAG,cAAc,CAsB9E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineMiddleware } from "@kamod-ch/otok/server";
|
|
2
|
+
import { assertCsrf, ensureCsrfCookie } from "../csrf.js";
|
|
3
|
+
export function createCsrfMiddleware(options = {}) {
|
|
4
|
+
return defineMiddleware(async (c, next) => {
|
|
5
|
+
const method = c.req.method.toUpperCase();
|
|
6
|
+
if (method === "GET" || method === "HEAD") {
|
|
7
|
+
ensureCsrfCookie(c, options);
|
|
8
|
+
await next();
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE") {
|
|
12
|
+
const contentType = c.req.header("content-type") ?? "";
|
|
13
|
+
if (contentType.includes("application/x-www-form-urlencoded") ||
|
|
14
|
+
contentType.includes("multipart/form-data")) {
|
|
15
|
+
const formData = await c.req.raw.clone().formData();
|
|
16
|
+
assertCsrf(c, formData, options);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
await next();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=csrf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.js","sourceRoot":"","sources":["../../src/middleware/csrf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAuB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAE5E,MAAM,UAAU,oBAAoB,CAAC,UAAuB,EAAE;IAC5D,OAAO,gBAAgB,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1C,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC7B,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACvF,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YACvD,IACE,WAAW,CAAC,QAAQ,CAAC,mCAAmC,CAAC;gBACzD,WAAW,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAC3C,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,CAAC;gBACpD,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createApiGuard } from "./api-guard.js";
|
|
2
|
+
export { createCsrfMiddleware } from "./csrf.js";
|
|
3
|
+
export { createRequireAuthMiddleware, type RequireAuthOptions } from "./require-auth.js";
|
|
4
|
+
export { composeMiddleware, createRequireRoleMiddleware, createSessionContextMiddleware, createTenantMiddleware, type RequireRoleMiddlewareOptions, type SessionContextMiddlewareOptions, type TenantMiddlewareOptions, } from "./rbac.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,2BAA2B,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,uBAAuB,GAC7B,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createApiGuard } from "./api-guard.js";
|
|
2
|
+
export { createCsrfMiddleware } from "./csrf.js";
|
|
3
|
+
export { createRequireAuthMiddleware } from "./require-auth.js";
|
|
4
|
+
export { composeMiddleware, createRequireRoleMiddleware, createSessionContextMiddleware, createTenantMiddleware, } from "./rbac.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,2BAA2B,EAA2B,MAAM,mBAAmB,CAAC;AACzF,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,GAIvB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import { type OtokMiddleware } from "@kamod-ch/otok/server";
|
|
3
|
+
export interface SessionContextMiddlewareOptions<TUser> {
|
|
4
|
+
/** Defaults to `c.get("user")`. */
|
|
5
|
+
getUser?: (c: Context) => TUser | undefined;
|
|
6
|
+
set: Record<string, (user: TUser) => unknown>;
|
|
7
|
+
}
|
|
8
|
+
export declare function createSessionContextMiddleware<TUser>(options: SessionContextMiddlewareOptions<TUser>): OtokMiddleware;
|
|
9
|
+
export interface TenantMiddlewareOptions<TUser> {
|
|
10
|
+
getUser?: (c: Context) => TUser | undefined;
|
|
11
|
+
getTenantId: (user: TUser) => string;
|
|
12
|
+
/** Defaults to `tenantId`. Use `organizationId`, `workspaceId`, etc. */
|
|
13
|
+
contextKey?: string;
|
|
14
|
+
also?: Record<string, (user: TUser) => unknown>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createTenantMiddleware<TUser>(options: TenantMiddlewareOptions<TUser>): OtokMiddleware;
|
|
17
|
+
export interface RequireRoleMiddlewareOptions<TUser, TRole extends string = string> {
|
|
18
|
+
getUser?: (c: Context) => TUser | undefined;
|
|
19
|
+
getRole: (user: TUser) => TRole;
|
|
20
|
+
allowed: readonly TRole[];
|
|
21
|
+
loginPath?: string;
|
|
22
|
+
message?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function createRequireRoleMiddleware<TUser, TRole extends string = string>(options: RequireRoleMiddlewareOptions<TUser, TRole>): OtokMiddleware;
|
|
25
|
+
export declare function composeMiddleware(...middlewares: OtokMiddleware[]): OtokMiddleware;
|
|
26
|
+
//# sourceMappingURL=rbac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../../src/middleware/rbac.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO9F,MAAM,WAAW,+BAA+B,CAAC,KAAK;IACpD,mCAAmC;IACnC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,KAAK,GAAG,SAAS,CAAC;IAC5C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC;CAC/C;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAClD,OAAO,EAAE,+BAA+B,CAAC,KAAK,CAAC,GAC9C,cAAc,CAWhB;AAED,MAAM,WAAW,uBAAuB,CAAC,KAAK;IAC5C,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,KAAK,GAAG,SAAS,CAAC;IAC5C,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;IACrC,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC;CACjD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAC1C,OAAO,EAAE,uBAAuB,CAAC,KAAK,CAAC,GACtC,cAAc,CAShB;AAED,MAAM,WAAW,4BAA4B,CAAC,KAAK,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM;IAChF,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,KAAK,GAAG,SAAS,CAAC;IAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,KAAK,CAAC;IAChC,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM,EAC9E,OAAO,EAAE,4BAA4B,CAAC,KAAK,EAAE,KAAK,CAAC,GAClD,cAAc,CAehB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,WAAW,EAAE,cAAc,EAAE,GAAG,cAAc,CAqBlF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { defineMiddleware, fail, redirect } from "@kamod-ch/otok/server";
|
|
2
|
+
function readUser(c, getUser) {
|
|
3
|
+
if (getUser)
|
|
4
|
+
return getUser(c);
|
|
5
|
+
return c.get("user");
|
|
6
|
+
}
|
|
7
|
+
export function createSessionContextMiddleware(options) {
|
|
8
|
+
return defineMiddleware(async (c, next) => {
|
|
9
|
+
const user = readUser(c, options.getUser);
|
|
10
|
+
if (!user)
|
|
11
|
+
redirect("/login", 303);
|
|
12
|
+
for (const [key, getter] of Object.entries(options.set)) {
|
|
13
|
+
c.set(key, getter(user));
|
|
14
|
+
}
|
|
15
|
+
await next();
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function createTenantMiddleware(options) {
|
|
19
|
+
const contextKey = options.contextKey ?? "tenantId";
|
|
20
|
+
return createSessionContextMiddleware({
|
|
21
|
+
getUser: options.getUser,
|
|
22
|
+
set: {
|
|
23
|
+
[contextKey]: options.getTenantId,
|
|
24
|
+
...options.also,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export function createRequireRoleMiddleware(options) {
|
|
29
|
+
const loginPath = options.loginPath ?? "/login";
|
|
30
|
+
const message = options.message ?? "Insufficient permissions";
|
|
31
|
+
return defineMiddleware(async (c, next) => {
|
|
32
|
+
const user = readUser(c, options.getUser);
|
|
33
|
+
if (!user)
|
|
34
|
+
redirect(loginPath, 303);
|
|
35
|
+
const role = options.getRole(user);
|
|
36
|
+
if (!options.allowed.includes(role)) {
|
|
37
|
+
fail(403, { formErrors: [message] });
|
|
38
|
+
}
|
|
39
|
+
await next();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function composeMiddleware(...middlewares) {
|
|
43
|
+
return defineMiddleware(async (c, next) => {
|
|
44
|
+
async function dispatch(index) {
|
|
45
|
+
const middleware = middlewares[index];
|
|
46
|
+
if (!middleware) {
|
|
47
|
+
await next();
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
let downstream;
|
|
51
|
+
const result = await middleware(c, async () => {
|
|
52
|
+
downstream = await dispatch(index + 1);
|
|
53
|
+
});
|
|
54
|
+
if (result instanceof Response)
|
|
55
|
+
return result;
|
|
56
|
+
return downstream;
|
|
57
|
+
}
|
|
58
|
+
const response = await dispatch(0);
|
|
59
|
+
if (response instanceof Response)
|
|
60
|
+
return response;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=rbac.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.js","sourceRoot":"","sources":["../../src/middleware/rbac.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import { type OtokMiddleware } from "@kamod-ch/otok/server";
|
|
3
|
+
export interface RequireAuthOptions<TUser> {
|
|
4
|
+
getUser: (c: Context) => Promise<TUser | null>;
|
|
5
|
+
loginPath?: string;
|
|
6
|
+
publicPaths?: Iterable<string>;
|
|
7
|
+
contextKey?: string;
|
|
8
|
+
onAuthenticated?: (c: Context, user: TUser) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createRequireAuthMiddleware<TUser>(options: RequireAuthOptions<TUser>): OtokMiddleware;
|
|
11
|
+
//# sourceMappingURL=require-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-auth.d.ts","sourceRoot":"","sources":["../../src/middleware/require-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAA8B,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAExF,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;CACrD;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAC/C,OAAO,EAAE,kBAAkB,CAAC,KAAK,CAAC,GACjC,cAAc,CAiBhB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineMiddleware, redirect } from "@kamod-ch/otok/server";
|
|
2
|
+
export function createRequireAuthMiddleware(options) {
|
|
3
|
+
const loginPath = options.loginPath ?? "/login";
|
|
4
|
+
const publicPaths = new Set(options.publicPaths ?? []);
|
|
5
|
+
const contextKey = options.contextKey ?? "user";
|
|
6
|
+
return defineMiddleware(async (c, next) => {
|
|
7
|
+
const pathname = new URL(c.req.url).pathname;
|
|
8
|
+
if (publicPaths.has(pathname)) {
|
|
9
|
+
await next();
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const user = await options.getUser(c);
|
|
13
|
+
if (!user)
|
|
14
|
+
redirect(loginPath, 303);
|
|
15
|
+
c.set(contextKey, user);
|
|
16
|
+
options.onAuthenticated?.(c, user);
|
|
17
|
+
await next();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=require-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-auth.js","sourceRoot":"","sources":["../../src/middleware/require-auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAuB,MAAM,uBAAuB,CAAC;AAUxF,MAAM,UAAU,2BAA2B,CACzC,OAAkC;IAElC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,QAAQ,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC;IAEhD,OAAO,gBAAgB,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QAC7C,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI;YAAE,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACxB,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACnC,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge-safe password hashing via Web Crypto PBKDF2 (Workers / browsers / Node 20+).
|
|
3
|
+
* Prefer `@node-rs/argon2` (`hashPassword` / `verifyPassword`) on Node when available.
|
|
4
|
+
*
|
|
5
|
+
* Encoded format: `pbkdf2$iterations$saltB64$hashB64`
|
|
6
|
+
*/
|
|
7
|
+
export declare function hashPasswordWebCrypto(password: string, options?: {
|
|
8
|
+
iterations?: number;
|
|
9
|
+
}): Promise<string>;
|
|
10
|
+
export declare function verifyPasswordWebCrypto(passwordHash: string, password: string): Promise<boolean>;
|
|
11
|
+
//# sourceMappingURL=password-webcrypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-webcrypto.d.ts","sourceRoot":"","sources":["../src/password-webcrypto.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyDH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CASlB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge-safe password hashing via Web Crypto PBKDF2 (Workers / browsers / Node 20+).
|
|
3
|
+
* Prefer `@node-rs/argon2` (`hashPassword` / `verifyPassword`) on Node when available.
|
|
4
|
+
*
|
|
5
|
+
* Encoded format: `pbkdf2$iterations$saltB64$hashB64`
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_ITERATIONS = 310_000;
|
|
8
|
+
const SALT_BYTES = 16;
|
|
9
|
+
const KEY_BITS = 256;
|
|
10
|
+
function toBase64(bytes) {
|
|
11
|
+
if (typeof Buffer !== "undefined") {
|
|
12
|
+
return Buffer.from(bytes).toString("base64");
|
|
13
|
+
}
|
|
14
|
+
let binary = "";
|
|
15
|
+
for (const byte of bytes)
|
|
16
|
+
binary += String.fromCharCode(byte);
|
|
17
|
+
return btoa(binary);
|
|
18
|
+
}
|
|
19
|
+
function fromBase64(value) {
|
|
20
|
+
if (typeof Buffer !== "undefined") {
|
|
21
|
+
return new Uint8Array(Buffer.from(value, "base64"));
|
|
22
|
+
}
|
|
23
|
+
const binary = atob(value);
|
|
24
|
+
const bytes = new Uint8Array(binary.length);
|
|
25
|
+
for (let i = 0; i < binary.length; i++)
|
|
26
|
+
bytes[i] = binary.charCodeAt(i);
|
|
27
|
+
return bytes;
|
|
28
|
+
}
|
|
29
|
+
function timingSafeEqual(a, b) {
|
|
30
|
+
if (a.length !== b.length)
|
|
31
|
+
return false;
|
|
32
|
+
let diff = 0;
|
|
33
|
+
for (let i = 0; i < a.length; i++)
|
|
34
|
+
diff |= a[i] ^ b[i];
|
|
35
|
+
return diff === 0;
|
|
36
|
+
}
|
|
37
|
+
async function deriveKey(password, salt, iterations) {
|
|
38
|
+
const material = await crypto.subtle.importKey("raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveBits"]);
|
|
39
|
+
const bits = await crypto.subtle.deriveBits({
|
|
40
|
+
name: "PBKDF2",
|
|
41
|
+
hash: "SHA-256",
|
|
42
|
+
salt: salt,
|
|
43
|
+
iterations,
|
|
44
|
+
}, material, KEY_BITS);
|
|
45
|
+
return new Uint8Array(bits);
|
|
46
|
+
}
|
|
47
|
+
export async function hashPasswordWebCrypto(password, options) {
|
|
48
|
+
const iterations = options?.iterations ?? DEFAULT_ITERATIONS;
|
|
49
|
+
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));
|
|
50
|
+
const hash = await deriveKey(password, salt, iterations);
|
|
51
|
+
return `pbkdf2$${iterations}$${toBase64(salt)}$${toBase64(hash)}`;
|
|
52
|
+
}
|
|
53
|
+
export async function verifyPasswordWebCrypto(passwordHash, password) {
|
|
54
|
+
const parts = passwordHash.split("$");
|
|
55
|
+
if (parts.length !== 4 || parts[0] !== "pbkdf2")
|
|
56
|
+
return false;
|
|
57
|
+
const iterations = Number(parts[1]);
|
|
58
|
+
if (!Number.isFinite(iterations) || iterations < 1000)
|
|
59
|
+
return false;
|
|
60
|
+
const salt = fromBase64(parts[2]);
|
|
61
|
+
const expected = fromBase64(parts[3]);
|
|
62
|
+
const actual = await deriveKey(password, salt, iterations);
|
|
63
|
+
return timingSafeEqual(actual, expected);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=password-webcrypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-webcrypto.js","sourceRoot":"","sources":["../src/password-webcrypto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAED,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE7F"}
|
package/dist/password.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { hash, verify } from "@node-rs/argon2";
|
|
2
|
+
export async function hashPassword(password) {
|
|
3
|
+
return hash(password, { algorithm: 2 });
|
|
4
|
+
}
|
|
5
|
+
export async function verifyPassword(passwordHash, password) {
|
|
6
|
+
return verify(passwordHash, password);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=password.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.js","sourceRoot":"","sources":["../src/password.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,YAAoB,EAAE,QAAgB;IACzE,OAAO,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import { createAuthHelpers } from "./context.js";
|
|
3
|
+
import { createCsrfMiddleware } from "./middleware/csrf.js";
|
|
4
|
+
import { createRequireAuthMiddleware } from "./middleware/require-auth.js";
|
|
5
|
+
import { createSessionManager } from "./session/manager.js";
|
|
6
|
+
import type { AuthPluginOptions, AuthUser } from "./types.js";
|
|
7
|
+
declare function configureAuthApp(app: Hono, options: AuthPluginOptions): void;
|
|
8
|
+
/** Otok plugin factory — register after `auth()` in otok.config.ts. */
|
|
9
|
+
export default function auth(options: AuthPluginOptions): import("@kamod-ch/otok-config").OtokPlugin<unknown>;
|
|
10
|
+
/** Factory for programmatic (non-plugin) setup — same options as the plugin. */
|
|
11
|
+
export declare function createAuthRuntime<TUser extends AuthUser>(options: AuthPluginOptions<TUser>): ReturnType<typeof createAuthHelpers<TUser>> & {
|
|
12
|
+
sessions: ReturnType<typeof createSessionManager<TUser>>;
|
|
13
|
+
middleware: {
|
|
14
|
+
requireAuth: ReturnType<typeof createRequireAuthMiddleware<TUser>>;
|
|
15
|
+
csrf: ReturnType<typeof createCsrfMiddleware>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export { configureAuthApp };
|
|
19
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc9D,iBAAS,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAkDrE;AA6BD,uEAAuE;AACvE,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAO,EAAE,iBAAiB,uDAMtD;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,QAAQ,EACtD,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAChC,UAAU,CAAC,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC,GAAG;IAC/C,QAAQ,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,UAAU,EAAE;QACV,WAAW,EAAE,UAAU,CAAC,OAAO,2BAA2B,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;KAC/C,CAAC;CACH,CAyCA;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|