@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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +318 -0
  3. package/build/consts.d.ts +9 -0
  4. package/build/consts.d.ts.map +1 -0
  5. package/build/consts.js +9 -0
  6. package/build/consts.js.map +1 -0
  7. package/build/guards/basic-ed25519/consts.d.ts +6 -0
  8. package/build/guards/basic-ed25519/consts.d.ts.map +1 -0
  9. package/build/guards/basic-ed25519/consts.js +7 -0
  10. package/build/guards/basic-ed25519/consts.js.map +1 -0
  11. package/build/guards/basic-ed25519/index.d.ts +4 -0
  12. package/build/guards/basic-ed25519/index.d.ts.map +1 -0
  13. package/build/guards/basic-ed25519/index.js +3 -0
  14. package/build/guards/basic-ed25519/index.js.map +1 -0
  15. package/build/guards/basic-ed25519/service.d.ts +8 -0
  16. package/build/guards/basic-ed25519/service.d.ts.map +1 -0
  17. package/build/guards/basic-ed25519/service.js +110 -0
  18. package/build/guards/basic-ed25519/service.js.map +1 -0
  19. package/build/guards/basic-ed25519/types.d.ts +7 -0
  20. package/build/guards/basic-ed25519/types.d.ts.map +1 -0
  21. package/build/guards/basic-ed25519/types.js +2 -0
  22. package/build/guards/basic-ed25519/types.js.map +1 -0
  23. package/build/guards/index.d.ts +2 -0
  24. package/build/guards/index.d.ts.map +1 -0
  25. package/build/guards/index.js +2 -0
  26. package/build/guards/index.js.map +1 -0
  27. package/build/index.d.ts +6 -0
  28. package/build/index.d.ts.map +1 -0
  29. package/build/index.js +5 -0
  30. package/build/index.js.map +1 -0
  31. package/build/middleware.d.ts +3 -0
  32. package/build/middleware.d.ts.map +1 -0
  33. package/build/middleware.js +39 -0
  34. package/build/middleware.js.map +1 -0
  35. package/build/modules.d.ts +2 -0
  36. package/build/modules.d.ts.map +1 -0
  37. package/build/modules.js +32 -0
  38. package/build/modules.js.map +1 -0
  39. package/build/types.d.ts +28 -0
  40. package/build/types.d.ts.map +1 -0
  41. package/build/types.js +2 -0
  42. package/build/types.js.map +1 -0
  43. package/build/utils/header.d.ts +3 -0
  44. package/build/utils/header.d.ts.map +1 -0
  45. package/build/utils/header.js +16 -0
  46. package/build/utils/header.js.map +1 -0
  47. package/build/utils/index.d.ts +4 -0
  48. package/build/utils/index.d.ts.map +1 -0
  49. package/build/utils/index.js +3 -0
  50. package/build/utils/index.js.map +1 -0
  51. package/build/utils/trusted.d.ts +7 -0
  52. package/build/utils/trusted.d.ts.map +1 -0
  53. package/build/utils/trusted.js +11 -0
  54. package/build/utils/trusted.js.map +1 -0
  55. package/build/utils/types.d.ts +6 -0
  56. package/build/utils/types.d.ts.map +1 -0
  57. package/build/utils/types.js +2 -0
  58. package/build/utils/types.js.map +1 -0
  59. package/package.json +49 -0
  60. package/src/consts.ts +16 -0
  61. package/src/guards/basic-ed25519/consts.ts +10 -0
  62. package/src/guards/basic-ed25519/index.ts +4 -0
  63. package/src/guards/basic-ed25519/service.ts +142 -0
  64. package/src/guards/basic-ed25519/types.ts +9 -0
  65. package/src/guards/index.ts +2 -0
  66. package/src/index.ts +6 -0
  67. package/src/middleware.ts +50 -0
  68. package/src/modules.ts +40 -0
  69. package/src/types.ts +38 -0
  70. package/src/utils/header.ts +24 -0
  71. package/src/utils/index.ts +4 -0
  72. package/src/utils/trusted.ts +17 -0
  73. package/src/utils/types.ts +6 -0
  74. package/tsconfig.json +15 -0
  75. 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,2 @@
1
+ export declare const modules: import("@owlmeans/module").CommonModule[];
2
+ //# sourceMappingURL=modules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,OAAO,2CAuBnB,CAAA"}
@@ -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"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { AbstractRequest } from '@owlmeans/module';
2
+ export declare const extractAuthToken: (req: Partial<AbstractRequest>, type?: string | null, onlyValue?: boolean) => string | null;
3
+ //# sourceMappingURL=header.d.ts.map
@@ -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,4 @@
1
+ export type * from './types.js';
2
+ export * from './trusted.js';
3
+ export * from './header.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export * from './trusted.js';
2
+ export * from './header.js';
3
+ //# sourceMappingURL=index.js.map
@@ -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,6 @@
1
+ import type { BasicContext, BasicConfig } from '@owlmeans/context';
2
+ export interface Config extends BasicConfig {
3
+ }
4
+ export interface Context<C extends Config = Config> extends BasicContext<C> {
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -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,4 @@
1
+
2
+ export type * from './types.js'
3
+ export * from './consts.js'
4
+ export * from './service.js'
@@ -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
+ }
@@ -0,0 +1,9 @@
1
+ import type { GuardService } from '@owlmeans/module'
2
+
3
+ export interface BasicEd25519Guard extends GuardService {
4
+ }
5
+
6
+ export interface BasicEd25519GuardOptions {
7
+ cache?: string
8
+ }
9
+
@@ -0,0 +1,2 @@
1
+
2
+ export * from './basic-ed25519/index.js'
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type * from './types.js'
2
+
3
+ export * from './modules.js'
4
+ export * from './consts.js'
5
+ export * from './middleware.js'
6
+ export * from './guards/index.js'
@@ -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,4 @@
1
+
2
+ export type * from './types.js'
3
+ export * from './trusted.js'
4
+ export * from './header.js'
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+
2
+ import type { BasicContext, BasicConfig } from '@owlmeans/context'
3
+
4
+ export interface Config extends BasicConfig {}
5
+
6
+ export interface Context<C extends Config = Config> extends BasicContext<C> {}