@owlmeans/auth-common 0.1.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 +318 -0
- package/build/consts.d.ts +9 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +9 -0
- package/build/consts.js.map +1 -0
- package/build/guards/basic-ed25519/consts.d.ts +6 -0
- package/build/guards/basic-ed25519/consts.d.ts.map +1 -0
- package/build/guards/basic-ed25519/consts.js +7 -0
- package/build/guards/basic-ed25519/consts.js.map +1 -0
- package/build/guards/basic-ed25519/index.d.ts +4 -0
- package/build/guards/basic-ed25519/index.d.ts.map +1 -0
- package/build/guards/basic-ed25519/index.js +3 -0
- package/build/guards/basic-ed25519/index.js.map +1 -0
- package/build/guards/basic-ed25519/service.d.ts +8 -0
- package/build/guards/basic-ed25519/service.d.ts.map +1 -0
- package/build/guards/basic-ed25519/service.js +110 -0
- package/build/guards/basic-ed25519/service.js.map +1 -0
- package/build/guards/basic-ed25519/types.d.ts +7 -0
- package/build/guards/basic-ed25519/types.d.ts.map +1 -0
- package/build/guards/basic-ed25519/types.js +2 -0
- package/build/guards/basic-ed25519/types.js.map +1 -0
- package/build/guards/index.d.ts +2 -0
- package/build/guards/index.d.ts.map +1 -0
- package/build/guards/index.js +2 -0
- package/build/guards/index.js.map +1 -0
- package/build/index.d.ts +6 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +5 -0
- package/build/index.js.map +1 -0
- package/build/middleware.d.ts +3 -0
- package/build/middleware.d.ts.map +1 -0
- package/build/middleware.js +39 -0
- package/build/middleware.js.map +1 -0
- package/build/modules.d.ts +2 -0
- package/build/modules.d.ts.map +1 -0
- package/build/modules.js +32 -0
- package/build/modules.js.map +1 -0
- package/build/types.d.ts +28 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/header.d.ts +3 -0
- package/build/utils/header.d.ts.map +1 -0
- package/build/utils/header.js +16 -0
- package/build/utils/header.js.map +1 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +3 -0
- package/build/utils/index.js.map +1 -0
- package/build/utils/trusted.d.ts +7 -0
- package/build/utils/trusted.d.ts.map +1 -0
- package/build/utils/trusted.js +11 -0
- package/build/utils/trusted.js.map +1 -0
- package/build/utils/types.d.ts +6 -0
- package/build/utils/types.d.ts.map +1 -0
- package/build/utils/types.js +2 -0
- package/build/utils/types.js.map +1 -0
- package/package.json +49 -0
- package/src/consts.ts +16 -0
- package/src/guards/basic-ed25519/consts.ts +10 -0
- package/src/guards/basic-ed25519/index.ts +4 -0
- package/src/guards/basic-ed25519/service.ts +142 -0
- package/src/guards/basic-ed25519/types.ts +9 -0
- package/src/guards/index.ts +2 -0
- package/src/index.ts +6 -0
- package/src/middleware.ts +50 -0
- package/src/modules.ts +40 -0
- package/src/types.ts +38 -0
- package/src/utils/header.ts +24 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/trusted.ts +17 -0
- package/src/utils/types.ts +6 -0
- package/tsconfig.json +15 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG5C,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,IAAI,EAAE,cAAc,CAAC,OAAO;IAC5B,KAAK,EAAE,eAAe,CAAC,OAAO;IAC9B,KAAK,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;QACrB,OAAO,CAAC,OAAO,EAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACzC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;gBACvE,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;gBACjC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,IAAI,MAAM,CAAC,+BAA+B,KAAK,IAAI,EAAE,CAAC;wBACpD,OAAM;oBACR,CAAC;oBACD,MAAM,CAAC,+BAA+B,GAAG,IAAI,CAAA;oBAC7C,sDAAsD;oBACtD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;oBACxB,MAAM,CAAC,IAAI,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;wBAC/B,+EAA+E;wBAC/E,sCAAsC;wBACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAC3C,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAe,KAAK,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CACjE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,CAAA;wBAC5C,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;4BAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;4BACtB,MAAM,IAAI,GAA6B,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;4BACjG,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAuC,CAAA;4BAC1E,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,IAAI,EAAE,CAAC;gCACjC,OAAO,CAAC,WAAW,CAAC,GAAG,KAAK,CAAA;gCAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;gCACtB,GAAG,GAAG,IAAkB,CAAA;4BAC1B,CAAC;wBACH,CAAC;wBAED,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;oBACvB,CAAC,CAAA;gBAEH,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,OAAO,2CAuBnB,CAAA"}
|
package/build/modules.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AUTHEN, AUTHEN_AUTHEN, AUTHEN_INIT, AUTHEN_RELY, AllowanceRequestSchema, AuthCredentialsSchema, AuthTokenSchema, CAUTHEN, CAUTHEN_AUTHEN, CAUTHEN_AUTHEN_DEFAULT, CAUTHEN_AUTHEN_TYPED, DISPATCHER, DISPATCHER_AUTHEN, OptionalAuthTokenSchema, CAUTHEN_FLOW_ENTER } from '@owlmeans/auth';
|
|
2
|
+
// import { AppType } from '@owlmeans/context'
|
|
3
|
+
import { body, filter, module, query } from '@owlmeans/module';
|
|
4
|
+
import { route, RouteMethod, frontend, backend, socket } from '@owlmeans/route';
|
|
5
|
+
import { DISPATCHER_PATH } from './consts.js';
|
|
6
|
+
export const modules = [
|
|
7
|
+
module(route(AUTHEN, '/authentication', backend())),
|
|
8
|
+
module(route(AUTHEN_INIT, '/init', backend(AUTHEN, RouteMethod.POST)), filter(body(AllowanceRequestSchema))),
|
|
9
|
+
module(route(AUTHEN_AUTHEN, '/authenticate', backend(AUTHEN, RouteMethod.POST)), filter(body(AuthCredentialsSchema))),
|
|
10
|
+
module(route(AUTHEN_RELY, '/rely', socket(AUTHEN)), filter(query(OptionalAuthTokenSchema))),
|
|
11
|
+
module(route(CAUTHEN, '/authentication', frontend())),
|
|
12
|
+
module(route(CAUTHEN_AUTHEN, '/login', frontend(CAUTHEN))),
|
|
13
|
+
module(route(CAUTHEN_AUTHEN_DEFAULT, '/', frontend(CAUTHEN_AUTHEN, true))),
|
|
14
|
+
module(route(CAUTHEN_AUTHEN_TYPED, '/:type', frontend(CAUTHEN_AUTHEN))),
|
|
15
|
+
// This is a helper route that is used by service providers to redirect to an external authentication service.
|
|
16
|
+
module(route(CAUTHEN_FLOW_ENTER, '/', frontend())),
|
|
17
|
+
// This is a helper route that is useb by service providres to process authentication provisioning via redirect.
|
|
18
|
+
// Also it can be default starting point to be redirected to an external identity provider.
|
|
19
|
+
module(route(DISPATCHER, DISPATCHER_PATH, frontend({ service: DISPATCHER })),
|
|
20
|
+
// This module is sticky - it means it's always attach to client router.
|
|
21
|
+
// It's required here cause every web app needs dispatcher route to authorize
|
|
22
|
+
// rediected users.
|
|
23
|
+
filter(query(AuthTokenSchema), { sticky: true })),
|
|
24
|
+
// This is a helper route that representes a API endpoint of service provider that wants to authenticate
|
|
25
|
+
// a user with OwlMeans server-auth library.
|
|
26
|
+
module(route(DISPATCHER_AUTHEN, '/authenticate', backend(null, RouteMethod.POST)), filter(body(AuthTokenSchema))),
|
|
27
|
+
];
|
|
28
|
+
// const skipModules = [DISPATCHER]
|
|
29
|
+
// export const authBackendModules = modules.filter(
|
|
30
|
+
// module => !skipModules.includes(module.alias) && module.route.route.type === AppType.Backend
|
|
31
|
+
// ).map(module => module.alias)
|
|
32
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,sBAAsB,EAAE,qBAAqB,EAC9F,eAAe,EAAE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,UAAU,EAClG,iBAAiB,EAAE,uBAAuB,EAAE,kBAAkB,EAC/D,MAAM,gBAAgB,CAAA;AACvB,8CAA8C;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC5G,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACrH,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC3F,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IACvE,8GAA8G;IAC9G,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD,gHAAgH;IAChH,2FAA2F;IAC3F,MAAM,CACJ,KAAK,CAAC,UAAU,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACrE,wEAAwE;IACxE,6EAA6E;IAC7E,mBAAmB;IACnB,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CACjD;IACD,yGAAyG;IACzG,4CAA4C;IAC5C,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,eAAe,EAAE,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;CAClH,CAAA;AAED,mCAAmC;AACnC,oDAAoD;AACpD,iGAAiG;AACjG,gCAAgC"}
|
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Auth, AuthToken, PermissionSet, Profile } from '@owlmeans/auth';
|
|
2
|
+
import type { ConfigRecord, InitializedService } from '@owlmeans/context';
|
|
3
|
+
import type { AbstractRequest, GuardService } from '@owlmeans/module';
|
|
4
|
+
import type { Resource, ResourceRecord } from '@owlmeans/resource';
|
|
5
|
+
export interface AuthRequest extends AbstractRequest {
|
|
6
|
+
query: AuthToken;
|
|
7
|
+
}
|
|
8
|
+
export interface AuthUIParams {
|
|
9
|
+
type?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AuthService extends GuardService {
|
|
12
|
+
auth?: Auth;
|
|
13
|
+
/**
|
|
14
|
+
* @throws {AuthenFailed}
|
|
15
|
+
*/
|
|
16
|
+
authenticate: (token: AuthToken) => Promise<void>;
|
|
17
|
+
update: (token: string | undefined) => Promise<void>;
|
|
18
|
+
user: () => Auth;
|
|
19
|
+
store: <T extends ResourceRecord = ResourceRecord>() => Resource<T>;
|
|
20
|
+
}
|
|
21
|
+
export interface AuthorizationService extends InitializedService {
|
|
22
|
+
isAllowed: (permissions: string | string[] | PermissionSet | PermissionSet[], token?: string | AuthToken | null, thr?: boolean) => Promise<boolean>;
|
|
23
|
+
update: (token?: string | AuthToken, thr?: boolean) => Promise<AuthToken | null>;
|
|
24
|
+
}
|
|
25
|
+
export interface TrustedRecord extends ConfigRecord, Partial<Omit<Profile, "permissions" | "attributes">> {
|
|
26
|
+
id: string;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAElE,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,KAAK,EAAE,SAAS,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,WAAY,SAAQ,YAAY;IAC/C,IAAI,CAAC,EAAE,IAAI,CAAA;IACX;;OAEG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,IAAI,EAAE,MAAM,IAAI,CAAA;IAEhB,KAAK,EAAE,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAA;CACpE;AAED,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAC9D,SAAS,EAAE,CACT,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,aAAa,GAAG,aAAa,EAAE,EAChE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACjC,GAAG,CAAC,EAAE,OAAO,KACV,OAAO,CAAC,OAAO,CAAC,CAAA;IAErB,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;CACjF;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAAC,CAAC;IACvG,EAAE,EAAE,MAAM,CAAA;CACX"}
|
package/build/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/utils/header.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEvD,eAAO,MAAM,gBAAgB,QACtB,OAAO,CAAC,eAAe,CAAC,SACvB,MAAM,GAAG,IAAI,cACR,OAAO,KACjB,MAAM,GAAG,IAgBX,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AUTH_HEADER, AuthroizationType } from '@owlmeans/auth';
|
|
2
|
+
export const extractAuthToken = (req, type = AuthroizationType.Ed25519BasicToken, onlyValue = true) => {
|
|
3
|
+
let authorization = req.headers?.[AUTH_HEADER];
|
|
4
|
+
authorization = Array.isArray(authorization) ? authorization[0] : authorization;
|
|
5
|
+
if (authorization == null) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const [prefix, ...rest] = authorization.split(' ');
|
|
9
|
+
if (type == null) {
|
|
10
|
+
return onlyValue ? rest.join(' ') : authorization;
|
|
11
|
+
}
|
|
12
|
+
return prefix === type.toUpperCase() ?
|
|
13
|
+
onlyValue ? rest.join(' ') : authorization
|
|
14
|
+
: null;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/utils/header.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAG/D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,GAA6B,EAC7B,OAAsB,iBAAiB,CAAC,iBAAiB,EACzD,YAAqB,IAAI,EACV,EAAE;IACjB,IAAI,aAAa,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAA;IAC9C,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAA;IAE/E,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClD,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAA;IACnD,CAAC;IAED,OAAO,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa;QAC1C,CAAC,CAAC,IAAI,CAAA;AACV,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Context, Config } from './types.js';
|
|
2
|
+
import type { TrustedRecord } from '../types.js';
|
|
3
|
+
export declare const trust: <C extends Config, T extends Context<C>>(context: T, resource: string, userName: string, field?: string) => Promise<{
|
|
4
|
+
user: TrustedRecord;
|
|
5
|
+
key: import("@owlmeans/basic-keys").KeyPairModel;
|
|
6
|
+
}>;
|
|
7
|
+
//# sourceMappingURL=trusted.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted.d.ts","sourceRoot":"","sources":["../../src/utils/trusted.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,eAAO,MAAM,KAAK,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,MAAM,YAAY,MAAM,UAAS,MAAM;;;EAUhI,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { fromPubKey, makeKeyPairModel } from '@owlmeans/basic-keys';
|
|
2
|
+
export const trust = async (context, resource, userName, field = 'name') => {
|
|
3
|
+
const trustedUser = await context.resource(resource).load(userName, field);
|
|
4
|
+
if (trustedUser == null) {
|
|
5
|
+
throw new SyntaxError(`Auth service trusted entity is not provided: ${userName}`);
|
|
6
|
+
}
|
|
7
|
+
// @TODO credential can really be undefined - we need to process it properly
|
|
8
|
+
const keyPair = trustedUser.secret != null ? makeKeyPairModel(trustedUser.secret) : fromPubKey(trustedUser.credential);
|
|
9
|
+
return { user: trustedUser, key: keyPair };
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=trusted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted.js","sourceRoot":"","sources":["../../src/utils/trusted.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEnE,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAA0C,OAAU,EAAE,QAAgB,EAAE,QAAgB,EAAE,QAAgB,MAAM,EAAE,EAAE;IAC5I,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,QAAQ,CAA0B,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IACnG,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,WAAW,CAAC,gDAAgD,QAAQ,EAAE,CAAC,CAAA;IACnF,CAAC;IAED,4EAA4E;IAC5E,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,UAAW,CAAC,CAAA;IAEvH,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA;AAC5C,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAElE,MAAM,WAAW,MAAO,SAAQ,WAAW;CAAG;AAE9C,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@owlmeans/auth-common",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc -b",
|
|
7
|
+
"dev": "sleep 30 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
|
|
8
|
+
"watch": "tsc -b -w --preserveWatchOutput --pretty"
|
|
9
|
+
},
|
|
10
|
+
"main": "build/index.js",
|
|
11
|
+
"module": "build/index.js",
|
|
12
|
+
"types": "build/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./build/index.js",
|
|
16
|
+
"require": "./build/index.js",
|
|
17
|
+
"default": "./build/index.js",
|
|
18
|
+
"module": "./build/index.js",
|
|
19
|
+
"types": "./build/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./utils": {
|
|
22
|
+
"import": "./build/utils/index.js",
|
|
23
|
+
"require": "./build/utils/index.js",
|
|
24
|
+
"default": "./build/utils/index.js",
|
|
25
|
+
"module": "./build/utils/index.js",
|
|
26
|
+
"types": "./build/utils/index.d.ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@owlmeans/auth": "^0.1.0",
|
|
31
|
+
"@owlmeans/auth-common": "^0.1.0",
|
|
32
|
+
"@owlmeans/basic-ids": "^0.1.0",
|
|
33
|
+
"@owlmeans/basic-keys": "^0.1.0",
|
|
34
|
+
"@owlmeans/client-module": "^0.1.0",
|
|
35
|
+
"@owlmeans/context": "^0.1.0",
|
|
36
|
+
"@owlmeans/module": "^0.1.0",
|
|
37
|
+
"@owlmeans/resource": "^0.1.0",
|
|
38
|
+
"@owlmeans/route": "^0.1.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"nodemon": "^3.1.7",
|
|
42
|
+
"npm-check": "^6.0.1",
|
|
43
|
+
"typescript": "^5.6.3"
|
|
44
|
+
},
|
|
45
|
+
"private": false,
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/consts.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const RELY_PIN_PERFIX = 'rely-pin:'
|
|
2
|
+
|
|
3
|
+
export const RELY_TOKEN_PREFIX = 'rely-token:'
|
|
4
|
+
|
|
5
|
+
export const RELY_CALL_TIMEOUT = 120
|
|
6
|
+
|
|
7
|
+
export const RELY_ACTION_TIMEOUT = 600
|
|
8
|
+
|
|
9
|
+
export const DISPATCHER_PATH = '/dispatcher'
|
|
10
|
+
|
|
11
|
+
export const DEF_AUTH_SRV = 'auth'
|
|
12
|
+
|
|
13
|
+
export const DEFAULT_GUARD = DEF_AUTH_SRV
|
|
14
|
+
|
|
15
|
+
export const TOKEN_UPDATE = 'auth-token-refresh'
|
|
16
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AuthroizationType } from '@owlmeans/auth'
|
|
2
|
+
|
|
3
|
+
export const GUARD_ED25519 = `guard:${AuthroizationType.Ed25519BasicSignature}`
|
|
4
|
+
|
|
5
|
+
export const BED255_TIME_HEADER = 'X-Auth-Time'
|
|
6
|
+
export const BED255_NONCE_HEADER = 'X-Auth-Nonce'
|
|
7
|
+
|
|
8
|
+
export const BED255_SIG_TTL = 60 * 1000
|
|
9
|
+
|
|
10
|
+
export const BED255_CASHE_RESOURCE = 'basic-ed25519-nonce-cache'
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createService } from '@owlmeans/context'
|
|
2
|
+
import type { AbstractRequest, AbstractResponse } from '@owlmeans/module'
|
|
3
|
+
import { assertContext } from '@owlmeans/context'
|
|
4
|
+
import {
|
|
5
|
+
BED255_NONCE_HEADER, BED255_TIME_HEADER, BED255_CASHE_RESOURCE, GUARD_ED25519,
|
|
6
|
+
BED255_SIG_TTL
|
|
7
|
+
} from './consts.js'
|
|
8
|
+
import { trust } from '../../utils/trusted.js'
|
|
9
|
+
import type { Config, Context } from '../../utils/types.js'
|
|
10
|
+
import type { BasicEd25519Guard, BasicEd25519GuardOptions } from './types.js'
|
|
11
|
+
import { AuthenPayloadError, AuthroizationType, AuthRole } from '@owlmeans/auth'
|
|
12
|
+
import type { Auth } from '@owlmeans/auth'
|
|
13
|
+
import { createIdOfLength } from '@owlmeans/basic-ids'
|
|
14
|
+
import type { Resource, ResourceRecord } from '@owlmeans/resource'
|
|
15
|
+
import { extractAuthToken } from '@owlmeans/auth-common/utils'
|
|
16
|
+
|
|
17
|
+
const timeKey = BED255_TIME_HEADER.toLocaleLowerCase()
|
|
18
|
+
const nonceKey = BED255_NONCE_HEADER.toLocaleLowerCase()
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Proper configuration:
|
|
22
|
+
* - One needs to specify opts.cache as a redis resource that stores nonces for a while to
|
|
23
|
+
* avoid requests duplication.
|
|
24
|
+
*/
|
|
25
|
+
export const makeBasicEd25519Guard = (resource: string, opts?: BasicEd25519GuardOptions): BasicEd25519Guard => {
|
|
26
|
+
|
|
27
|
+
const cache = (context: Context) => context.hasResource(opts?.cache ?? BED255_CASHE_RESOURCE)
|
|
28
|
+
? context.resource<Resource<ResourceRecord>>(opts?.cache ?? BED255_CASHE_RESOURCE)
|
|
29
|
+
: null
|
|
30
|
+
|
|
31
|
+
const guard: BasicEd25519Guard = createService<BasicEd25519Guard>(GUARD_ED25519, {
|
|
32
|
+
authenticated: async req => {
|
|
33
|
+
const context = assertContext<Config, Context>(guard.ctx)
|
|
34
|
+
const truested = await trust(context, resource, context.cfg.alias ?? context.cfg.service)
|
|
35
|
+
|
|
36
|
+
// req?.body != null
|
|
37
|
+
if (req != null && truested.user.secret != null) {
|
|
38
|
+
if (req.headers == null) {
|
|
39
|
+
req.headers = {}
|
|
40
|
+
}
|
|
41
|
+
req.headers[timeKey] = new Date().toISOString()
|
|
42
|
+
req.headers[nonceKey] = createIdOfLength(16)
|
|
43
|
+
|
|
44
|
+
const payload = {
|
|
45
|
+
body: req.body ?? {},
|
|
46
|
+
headers: { [timeKey]: req.headers[timeKey], [nonceKey]: req.headers[nonceKey] }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const token = [
|
|
50
|
+
AuthroizationType.Ed25519BasicSignature.toUpperCase()
|
|
51
|
+
, ['Credential', truested.user.id]
|
|
52
|
+
, ['Signature', await truested.key.sign(payload)]
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
return token.map(
|
|
56
|
+
item => Array.isArray(item) ? item.join('=') : item
|
|
57
|
+
).join(' ')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return null
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
match: async req =>
|
|
64
|
+
extractAuthToken(req, AuthroizationType.Ed25519BasicSignature) != null,
|
|
65
|
+
|
|
66
|
+
handle: async <T>(req: AbstractRequest, res: AbstractResponse<Auth>) => {
|
|
67
|
+
const context = assertContext<Config, Context>(guard.ctx)
|
|
68
|
+
const authorization = extractAuthToken(req, AuthroizationType.Ed25519BasicSignature)
|
|
69
|
+
if (authorization == null) {
|
|
70
|
+
return false as T
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const signature = authorization.split(' ', 3).reduce((result, pair) => {
|
|
74
|
+
if (!pair.includes('=')) {
|
|
75
|
+
return result
|
|
76
|
+
}
|
|
77
|
+
const [key, value] = pair.split('=', 2)
|
|
78
|
+
return { ...result, [key.toLowerCase()]: value }
|
|
79
|
+
}, {} as { credential: string, signature: string })
|
|
80
|
+
|
|
81
|
+
const trusted = await trust(context, resource, signature.credential, "id")
|
|
82
|
+
if (trusted.user.credential == null) {
|
|
83
|
+
return false as T
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const payload = {
|
|
87
|
+
body: req.body ?? {},
|
|
88
|
+
headers: { [timeKey]: req.headers[timeKey], [nonceKey]: req.headers[nonceKey] }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!await trusted.key.verify(payload, signature.signature)) {
|
|
92
|
+
return false as T
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (typeof req.headers[timeKey] !== 'string') {
|
|
96
|
+
throw new AuthenPayloadError('timestamp')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const createdAt = new Date(req.headers[timeKey])
|
|
100
|
+
|
|
101
|
+
if (createdAt.getTime() + BED255_SIG_TTL < Date.now()) {
|
|
102
|
+
throw new AuthenPayloadError('expired')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const nonce = req.headers[nonceKey]
|
|
106
|
+
if (typeof nonce !== 'string') {
|
|
107
|
+
throw new AuthenPayloadError('nonce')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const tried = cache(context)
|
|
112
|
+
if (tried != null) {
|
|
113
|
+
await tried.create({ id: nonce }, { ttl: BED255_SIG_TTL / 1000 })
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
throw new AuthenPayloadError('nonce')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
res.resolve({
|
|
120
|
+
token: authorization,
|
|
121
|
+
userId: trusted.user.id,
|
|
122
|
+
profileId: trusted.user.id,
|
|
123
|
+
entityId: trusted.user.entityId,
|
|
124
|
+
scopes: trusted.user.name != null ? [trusted.user.name] : [],
|
|
125
|
+
type: AuthroizationType.Ed25519BasicSignature,
|
|
126
|
+
source: context.cfg.service,
|
|
127
|
+
/**
|
|
128
|
+
* @TODO actually it's not always the case (that the the role is the service)
|
|
129
|
+
*/
|
|
130
|
+
role: AuthRole.Service,
|
|
131
|
+
isUser: false,
|
|
132
|
+
createdAt: new Date()
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return true as T
|
|
136
|
+
}
|
|
137
|
+
}, guard => async () => {
|
|
138
|
+
guard.initialized = true
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
return guard
|
|
142
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Middleware } from '@owlmeans/context'
|
|
2
|
+
import { MiddlewareType, MiddlewareStage, AppType } from '@owlmeans/context'
|
|
3
|
+
import { provideRequest } from '@owlmeans/client-module'
|
|
4
|
+
import type { ClientModule } from '@owlmeans/client-module'
|
|
5
|
+
import { AUTH_HEADER } from '@owlmeans/auth'
|
|
6
|
+
import type { AbstractRequest, GuardService } from '@owlmeans/module'
|
|
7
|
+
|
|
8
|
+
export const authMiddleware: Middleware = {
|
|
9
|
+
type: MiddlewareType.Context,
|
|
10
|
+
stage: MiddlewareStage.Loading,
|
|
11
|
+
apply: async context => {
|
|
12
|
+
context.modules<Perked>().forEach(module => {
|
|
13
|
+
if (module.route.route.type === AppType.Backend && module.call != null) {
|
|
14
|
+
const guards = module.getGuards()
|
|
15
|
+
if (guards.length > 0) {
|
|
16
|
+
if (module._auth_common_middleware_applied === true) {
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
module._auth_common_middleware_applied = true
|
|
20
|
+
// const auth = context.service<GuardService>(service)
|
|
21
|
+
const call = module.call
|
|
22
|
+
module.call = async (req, res) => {
|
|
23
|
+
// @TODO Actually we may use multiple authentication headers with the same name
|
|
24
|
+
// As I learnt its not always the case
|
|
25
|
+
const [token] = (await Promise.all(guards.map(
|
|
26
|
+
guard => context.service<GuardService>(guard).authenticated(req)
|
|
27
|
+
))).filter(token => token != null).reverse()
|
|
28
|
+
if (token != null) {
|
|
29
|
+
await module.resolve()
|
|
30
|
+
const _req: Partial<AbstractRequest> = req ?? provideRequest(module.getAlias(), module.getPath())
|
|
31
|
+
const headers = (_req.headers ?? {}) as Record<string, string | undefined>
|
|
32
|
+
if (headers[AUTH_HEADER] == null) {
|
|
33
|
+
headers[AUTH_HEADER] = token
|
|
34
|
+
_req.headers = headers
|
|
35
|
+
req = _req as typeof req
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return call(req, res)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface Perked extends ClientModule<unknown> {
|
|
49
|
+
_auth_common_middleware_applied?: boolean
|
|
50
|
+
}
|
package/src/modules.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
AUTHEN, AUTHEN_AUTHEN, AUTHEN_INIT, AUTHEN_RELY, AllowanceRequestSchema, AuthCredentialsSchema,
|
|
4
|
+
AuthTokenSchema, CAUTHEN, CAUTHEN_AUTHEN, CAUTHEN_AUTHEN_DEFAULT, CAUTHEN_AUTHEN_TYPED, DISPATCHER,
|
|
5
|
+
DISPATCHER_AUTHEN, OptionalAuthTokenSchema, CAUTHEN_FLOW_ENTER
|
|
6
|
+
} from '@owlmeans/auth'
|
|
7
|
+
// import { AppType } from '@owlmeans/context'
|
|
8
|
+
import { body, filter, module, query } from '@owlmeans/module'
|
|
9
|
+
import { route, RouteMethod, frontend, backend, socket } from '@owlmeans/route'
|
|
10
|
+
import { DISPATCHER_PATH } from './consts.js'
|
|
11
|
+
|
|
12
|
+
export const modules = [
|
|
13
|
+
module(route(AUTHEN, '/authentication', backend())),
|
|
14
|
+
module(route(AUTHEN_INIT, '/init', backend(AUTHEN, RouteMethod.POST)), filter(body(AllowanceRequestSchema))),
|
|
15
|
+
module(route(AUTHEN_AUTHEN, '/authenticate', backend(AUTHEN, RouteMethod.POST)), filter(body(AuthCredentialsSchema))),
|
|
16
|
+
module(route(AUTHEN_RELY, '/rely', socket(AUTHEN)), filter(query(OptionalAuthTokenSchema))),
|
|
17
|
+
module(route(CAUTHEN, '/authentication', frontend())),
|
|
18
|
+
module(route(CAUTHEN_AUTHEN, '/login', frontend(CAUTHEN))),
|
|
19
|
+
module(route(CAUTHEN_AUTHEN_DEFAULT, '/', frontend(CAUTHEN_AUTHEN, true))),
|
|
20
|
+
module(route(CAUTHEN_AUTHEN_TYPED, '/:type', frontend(CAUTHEN_AUTHEN))),
|
|
21
|
+
// This is a helper route that is used by service providers to redirect to an external authentication service.
|
|
22
|
+
module(route(CAUTHEN_FLOW_ENTER, '/', frontend())),
|
|
23
|
+
// This is a helper route that is useb by service providres to process authentication provisioning via redirect.
|
|
24
|
+
// Also it can be default starting point to be redirected to an external identity provider.
|
|
25
|
+
module(
|
|
26
|
+
route(DISPATCHER, DISPATCHER_PATH, frontend({ service: DISPATCHER })),
|
|
27
|
+
// This module is sticky - it means it's always attach to client router.
|
|
28
|
+
// It's required here cause every web app needs dispatcher route to authorize
|
|
29
|
+
// rediected users.
|
|
30
|
+
filter(query(AuthTokenSchema), { sticky: true })
|
|
31
|
+
),
|
|
32
|
+
// This is a helper route that representes a API endpoint of service provider that wants to authenticate
|
|
33
|
+
// a user with OwlMeans server-auth library.
|
|
34
|
+
module(route(DISPATCHER_AUTHEN, '/authenticate', backend(null, RouteMethod.POST)), filter(body(AuthTokenSchema))),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
// const skipModules = [DISPATCHER]
|
|
38
|
+
// export const authBackendModules = modules.filter(
|
|
39
|
+
// module => !skipModules.includes(module.alias) && module.route.route.type === AppType.Backend
|
|
40
|
+
// ).map(module => module.alias)
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Auth, AuthToken, PermissionSet, Profile } from '@owlmeans/auth'
|
|
2
|
+
import type { ConfigRecord, InitializedService } from '@owlmeans/context'
|
|
3
|
+
import type { AbstractRequest, GuardService } from '@owlmeans/module'
|
|
4
|
+
import type { Resource, ResourceRecord } from '@owlmeans/resource'
|
|
5
|
+
|
|
6
|
+
export interface AuthRequest extends AbstractRequest {
|
|
7
|
+
query: AuthToken
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface AuthUIParams {
|
|
11
|
+
type?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AuthService extends GuardService {
|
|
15
|
+
auth?: Auth
|
|
16
|
+
/**
|
|
17
|
+
* @throws {AuthenFailed}
|
|
18
|
+
*/
|
|
19
|
+
authenticate: (token: AuthToken) => Promise<void>
|
|
20
|
+
update: (token: string | undefined) => Promise<void>
|
|
21
|
+
user: () => Auth
|
|
22
|
+
|
|
23
|
+
store: <T extends ResourceRecord = ResourceRecord>() => Resource<T>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AuthorizationService extends InitializedService {
|
|
27
|
+
isAllowed: (
|
|
28
|
+
permissions: string | string[] | PermissionSet | PermissionSet[],
|
|
29
|
+
token?: string | AuthToken | null,
|
|
30
|
+
thr?: boolean
|
|
31
|
+
) => Promise<boolean>
|
|
32
|
+
|
|
33
|
+
update: (token?: string | AuthToken, thr?: boolean) => Promise<AuthToken | null>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TrustedRecord extends ConfigRecord, Partial<Omit<Profile, "permissions" | "attributes">> {
|
|
37
|
+
id: string
|
|
38
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AUTH_HEADER, AuthroizationType } from '@owlmeans/auth'
|
|
2
|
+
import type { AbstractRequest } from '@owlmeans/module'
|
|
3
|
+
|
|
4
|
+
export const extractAuthToken = (
|
|
5
|
+
req: Partial<AbstractRequest>,
|
|
6
|
+
type: string | null = AuthroizationType.Ed25519BasicToken,
|
|
7
|
+
onlyValue: boolean = true
|
|
8
|
+
): string | null => {
|
|
9
|
+
let authorization = req.headers?.[AUTH_HEADER]
|
|
10
|
+
authorization = Array.isArray(authorization) ? authorization[0] : authorization
|
|
11
|
+
|
|
12
|
+
if (authorization == null) {
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const [prefix, ...rest] = authorization.split(' ')
|
|
17
|
+
if (type == null) {
|
|
18
|
+
return onlyValue ? rest.join(' ') : authorization
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return prefix === type.toUpperCase() ?
|
|
22
|
+
onlyValue ? rest.join(' ') : authorization
|
|
23
|
+
: null
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
import type { Context, Config } from './types.js'
|
|
3
|
+
import type { TrustedRecord } from '../types.js'
|
|
4
|
+
import type { Resource } from '@owlmeans/resource'
|
|
5
|
+
import { fromPubKey, makeKeyPairModel } from '@owlmeans/basic-keys'
|
|
6
|
+
|
|
7
|
+
export const trust = async <C extends Config, T extends Context<C>>(context: T, resource: string, userName: string, field: string = 'name') => {
|
|
8
|
+
const trustedUser = await context.resource<Resource<TrustedRecord>>(resource).load(userName, field)
|
|
9
|
+
if (trustedUser == null) {
|
|
10
|
+
throw new SyntaxError(`Auth service trusted entity is not provided: ${userName}`)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// @TODO credential can really be undefined - we need to process it properly
|
|
14
|
+
const keyPair = trustedUser.secret != null ? makeKeyPairModel(trustedUser.secret) : fromPubKey(trustedUser.credential!)
|
|
15
|
+
|
|
16
|
+
return { user: trustedUser, key: keyPair }
|
|
17
|
+
}
|