@jsango/auth 1.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 +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/base64url.d.ts +6 -0
- package/dist/internal/base64url.d.ts.map +1 -0
- package/dist/internal/base64url.js +21 -0
- package/dist/internal/base64url.js.map +1 -0
- package/dist/internal/crypto-utils.d.ts +11 -0
- package/dist/internal/crypto-utils.d.ts.map +1 -0
- package/dist/internal/crypto-utils.js +16 -0
- package/dist/internal/crypto-utils.js.map +1 -0
- package/dist/internal/timing.d.ts +5 -0
- package/dist/internal/timing.d.ts.map +1 -0
- package/dist/internal/timing.js +15 -0
- package/dist/internal/timing.js.map +1 -0
- package/dist/public/authentication/api-key.d.ts +17 -0
- package/dist/public/authentication/api-key.d.ts.map +1 -0
- package/dist/public/authentication/api-key.js +57 -0
- package/dist/public/authentication/api-key.js.map +1 -0
- package/dist/public/authentication/bearer.d.ts +27 -0
- package/dist/public/authentication/bearer.d.ts.map +1 -0
- package/dist/public/authentication/bearer.js +97 -0
- package/dist/public/authentication/bearer.js.map +1 -0
- package/dist/public/authentication/jwt.d.ts +60 -0
- package/dist/public/authentication/jwt.d.ts.map +1 -0
- package/dist/public/authentication/jwt.js +154 -0
- package/dist/public/authentication/jwt.js.map +1 -0
- package/dist/public/authentication/manager.d.ts +23 -0
- package/dist/public/authentication/manager.d.ts.map +1 -0
- package/dist/public/authentication/manager.js +64 -0
- package/dist/public/authentication/manager.js.map +1 -0
- package/dist/public/authentication/password.d.ts +24 -0
- package/dist/public/authentication/password.d.ts.map +1 -0
- package/dist/public/authentication/password.js +108 -0
- package/dist/public/authentication/password.js.map +1 -0
- package/dist/public/authentication/session.d.ts +31 -0
- package/dist/public/authentication/session.d.ts.map +1 -0
- package/dist/public/authentication/session.js +165 -0
- package/dist/public/authentication/session.js.map +1 -0
- package/dist/public/authentication/totp.d.ts +52 -0
- package/dist/public/authentication/totp.d.ts.map +1 -0
- package/dist/public/authentication/totp.js +138 -0
- package/dist/public/authentication/totp.js.map +1 -0
- package/dist/public/authorization/composite.d.ts +23 -0
- package/dist/public/authorization/composite.d.ts.map +1 -0
- package/dist/public/authorization/composite.js +79 -0
- package/dist/public/authorization/composite.js.map +1 -0
- package/dist/public/authorization/decision.d.ts +11 -0
- package/dist/public/authorization/decision.d.ts.map +1 -0
- package/dist/public/authorization/decision.js +19 -0
- package/dist/public/authorization/decision.js.map +1 -0
- package/dist/public/authorization/manager.d.ts +39 -0
- package/dist/public/authorization/manager.d.ts.map +1 -0
- package/dist/public/authorization/manager.js +138 -0
- package/dist/public/authorization/manager.js.map +1 -0
- package/dist/public/authorization/permission.d.ts +20 -0
- package/dist/public/authorization/permission.d.ts.map +1 -0
- package/dist/public/authorization/permission.js +46 -0
- package/dist/public/authorization/permission.js.map +1 -0
- package/dist/public/authorization/policy.d.ts +30 -0
- package/dist/public/authorization/policy.d.ts.map +1 -0
- package/dist/public/authorization/policy.js +93 -0
- package/dist/public/authorization/policy.js.map +1 -0
- package/dist/public/authorization/role.d.ts +17 -0
- package/dist/public/authorization/role.d.ts.map +1 -0
- package/dist/public/authorization/role.js +43 -0
- package/dist/public/authorization/role.js.map +1 -0
- package/dist/public/context/auth-context.d.ts +8 -0
- package/dist/public/context/auth-context.d.ts.map +1 -0
- package/dist/public/context/auth-context.js +33 -0
- package/dist/public/context/auth-context.js.map +1 -0
- package/dist/public/errors.d.ts +33 -0
- package/dist/public/errors.d.ts.map +1 -0
- package/dist/public/errors.js +89 -0
- package/dist/public/errors.js.map +1 -0
- package/dist/public/identity.d.ts +40 -0
- package/dist/public/identity.d.ts.map +1 -0
- package/dist/public/identity.js +102 -0
- package/dist/public/identity.js.map +1 -0
- package/dist/public/index.d.ts +23 -0
- package/dist/public/index.d.ts.map +1 -0
- package/dist/public/index.js +29 -0
- package/dist/public/index.js.map +1 -0
- package/dist/public/middleware/authenticate.d.ts +10 -0
- package/dist/public/middleware/authenticate.d.ts.map +1 -0
- package/dist/public/middleware/authenticate.js +65 -0
- package/dist/public/middleware/authenticate.js.map +1 -0
- package/dist/public/middleware/authorize.d.ts +11 -0
- package/dist/public/middleware/authorize.d.ts.map +1 -0
- package/dist/public/middleware/authorize.js +42 -0
- package/dist/public/middleware/authorize.js.map +1 -0
- package/dist/public/types.d.ts +75 -0
- package/dist/public/types.d.ts.map +1 -0
- package/dist/public/types.js +2 -0
- package/dist/public/types.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class RoleRegistry {
|
|
2
|
+
roles = new Map();
|
|
3
|
+
register(role) {
|
|
4
|
+
if (this.roles.has(role.name)) {
|
|
5
|
+
throw new Error(`Role "${role.name}" is already registered.`);
|
|
6
|
+
}
|
|
7
|
+
this.roles.set(role.name, Object.freeze({
|
|
8
|
+
...role,
|
|
9
|
+
permissions: Object.freeze([...role.permissions]),
|
|
10
|
+
}));
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
13
|
+
registerMany(roles) {
|
|
14
|
+
for (const role of roles) {
|
|
15
|
+
this.register(role);
|
|
16
|
+
}
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
get(name) {
|
|
20
|
+
return this.roles.get(name);
|
|
21
|
+
}
|
|
22
|
+
has(name) {
|
|
23
|
+
return this.roles.has(name);
|
|
24
|
+
}
|
|
25
|
+
getPermissionsForRole(roleName) {
|
|
26
|
+
const role = this.roles.get(roleName);
|
|
27
|
+
return role ? role.permissions : [];
|
|
28
|
+
}
|
|
29
|
+
getPermissionsForRoles(roleNames) {
|
|
30
|
+
const permissionsSet = new Set();
|
|
31
|
+
for (const roleName of roleNames) {
|
|
32
|
+
const permissions = this.getPermissionsForRole(roleName);
|
|
33
|
+
for (const p of permissions) {
|
|
34
|
+
permissionsSet.add(p);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return Object.freeze(Array.from(permissionsSet));
|
|
38
|
+
}
|
|
39
|
+
getAll() {
|
|
40
|
+
return Object.freeze(Array.from(this.roles.values()));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=role.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role.js","sourceRoot":"","sources":["../../../src/public/authorization/role.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,YAAY;IACN,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEpD,QAAQ,CAAC,IAAoB;QAClC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CACZ,IAAI,CAAC,IAAI,EACT,MAAM,CAAC,MAAM,CAAC;YACZ,GAAG,IAAI;YACP,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;SAClD,CAAC,CACH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,YAAY,CAAC,KAAgC;QAClD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,GAAG,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAEM,GAAG,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAEM,qBAAqB,CAAC,QAAgB;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC;IAEM,sBAAsB,CAAC,SAA4B;QACxD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;QACzC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YACzD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC5B,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IACnD,CAAC;IAEM,MAAM;QACX,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RequestContext } from '@jsango/http';
|
|
2
|
+
import type { AuthContext, Identity } from '../types.js';
|
|
3
|
+
export declare const AUTH_CONTEXT_STATE_KEY = "jsango:auth";
|
|
4
|
+
export declare function setAuthContext(ctx: RequestContext, authContext: AuthContext): void;
|
|
5
|
+
export declare function getAuthContext(ctx: RequestContext): AuthContext | undefined;
|
|
6
|
+
export declare function getIdentity(ctx: RequestContext): Identity;
|
|
7
|
+
export declare function requireIdentity(ctx: RequestContext): Identity;
|
|
8
|
+
//# sourceMappingURL=auth-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-context.d.ts","sourceRoot":"","sources":["../../../src/public/context/auth-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAUlF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,WAAW,GAAG,SAAS,CAE3E;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,CAMzD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,CAM7D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AnonymousIdentity } from '../identity.js';
|
|
2
|
+
import { UnauthenticatedError } from '../errors.js';
|
|
3
|
+
export const AUTH_CONTEXT_STATE_KEY = 'jsango:auth';
|
|
4
|
+
export function setAuthContext(ctx, authContext) {
|
|
5
|
+
ctx.state.set(AUTH_CONTEXT_STATE_KEY, authContext);
|
|
6
|
+
if (ctx.container) {
|
|
7
|
+
try {
|
|
8
|
+
ctx.container.register('auth.identity', authContext.identity);
|
|
9
|
+
ctx.container.register('auth.context', authContext);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Container may be locked or immutable in certain test scopes; state map is primary
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getAuthContext(ctx) {
|
|
17
|
+
return ctx.state.get(AUTH_CONTEXT_STATE_KEY);
|
|
18
|
+
}
|
|
19
|
+
export function getIdentity(ctx) {
|
|
20
|
+
const authCtx = getAuthContext(ctx);
|
|
21
|
+
if (authCtx?.identity) {
|
|
22
|
+
return authCtx.identity;
|
|
23
|
+
}
|
|
24
|
+
return new AnonymousIdentity();
|
|
25
|
+
}
|
|
26
|
+
export function requireIdentity(ctx) {
|
|
27
|
+
const identity = getIdentity(ctx);
|
|
28
|
+
if (!identity.isAuthenticated) {
|
|
29
|
+
throw new UnauthenticatedError('Authentication is required to access this resource.');
|
|
30
|
+
}
|
|
31
|
+
return identity;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=auth-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-context.js","sourceRoot":"","sources":["../../../src/public/context/auth-context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,aAAa,CAAC;AAEpD,MAAM,UAAU,cAAc,CAAC,GAAmB,EAAE,WAAwB;IAC1E,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,EAAE,WAAW,CAAC,CAAC;IACnD,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC9D,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,oFAAoF;QACtF,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAmB;IAChD,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAA4B,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAmB;IAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC,QAAQ,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,iBAAiB,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAmB;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC9B,MAAM,IAAI,oBAAoB,CAAC,qDAAqD,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { JsangoError } from '@jsango/core';
|
|
2
|
+
export interface AuthErrorOptions {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly message: string;
|
|
5
|
+
readonly cause?: unknown;
|
|
6
|
+
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
|
|
7
|
+
readonly statusCode?: number | undefined;
|
|
8
|
+
}
|
|
9
|
+
export declare class AuthenticationError extends JsangoError {
|
|
10
|
+
constructor(options: AuthErrorOptions);
|
|
11
|
+
}
|
|
12
|
+
export declare class UnauthenticatedError extends AuthenticationError {
|
|
13
|
+
constructor(message?: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class InvalidCredentialsError extends AuthenticationError {
|
|
16
|
+
constructor(message?: string);
|
|
17
|
+
}
|
|
18
|
+
export declare class TokenExpiredError extends AuthenticationError {
|
|
19
|
+
constructor(message?: string);
|
|
20
|
+
}
|
|
21
|
+
export declare class SessionExpiredError extends AuthenticationError {
|
|
22
|
+
constructor(message?: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class AuthorizationError extends JsangoError {
|
|
25
|
+
constructor(options: AuthErrorOptions);
|
|
26
|
+
}
|
|
27
|
+
export declare class ForbiddenError extends AuthorizationError {
|
|
28
|
+
constructor(message?: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class PolicyError extends AuthorizationError {
|
|
31
|
+
constructor(policyName: string, message?: string);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/public/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,qBAAa,mBAAoB,SAAQ,WAAW;gBAC/B,OAAO,EAAE,gBAAgB;CAW7C;AAED,qBAAa,oBAAqB,SAAQ,mBAAmB;gBACxC,OAAO,SAA6C;CAQxE;AAED,qBAAa,uBAAwB,SAAQ,mBAAmB;gBAC3C,OAAO,SAAwC;CAQnE;AAED,qBAAa,iBAAkB,SAAQ,mBAAmB;gBACrC,OAAO,SAAsC;CAQjE;AAED,qBAAa,mBAAoB,SAAQ,mBAAmB;gBACvC,OAAO,SAAwC;CAQnE;AAED,qBAAa,kBAAmB,SAAQ,WAAW;gBAC9B,OAAO,EAAE,gBAAgB;CAW7C;AAED,qBAAa,cAAe,SAAQ,kBAAkB;gBACjC,OAAO,SAAuD;CAQlF;AAED,qBAAa,WAAY,SAAQ,kBAAkB;gBAC9B,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CASxD"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { JsangoError } from '@jsango/core';
|
|
2
|
+
export class AuthenticationError extends JsangoError {
|
|
3
|
+
constructor(options) {
|
|
4
|
+
super({
|
|
5
|
+
code: options.code,
|
|
6
|
+
message: options.message,
|
|
7
|
+
cause: options.cause,
|
|
8
|
+
metadata: options.metadata,
|
|
9
|
+
statusCode: options.statusCode ?? 401,
|
|
10
|
+
});
|
|
11
|
+
this.name = 'AuthenticationError';
|
|
12
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class UnauthenticatedError extends AuthenticationError {
|
|
16
|
+
constructor(message = 'Authentication credentials are required.') {
|
|
17
|
+
super({
|
|
18
|
+
code: 'ERR_AUTH_UNAUTHENTICATED',
|
|
19
|
+
message,
|
|
20
|
+
statusCode: 401,
|
|
21
|
+
});
|
|
22
|
+
this.name = 'UnauthenticatedError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class InvalidCredentialsError extends AuthenticationError {
|
|
26
|
+
constructor(message = 'Invalid authentication credentials.') {
|
|
27
|
+
super({
|
|
28
|
+
code: 'ERR_AUTH_INVALID_CREDENTIALS',
|
|
29
|
+
message,
|
|
30
|
+
statusCode: 401,
|
|
31
|
+
});
|
|
32
|
+
this.name = 'InvalidCredentialsError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class TokenExpiredError extends AuthenticationError {
|
|
36
|
+
constructor(message = 'Authentication token has expired.') {
|
|
37
|
+
super({
|
|
38
|
+
code: 'ERR_AUTH_TOKEN_EXPIRED',
|
|
39
|
+
message,
|
|
40
|
+
statusCode: 401,
|
|
41
|
+
});
|
|
42
|
+
this.name = 'TokenExpiredError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class SessionExpiredError extends AuthenticationError {
|
|
46
|
+
constructor(message = 'Authentication session has expired.') {
|
|
47
|
+
super({
|
|
48
|
+
code: 'ERR_AUTH_SESSION_EXPIRED',
|
|
49
|
+
message,
|
|
50
|
+
statusCode: 401,
|
|
51
|
+
});
|
|
52
|
+
this.name = 'SessionExpiredError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class AuthorizationError extends JsangoError {
|
|
56
|
+
constructor(options) {
|
|
57
|
+
super({
|
|
58
|
+
code: options.code,
|
|
59
|
+
message: options.message,
|
|
60
|
+
cause: options.cause,
|
|
61
|
+
metadata: options.metadata,
|
|
62
|
+
statusCode: options.statusCode ?? 403,
|
|
63
|
+
});
|
|
64
|
+
this.name = 'AuthorizationError';
|
|
65
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class ForbiddenError extends AuthorizationError {
|
|
69
|
+
constructor(message = 'You do not have permission to perform this action.') {
|
|
70
|
+
super({
|
|
71
|
+
code: 'ERR_AUTH_FORBIDDEN',
|
|
72
|
+
message,
|
|
73
|
+
statusCode: 403,
|
|
74
|
+
});
|
|
75
|
+
this.name = 'ForbiddenError';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export class PolicyError extends AuthorizationError {
|
|
79
|
+
constructor(policyName, message) {
|
|
80
|
+
super({
|
|
81
|
+
code: 'ERR_AUTH_POLICY_VIOLATION',
|
|
82
|
+
message: message ?? `Access denied by policy "${policyName}".`,
|
|
83
|
+
metadata: { policy: policyName },
|
|
84
|
+
statusCode: 403,
|
|
85
|
+
});
|
|
86
|
+
this.name = 'PolicyError';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/public/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Identity, IdentityType } from './types.js';
|
|
2
|
+
export interface IdentityOptions {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly type?: IdentityType | undefined;
|
|
5
|
+
readonly isAuthenticated?: boolean | undefined;
|
|
6
|
+
readonly isSuperuser?: boolean | undefined;
|
|
7
|
+
readonly roles?: readonly string[] | undefined;
|
|
8
|
+
readonly permissions?: readonly string[] | undefined;
|
|
9
|
+
readonly tenantId?: string | undefined;
|
|
10
|
+
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare abstract class BaseIdentity implements Identity {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly type: IdentityType;
|
|
15
|
+
readonly isAuthenticated: boolean;
|
|
16
|
+
readonly isSuperuser: boolean;
|
|
17
|
+
readonly roles: readonly string[];
|
|
18
|
+
readonly permissions: readonly string[];
|
|
19
|
+
readonly tenantId?: string | undefined;
|
|
20
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
21
|
+
constructor(options: IdentityOptions);
|
|
22
|
+
hasRole(role: string): boolean;
|
|
23
|
+
hasPermission(permission: string): boolean;
|
|
24
|
+
toJSON(): Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
export declare class UserIdentity extends BaseIdentity {
|
|
27
|
+
constructor(options: Omit<IdentityOptions, 'isAuthenticated' | 'type'> & {
|
|
28
|
+
type?: IdentityType;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export declare class AnonymousIdentity extends BaseIdentity {
|
|
32
|
+
constructor();
|
|
33
|
+
}
|
|
34
|
+
export declare class SystemIdentity extends BaseIdentity {
|
|
35
|
+
constructor(options?: Partial<Omit<IdentityOptions, 'id' | 'type' | 'isAuthenticated' | 'isSuperuser'>>);
|
|
36
|
+
}
|
|
37
|
+
export declare class ServiceAccountIdentity extends BaseIdentity {
|
|
38
|
+
constructor(options: Omit<IdentityOptions, 'isAuthenticated' | 'type'>);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/public/identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;CACnE;AAED,8BAAsB,YAAa,YAAW,QAAQ;IACpD,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B,SAAgB,IAAI,EAAE,YAAY,CAAC;IACnC,SAAgB,eAAe,EAAE,OAAO,CAAC;IACzC,SAAgB,WAAW,EAAE,OAAO,CAAC;IACrC,SAAgB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,SAAgB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,SAAgB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,SAAgB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;gBAEzC,OAAO,EAAE,eAAe;IAWpC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAO9B,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAuB1C,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYzC;AAED,qBAAa,YAAa,SAAQ,YAAY;gBAE1C,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,YAAY,CAAA;KAAE;CAQvF;AAED,qBAAa,iBAAkB,SAAQ,YAAY;;CAWlD;AAED,qBAAa,cAAe,SAAQ,YAAY;gBAE5C,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,iBAAiB,GAAG,aAAa,CAAC,CAAM;CAYlG;AAED,qBAAa,sBAAuB,SAAQ,YAAY;gBACnC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,MAAM,CAAC;CAO9E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export class BaseIdentity {
|
|
2
|
+
id;
|
|
3
|
+
type;
|
|
4
|
+
isAuthenticated;
|
|
5
|
+
isSuperuser;
|
|
6
|
+
roles;
|
|
7
|
+
permissions;
|
|
8
|
+
tenantId;
|
|
9
|
+
metadata;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.id = options.id;
|
|
12
|
+
this.type = options.type ?? 'user';
|
|
13
|
+
this.isAuthenticated = options.isAuthenticated ?? false;
|
|
14
|
+
this.isSuperuser = options.isSuperuser ?? false;
|
|
15
|
+
this.roles = Object.freeze([...(options.roles ?? [])]);
|
|
16
|
+
this.permissions = Object.freeze([...(options.permissions ?? [])]);
|
|
17
|
+
this.tenantId = options.tenantId;
|
|
18
|
+
this.metadata = Object.freeze({ ...(options.metadata ?? {}) });
|
|
19
|
+
}
|
|
20
|
+
hasRole(role) {
|
|
21
|
+
if (this.isSuperuser) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return this.roles.includes(role);
|
|
25
|
+
}
|
|
26
|
+
hasPermission(permission) {
|
|
27
|
+
if (this.isSuperuser) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (this.permissions.includes('*')) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (this.permissions.includes(permission)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// Wildcard matching: e.g. "users.*" matches "users.read"
|
|
37
|
+
const dotIndex = permission.indexOf('.');
|
|
38
|
+
if (dotIndex !== -1) {
|
|
39
|
+
const namespace = permission.slice(0, dotIndex);
|
|
40
|
+
if (this.permissions.includes(`${namespace}.*`)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
toJSON() {
|
|
47
|
+
return {
|
|
48
|
+
id: this.id,
|
|
49
|
+
type: this.type,
|
|
50
|
+
isAuthenticated: this.isAuthenticated,
|
|
51
|
+
isSuperuser: this.isSuperuser,
|
|
52
|
+
roles: this.roles,
|
|
53
|
+
permissions: this.permissions,
|
|
54
|
+
tenantId: this.tenantId,
|
|
55
|
+
metadata: this.metadata,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export class UserIdentity extends BaseIdentity {
|
|
60
|
+
constructor(options) {
|
|
61
|
+
super({
|
|
62
|
+
...options,
|
|
63
|
+
type: options.type ?? 'user',
|
|
64
|
+
isAuthenticated: true,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class AnonymousIdentity extends BaseIdentity {
|
|
69
|
+
constructor() {
|
|
70
|
+
super({
|
|
71
|
+
id: 'anonymous',
|
|
72
|
+
type: 'anonymous',
|
|
73
|
+
isAuthenticated: false,
|
|
74
|
+
isSuperuser: false,
|
|
75
|
+
roles: [],
|
|
76
|
+
permissions: [],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export class SystemIdentity extends BaseIdentity {
|
|
81
|
+
constructor(options = {}) {
|
|
82
|
+
super({
|
|
83
|
+
...options,
|
|
84
|
+
id: 'system',
|
|
85
|
+
type: 'system',
|
|
86
|
+
isAuthenticated: true,
|
|
87
|
+
isSuperuser: true,
|
|
88
|
+
roles: ['system'],
|
|
89
|
+
permissions: ['*'],
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export class ServiceAccountIdentity extends BaseIdentity {
|
|
94
|
+
constructor(options) {
|
|
95
|
+
super({
|
|
96
|
+
...options,
|
|
97
|
+
type: 'service_account',
|
|
98
|
+
isAuthenticated: true,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/public/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type { Identity, IdentityType, AuthenticationResult, AuthenticationStatus, IAuthenticationStrategy, AuthContext, Session, CreateSessionData, ISessionStore, AuthorizationDecision, PolicyResult, IPolicy, ResourceResolver, } from './types.js';
|
|
2
|
+
export { type AuthErrorOptions, AuthenticationError, UnauthenticatedError, InvalidCredentialsError, TokenExpiredError, SessionExpiredError, AuthorizationError, ForbiddenError, PolicyError, } from './errors.js';
|
|
3
|
+
export { type IdentityOptions, BaseIdentity, UserIdentity, AnonymousIdentity, SystemIdentity, ServiceAccountIdentity, } from './identity.js';
|
|
4
|
+
export { type IPasswordHasher, type ScryptOptions, ScryptPasswordHasher, } from './authentication/password.js';
|
|
5
|
+
export { type JwtAlgorithm, type JwtHeader, type JwtPayload, type JwtSignOptions, type JwtVerifyOptions, type ITokenRevocationStore, MemoryTokenRevocationStore, JwtService, } from './authentication/jwt.js';
|
|
6
|
+
export { type SessionAuthStrategyOptions, MemorySessionStore, SessionAuthenticationStrategy, } from './authentication/session.js';
|
|
7
|
+
export { type TotpSetupOptions, type TotpSecretResult, type TotpVerifyOptions, TotpService, base32Encode, base32Decode, } from './authentication/totp.js';
|
|
8
|
+
export { type ITokenVerifier, type BearerAuthStrategyOptions, JwtTokenVerifier, BearerTokenAuthenticationStrategy, } from './authentication/bearer.js';
|
|
9
|
+
export { type IApiKeyVerifier, type ApiKeyAuthStrategyOptions, ApiKeyAuthenticationStrategy, } from './authentication/api-key.js';
|
|
10
|
+
export { type AuthenticationManagerOptions, AuthenticationManager, } from './authentication/manager.js';
|
|
11
|
+
export { AuthDecision } from './authorization/decision.js';
|
|
12
|
+
export { type PermissionDefinition, PermissionRegistry } from './authorization/permission.js';
|
|
13
|
+
export { type RoleDefinition, RoleRegistry } from './authorization/role.js';
|
|
14
|
+
export { BasePolicy, PolicyRegistry } from './authorization/policy.js';
|
|
15
|
+
export { AndPolicy, OrPolicy, NotPolicy, andPolicy, orPolicy, notPolicy, } from './authorization/composite.js';
|
|
16
|
+
export { type AuthorizationManagerOptions, type AuthorizeOptions, AuthorizationManager, } from './authorization/manager.js';
|
|
17
|
+
export { AUTH_CONTEXT_STATE_KEY, setAuthContext, getAuthContext, getIdentity, requireIdentity, } from './context/auth-context.js';
|
|
18
|
+
export { type AuthenticateOptions, authenticate } from './middleware/authenticate.js';
|
|
19
|
+
export { type AuthorizeMiddlewareOptions, authorize } from './middleware/authorize.js';
|
|
20
|
+
export { timingSafeEqualString } from '../internal/timing.js';
|
|
21
|
+
export { CryptoUtils } from '../internal/crypto-utils.js';
|
|
22
|
+
export { Base64Url } from '../internal/base64url.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/public/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,WAAW,EACX,OAAO,EACP,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,OAAO,EACP,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,KAAK,eAAe,EACpB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,0BAA0B,EAC1B,UAAU,GACX,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,KAAK,0BAA0B,EAC/B,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,yBAAyB,EAC9B,gBAAgB,EAChB,iCAAiC,GAClC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,4BAA4B,GAC7B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,KAAK,4BAA4B,EACjC,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,KAAK,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE9F,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,GACV,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,WAAW,EACX,eAAe,GAChB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,KAAK,mBAAmB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAE,KAAK,0BAA0B,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Errors
|
|
2
|
+
export { AuthenticationError, UnauthenticatedError, InvalidCredentialsError, TokenExpiredError, SessionExpiredError, AuthorizationError, ForbiddenError, PolicyError, } from './errors.js';
|
|
3
|
+
// Identity
|
|
4
|
+
export { BaseIdentity, UserIdentity, AnonymousIdentity, SystemIdentity, ServiceAccountIdentity, } from './identity.js';
|
|
5
|
+
// Authentication
|
|
6
|
+
export { ScryptPasswordHasher, } from './authentication/password.js';
|
|
7
|
+
export { MemoryTokenRevocationStore, JwtService, } from './authentication/jwt.js';
|
|
8
|
+
export { MemorySessionStore, SessionAuthenticationStrategy, } from './authentication/session.js';
|
|
9
|
+
export { TotpService, base32Encode, base32Decode, } from './authentication/totp.js';
|
|
10
|
+
export { JwtTokenVerifier, BearerTokenAuthenticationStrategy, } from './authentication/bearer.js';
|
|
11
|
+
export { ApiKeyAuthenticationStrategy, } from './authentication/api-key.js';
|
|
12
|
+
export { AuthenticationManager, } from './authentication/manager.js';
|
|
13
|
+
// Authorization
|
|
14
|
+
export { AuthDecision } from './authorization/decision.js';
|
|
15
|
+
export { PermissionRegistry } from './authorization/permission.js';
|
|
16
|
+
export { RoleRegistry } from './authorization/role.js';
|
|
17
|
+
export { BasePolicy, PolicyRegistry } from './authorization/policy.js';
|
|
18
|
+
export { AndPolicy, OrPolicy, NotPolicy, andPolicy, orPolicy, notPolicy, } from './authorization/composite.js';
|
|
19
|
+
export { AuthorizationManager, } from './authorization/manager.js';
|
|
20
|
+
// Context Helpers
|
|
21
|
+
export { AUTH_CONTEXT_STATE_KEY, setAuthContext, getAuthContext, getIdentity, requireIdentity, } from './context/auth-context.js';
|
|
22
|
+
// Middleware
|
|
23
|
+
export { authenticate } from './middleware/authenticate.js';
|
|
24
|
+
export { authorize } from './middleware/authorize.js';
|
|
25
|
+
// Utilities
|
|
26
|
+
export { timingSafeEqualString } from '../internal/timing.js';
|
|
27
|
+
export { CryptoUtils } from '../internal/crypto-utils.js';
|
|
28
|
+
export { Base64Url } from '../internal/base64url.js';
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/public/index.ts"],"names":[],"mappings":"AAiBA,SAAS;AACT,OAAO,EAEL,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,WAAW;AACX,OAAO,EAEL,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EAGL,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAOL,0BAA0B,EAC1B,UAAU,GACX,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAEL,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAIL,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAGL,gBAAgB,EAChB,iCAAiC,GAClC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAGL,4BAA4B,GAC7B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAEL,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AAErC,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAA6B,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE9F,OAAO,EAAuB,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,GACV,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAGL,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAEpC,kBAAkB;AAClB,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,WAAW,EACX,eAAe,GAChB,MAAM,2BAA2B,CAAC;AAEnC,aAAa;AACb,OAAO,EAA4B,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAmC,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEvF,YAAY;AACZ,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from '@jsango/middleware';
|
|
2
|
+
import { AuthenticationManager } from '../authentication/manager.js';
|
|
3
|
+
import type { IAuthenticationStrategy } from '../types.js';
|
|
4
|
+
export interface AuthenticateOptions {
|
|
5
|
+
readonly manager?: AuthenticationManager | undefined;
|
|
6
|
+
readonly strategies?: readonly IAuthenticationStrategy[] | undefined;
|
|
7
|
+
readonly required?: boolean | undefined;
|
|
8
|
+
}
|
|
9
|
+
export declare function authenticate(optionsOrManager?: AuthenticationManager | AuthenticateOptions): MiddlewareHandler;
|
|
10
|
+
//# sourceMappingURL=authenticate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../../../src/public/middleware/authenticate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAS5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,KAAK,EAAE,uBAAuB,EAAe,MAAM,aAAa,CAAC;AAExE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,uBAAuB,EAAE,GAAG,SAAS,CAAC;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,wBAAgB,YAAY,CAC1B,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,mBAAmB,GAC7D,iBAAiB,CAkEnB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { AuthenticationError, UnauthenticatedError, InvalidCredentialsError, TokenExpiredError, SessionExpiredError, } from '../errors.js';
|
|
2
|
+
import { AuthenticationManager } from '../authentication/manager.js';
|
|
3
|
+
import { setAuthContext } from '../context/auth-context.js';
|
|
4
|
+
export function authenticate(optionsOrManager) {
|
|
5
|
+
let manager;
|
|
6
|
+
let required = true;
|
|
7
|
+
if (optionsOrManager instanceof AuthenticationManager) {
|
|
8
|
+
manager = optionsOrManager;
|
|
9
|
+
}
|
|
10
|
+
else if (optionsOrManager) {
|
|
11
|
+
if (optionsOrManager.manager) {
|
|
12
|
+
manager = optionsOrManager.manager;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
manager = new AuthenticationManager({
|
|
16
|
+
strategies: optionsOrManager.strategies,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (optionsOrManager.required !== undefined) {
|
|
20
|
+
required = optionsOrManager.required;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
manager = new AuthenticationManager();
|
|
25
|
+
}
|
|
26
|
+
return async (ctx, next) => {
|
|
27
|
+
const result = await manager.authenticate(ctx.request, ctx);
|
|
28
|
+
const authContext = {
|
|
29
|
+
identity: result.identity,
|
|
30
|
+
result,
|
|
31
|
+
strategyUsed: result.strategy,
|
|
32
|
+
tenantId: result.identity.tenantId,
|
|
33
|
+
metadata: result.metadata ?? {},
|
|
34
|
+
};
|
|
35
|
+
setAuthContext(ctx, authContext);
|
|
36
|
+
if (result.status === 'authenticated') {
|
|
37
|
+
return (await next());
|
|
38
|
+
}
|
|
39
|
+
// If authentication is optional (required === false), allow anonymous request to proceed
|
|
40
|
+
if (!required) {
|
|
41
|
+
return (await next());
|
|
42
|
+
}
|
|
43
|
+
// Required authentication failed - throw appropriate structured 401 error
|
|
44
|
+
switch (result.status) {
|
|
45
|
+
case 'unauthenticated':
|
|
46
|
+
throw new UnauthenticatedError('Authentication credentials were not provided.');
|
|
47
|
+
case 'invalid_credentials':
|
|
48
|
+
throw new InvalidCredentialsError(result.error?.message ?? 'Invalid authentication credentials provided.');
|
|
49
|
+
case 'expired_credentials':
|
|
50
|
+
if (result.strategy === 'session') {
|
|
51
|
+
throw new SessionExpiredError();
|
|
52
|
+
}
|
|
53
|
+
throw new TokenExpiredError();
|
|
54
|
+
case 'malformed_credentials':
|
|
55
|
+
throw new AuthenticationError({
|
|
56
|
+
code: 'ERR_AUTH_MALFORMED_CREDENTIALS',
|
|
57
|
+
message: 'Malformed or invalid authentication credentials format.',
|
|
58
|
+
statusCode: 401,
|
|
59
|
+
});
|
|
60
|
+
default:
|
|
61
|
+
throw new UnauthenticatedError('Authentication failed.');
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=authenticate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../../../src/public/middleware/authenticate.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAS5D,MAAM,UAAU,YAAY,CAC1B,gBAA8D;IAE9D,IAAI,OAA8B,CAAC;IACnC,IAAI,QAAQ,GAAG,IAAI,CAAC;IAEpB,IAAI,gBAAgB,YAAY,qBAAqB,EAAE,CAAC;QACtD,OAAO,GAAG,gBAAgB,CAAC;IAC7B,CAAC;SAAM,IAAI,gBAAgB,EAAE,CAAC;QAC5B,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC7B,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,IAAI,qBAAqB,CAAC;gBAClC,UAAU,EAAE,gBAAgB,CAAC,UAAU;aACxC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,gBAAgB,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5C,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;QACvC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,qBAAqB,EAAE,CAAC;IACxC,CAAC;IAED,OAAO,KAAK,EAAE,GAAmB,EAAE,IAAiC,EAAyB,EAAE;QAC7F,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAE5D,MAAM,WAAW,GAAgB;YAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM;YACN,YAAY,EAAE,MAAM,CAAC,QAAQ;YAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;YAClC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;SAChC,CAAC;QAEF,cAAc,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAEjC,IAAI,MAAM,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;YACtC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAiB,CAAC;QACxC,CAAC;QAED,yFAAyF;QACzF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,IAAI,EAAE,CAAiB,CAAC;QACxC,CAAC;QAED,0EAA0E;QAC1E,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,KAAK,iBAAiB;gBACpB,MAAM,IAAI,oBAAoB,CAAC,+CAA+C,CAAC,CAAC;YAClF,KAAK,qBAAqB;gBACxB,MAAM,IAAI,uBAAuB,CAC/B,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,8CAA8C,CACxE,CAAC;YACJ,KAAK,qBAAqB;gBACxB,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAClC,MAAM,IAAI,mBAAmB,EAAE,CAAC;gBAClC,CAAC;gBACD,MAAM,IAAI,iBAAiB,EAAE,CAAC;YAChC,KAAK,uBAAuB;gBAC1B,MAAM,IAAI,mBAAmB,CAAC;oBAC5B,IAAI,EAAE,gCAAgC;oBACtC,OAAO,EAAE,yDAAyD;oBAClE,UAAU,EAAE,GAAG;iBAChB,CAAC,CAAC;YACL;gBACE,MAAM,IAAI,oBAAoB,CAAC,wBAAwB,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from '@jsango/middleware';
|
|
2
|
+
import { AuthorizationManager } from '../authorization/manager.js';
|
|
3
|
+
import type { ResourceResolver, IPolicy } from '../types.js';
|
|
4
|
+
export interface AuthorizeMiddlewareOptions<TResource = unknown> {
|
|
5
|
+
readonly action?: string | undefined;
|
|
6
|
+
readonly resource?: TResource | ResourceResolver<TResource> | undefined;
|
|
7
|
+
readonly policy?: string | IPolicy<TResource> | undefined;
|
|
8
|
+
readonly manager?: AuthorizationManager | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function authorize<TResource = unknown>(action: string, optionsOrResolver?: AuthorizeMiddlewareOptions<TResource> | ResourceResolver<TResource>): MiddlewareHandler;
|
|
11
|
+
//# sourceMappingURL=authorize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../../src/public/middleware/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,WAAW,0BAA0B,CAAC,SAAS,GAAG,OAAO;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACrD;AAED,wBAAgB,SAAS,CAAC,SAAS,GAAG,OAAO,EAC3C,MAAM,EAAE,MAAM,EACd,iBAAiB,CAAC,EAAE,0BAA0B,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC,SAAS,CAAC,GACtF,iBAAiB,CA8CnB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { UnauthenticatedError, ForbiddenError } from '../errors.js';
|
|
2
|
+
import { AuthorizationManager } from '../authorization/manager.js';
|
|
3
|
+
import { getAuthContext, getIdentity } from '../context/auth-context.js';
|
|
4
|
+
export function authorize(action, optionsOrResolver) {
|
|
5
|
+
let manager;
|
|
6
|
+
let resourceOrResolver;
|
|
7
|
+
let policyOverride;
|
|
8
|
+
if (typeof optionsOrResolver === 'function') {
|
|
9
|
+
resourceOrResolver = optionsOrResolver;
|
|
10
|
+
manager = new AuthorizationManager();
|
|
11
|
+
}
|
|
12
|
+
else if (optionsOrResolver) {
|
|
13
|
+
manager = optionsOrResolver.manager ?? new AuthorizationManager();
|
|
14
|
+
resourceOrResolver = optionsOrResolver.resource;
|
|
15
|
+
policyOverride = optionsOrResolver.policy;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
manager = new AuthorizationManager();
|
|
19
|
+
}
|
|
20
|
+
return async (ctx, next) => {
|
|
21
|
+
const identity = getIdentity(ctx);
|
|
22
|
+
// If request has not been authenticated, must return 401 Unauthorized, NOT 403 Forbidden
|
|
23
|
+
if (!identity.isAuthenticated) {
|
|
24
|
+
throw new UnauthenticatedError('Authentication is required before accessing this protected resource.');
|
|
25
|
+
}
|
|
26
|
+
// Resolve resource if resolver function provided
|
|
27
|
+
let resolvedResource = resourceOrResolver;
|
|
28
|
+
if (typeof resourceOrResolver === 'function') {
|
|
29
|
+
resolvedResource = await resourceOrResolver(ctx);
|
|
30
|
+
}
|
|
31
|
+
const authContext = getAuthContext(ctx);
|
|
32
|
+
const decision = await manager.authorize(identity, action, resolvedResource, {
|
|
33
|
+
context: authContext,
|
|
34
|
+
policy: policyOverride,
|
|
35
|
+
});
|
|
36
|
+
if (!decision.allowed) {
|
|
37
|
+
throw new ForbiddenError(decision.reason ?? `Access forbidden: not authorized for action "${action}".`);
|
|
38
|
+
}
|
|
39
|
+
return (await next());
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=authorize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../../src/public/middleware/authorize.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAUzE,MAAM,UAAU,SAAS,CACvB,MAAc,EACd,iBAAuF;IAEvF,IAAI,OAA6B,CAAC;IAClC,IAAI,kBAAuE,CAAC;IAC5E,IAAI,cAAuD,CAAC;IAE5D,IAAI,OAAO,iBAAiB,KAAK,UAAU,EAAE,CAAC;QAC5C,kBAAkB,GAAG,iBAAgD,CAAC;QACtE,OAAO,GAAG,IAAI,oBAAoB,EAAE,CAAC;IACvC,CAAC;SAAM,IAAI,iBAAiB,EAAE,CAAC;QAC7B,OAAO,GAAG,iBAAiB,CAAC,OAAO,IAAI,IAAI,oBAAoB,EAAE,CAAC;QAClE,kBAAkB,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QAChD,cAAc,GAAG,iBAAiB,CAAC,MAAM,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,oBAAoB,EAAE,CAAC;IACvC,CAAC;IAED,OAAO,KAAK,EAAE,GAAmB,EAAE,IAAiC,EAAyB,EAAE;QAC7F,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAElC,yFAAyF;QACzF,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;YAC9B,MAAM,IAAI,oBAAoB,CAC5B,sEAAsE,CACvE,CAAC;QACJ,CAAC;QAED,iDAAiD;QACjD,IAAI,gBAAgB,GAAY,kBAAkB,CAAC;QACnD,IAAI,OAAO,kBAAkB,KAAK,UAAU,EAAE,CAAC;YAC7C,gBAAgB,GAAG,MAAO,kBAAkD,CAAC,GAAG,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAC3E,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,cAA8C;SACvD,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,IAAI,cAAc,CACtB,QAAQ,CAAC,MAAM,IAAI,gDAAgD,MAAM,IAAI,CAC9E,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,MAAM,IAAI,EAAE,CAAiB,CAAC;IACxC,CAAC,CAAC;AACJ,CAAC"}
|