feathers-ucan 0.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/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # feathers-ucan
2
+
3
+ An extension of jwt authentication in feathersjs to include the added functionality of UCAN `@ucans/ucans` tokens. More specifically, adding capabilities.
4
+
5
+ UCAN tokens are unopinionated in general, and still emerging. There is a lot more that possibly could be done with this concept, we have built only what we have managed to use in my own current scope of project needs with this library. We have tried to leav it as unopinionated as possible.
6
+
7
+
8
+ # UCAN auth-strategy
9
+
10
+ Implementing UCAN auth in place of JWT is done, for example, like this.
11
+
12
+ ```angular2html
13
+ import {AuthService, UcanStrategy} from 'feathers-ucan';
14
+
15
+ export default (app: Application) => {
16
+ const authentication = new AuthService(app);
17
+ authentication.register('jwt', new UcanStrategy());
18
+ authentication.register('local', new LocalAuth());
19
+ authentication.register('google', new GoogleStrategy(app));
20
+ authentication.register('linkedin', new LinkedinStrategy(app));
21
+ const configKey = 'authentication';
22
+
23
+ app.use('authentication', authentication);
24
+ app.configure(expressOauth());
25
+
26
+ app.service('authentication').hooks({
27
+ around: {},
28
+ after: {
29
+ create: [
30
+ ...
31
+ ]
32
+ }
33
+ });
34
+ }
35
+ ```
36
+
37
+ # Implementing via hooks
38
+
39
+ See Ucan documentation for specs of ucan methods such as `verify` as well as types for standard ucan methods. This documentation is only to explain how these functions are used in hooks, and how we've extended them.
40
+
41
+ # Capabilities
42
+
43
+ For ease of use within an application setting, we have provided methods for generating proper capabilities with global application settings for `hierPart` and `scheme`. These can still be overridden easily for special requirements.
44
+
45
+ ### genCapability(capabilityParts, settings)
46
+
47
+ ****************capabilityParts****************: is just `Partial<Capability>` where `Capability` is just the ucan standard Capability type. genCapability generates a full capability using the settings for default `hierPart` and `scheme`.
48
+
49
+ genCapability() returns a standard ucan `Capability`
50
+
51
+ # Authentication hooks
52
+
53
+ ## allUcanAuth(methods, options)(context:HookContext)
54
+
55
+ ### Methods
56
+
57
+ **************methods**************: is an object that includes optional keys for all feathers service methods and the value is an array with 3 possible values:
58
+ `Array<CapabilityParts>`where `CapabilityParts` is the `Partial<Capability>` from the **********************genCapability********************** method, or a simplified `Array<[string, string]>` where the 2 elements of the array are the ucan Capability `namespace` and `segments` sequentially
59
+
60
+ In practice, here’s what methods look like (of course the mix of settings is nonsensical in normal use) that you can pass to the ********************allUcanAuth******************** function along with example capability configurations.
61
+
62
+ ```jsx
63
+ import { anyAuth, noThrow } from '../ucan-auth'
64
+ const methods = {
65
+ create: [['logins', 'WRITE']] //standard "easy" use. All capabilities are required
66
+ patch: [['orgs', 'WRITE'], ['threads', 'READ']] //both would be required in this case unless the "or" option is passed in
67
+ remove: [{ with: { scheme: 'yourScheme', hierPart: 'application/*' }, can: { namespace: 'collection', segments: ['WRITE'] }}]
68
+ get: anyAuth,
69
+ find: noThrow
70
+ }
71
+ ```
72
+
73
+ ************************anyAuth:************************ provides simple naked authentication and does not enforce any ucan capabilities. In other words, it’s standard JWT auth for that method. Pass/fail for a valid token.
74
+
75
+ ******************noThrow:****************** is even looser - because it will not throw an error if the auth fails. It is just useful for having the `login._id` present in the `context.params`
76
+
77
+ Note: the way ucans works, you cannot simply provide a “greatest ability” and have the verify method filter out lesser abilities. In other words, if you have `WRITE` segment, you’d expect that to be valid for a `READ` requirement. However, ucans is less opinionated than that. You need to reduce the ability yourself, or it will not verify even if you have a greater ability. We have greatest ability functions, but currently the `allUcanAuth` method does not use it. Add only the greatest ability you wish to enforce. The client for adding ucans to users does this already, so only custom scenarios should present a problem at this time. In the future, we will always reduce abilities for the greatest ability.
78
+
79
+ ## Options
80
+
81
+ ******************options:****************** is an object that allows additional settings for customizing the auth experience for common exception use cases. The following are the options
82
+
83
+ ```jsx
84
+ declare type UcanAuthOptions = {
85
+ creatorPass?: '*' | Array<string>,
86
+ loginPass?: [Array<string>, Array<string> | '*'],
87
+ or?: Array<string>,
88
+ adminPass?: Array<string>
89
+ }
90
+ ```
91
+
92
+ - **************************creatorPass:************************** allows for a pass if the `login._id` calling the method is the same as the record in question `record.createdBy.login`
93
+ - **********************loginPass:********************** allows for a free pass list of record paths that match the `login._id` calling the method. The first element of the array are the paths such as `[owner.id]` (dot notation for nested paths). In the future we expect to add `$in` functionality that can handle nested arrays as well (the current version will pass an array that includes the correct id, but only a flat array of simple ObjectIds). The second element are the methods you want to allow this on ie: `['patch', 'create']`Use the `*` superuser for allowing all methods to pass.
94
+ - ********or:******** explains to run the `Capability` configuration passed to the ********allUcanAuth methods******** to be run as an or scenario instead of and. This is a significant extension of how ucans otherwise work. It will run multiple verify methods and if any pass, the auth will pass.
95
+ - **********adminPass:********** allow internal call overrides of ucan requirements. This is important for writing functions that internal operations may need to perform like removing a created org if a hook isn’t successful. Calling this requires passing an array of methods as the value of the admin option (`Array<string>`) as well as setting `context.params.admin_pass` to `true` from within the feathers app (no client side overrides). The value of this property is an array of methods to allow `admin_pass` params on.
96
+
97
+ # Example
98
+
99
+ This is a realistic example for allowing anyone to create an `org` in this application, to only allow someone with universal ucan ability to `WRITE` to `orgs` or the ability to `WRITE` on the specific org being patched. It is using the ******or****** option to ensure either of those 2 will suffice
100
+
101
+ you will notice the parts of the `Capability` are indeed partial. Whatever parts are left out are filled in the the **************************genCapability************************** defaults.
102
+
103
+ ```jsx
104
+ import { CapabilityParts, anyAuth, hierPartBase, Capability, allUcanAuth, UcanAuthOptions } from '../ucans'
105
+
106
+ const writer = [['orgs', 'WRITE']] as Array<CapabilityParts>;
107
+ const deleter = [['orgs', '*']] as Array<CapabilityParts>;
108
+
109
+ const ucanArgs = (context:HookContext):UcanAuthOptions => {
110
+ return {
111
+ create: anyAuth,
112
+ patch: [
113
+ ['orgs', 'WRITE'] as [string, string],
114
+ {
115
+ with: {
116
+ hierPart: `${hierPartBase}/${context.id}`
117
+ },
118
+ can: {
119
+ namespace: 'orgs',
120
+ segments: ['WRITE']
121
+ }
122
+ } as Partial<Capability>
123
+ ],
124
+ update: writer,
125
+ remove: deleter
126
+ }
127
+ }
128
+ ```
129
+
130
+ Then the config is used in a before all hook like this
131
+
132
+ ```jsx
133
+ const authenticate = async (context:HookContext):Promise<HookContext> => {
134
+ return await allUcanAuth(ucanArgs(context), {or: ['patch'], admin: ['remove'] }})(context);
135
+ }
136
+
137
+ ...
138
+
139
+ before: {
140
+ all: [
141
+ authenticate,
142
+ ]
143
+ }
144
+ ...
145
+ ```
146
+
147
+ # Ucan for specific database records
148
+
149
+ The challenge of giving someone rights to write to, for example, their own profile - without granting them rights to write to all profiles is easy. However, enforcing that the other way around - where a user with permission for an entire collection should also have permissions for a specific record - poses a problem.
150
+
151
+ Ucan specs don’t allow for anything but an exact match of scheme, hierPart, namespace, and segments - except for a superuser.
152
+
153
+ So we allow for this scenario by checking for each namespace to have a `namespace:id` setup such as `orgs:423klsjsdf3kj13lkj14`.
@@ -0,0 +1,7 @@
1
+ export declare class NotAuthError extends Error {
2
+ constructor(message?: string);
3
+ }
4
+ export type AuthServiceOptions = {
5
+ NotAuthenticated?: any;
6
+ };
7
+ export declare const genAuthService: (ParentClass: any, options?: AuthServiceOptions) => void;
@@ -0,0 +1 @@
1
+ export * from './methods';
@@ -0,0 +1,31 @@
1
+ import { AnyObj } from '../types';
2
+ export type Id = string | object;
3
+ export type CallFindResult<T = AnyObj> = {
4
+ total: number;
5
+ limit: number;
6
+ skip: number;
7
+ data: Array<T>;
8
+ };
9
+ export type AnyParams = Iterable<AnyObj>;
10
+ declare type CoreOpts = {
11
+ skipJoins?: boolean;
12
+ };
13
+ export declare class CoreCall {
14
+ context: any;
15
+ service: string;
16
+ core: AnyObj;
17
+ constructor(service: string, context: any, coreOptions?: CoreOpts);
18
+ get(id: Id, params?: {}): Promise<any>;
19
+ find(params?: {}): Promise<any>;
20
+ create(data: AnyObj, params?: {}): Promise<any>;
21
+ patch(id: Id, data: AnyObj, params?: {}): Promise<any>;
22
+ update(id: Id, data: AnyObj, params?: {}): Promise<any>;
23
+ remove(id: Id, params?: {}): Promise<void>;
24
+ _get(id: Id, params?: {}): Promise<any>;
25
+ _find(params?: {}): Promise<any>;
26
+ _create(data: AnyObj, params?: {}): Promise<any>;
27
+ _patch(id: Id, data: AnyObj, params?: {}): Promise<any>;
28
+ _update(id: Id, data: AnyObj, params?: {}): Promise<any>;
29
+ _remove(id: Id, params?: {}): Promise<void>;
30
+ }
31
+ export {};
@@ -0,0 +1 @@
1
+ export declare const VERSION = "0.0.0";
@@ -0,0 +1,2 @@
1
+ export * from './ucan-auth';
2
+ export * from './update-ucan';
@@ -0,0 +1,53 @@
1
+ import { AnyObj as HookContext } from '../types';
2
+ import { Capability, VerifyOptions } from 'symbol-ucan';
3
+ type AnyAuth = '*';
4
+ export declare const anyAuth: AnyAuth;
5
+ type NoThrow = '$';
6
+ export declare const noThrow: NoThrow;
7
+ export type CapabilityParts = Partial<Capability> | [string, Array<string> | string];
8
+ declare type UcanAuthOptions = {
9
+ creatorPass?: '*' | Array<string>;
10
+ loginPass?: [Array<string>, Array<string> | '*'];
11
+ or?: Array<string>;
12
+ adminPass?: Array<string>;
13
+ };
14
+ type RequiredCapability = {
15
+ capability: Capability;
16
+ rootIssuer: string;
17
+ };
18
+ export type UcanCap = Array<CapabilityParts> | AnyAuth | NoThrow;
19
+ export type UcanAllArgs = {
20
+ all?: UcanCap;
21
+ get?: UcanCap;
22
+ find?: UcanCap;
23
+ create?: UcanCap;
24
+ patch?: UcanCap;
25
+ update?: UcanCap;
26
+ remove?: UcanCap;
27
+ };
28
+ type VerifyOne = {
29
+ ucan: string;
30
+ } & VerifyOptions;
31
+ type Auth = (method: string) => (context: HookContext) => Promise<HookContext>;
32
+ type Config = {
33
+ entity: string;
34
+ service: string;
35
+ defaultScheme: string;
36
+ defaultHierPart: string;
37
+ };
38
+ type VerifyRes = {
39
+ ok: boolean;
40
+ value: Array<any>;
41
+ };
42
+ export declare class UcanAuth {
43
+ authenticate: Auth;
44
+ configuration: Config;
45
+ constructor(authenticate: Auth, configuration: Config);
46
+ noThrowAuth(context: HookContext): Promise<HookContext>;
47
+ bareAuth(context: HookContext): Promise<HookContext>;
48
+ orVerifyLoop(arr: Array<VerifyOne>): Promise<any>;
49
+ verifyAgainstReqs(ucan: string, audience: string, reqs: Array<RequiredCapability>, options?: UcanAuthOptions): (context: HookContext) => Promise<VerifyRes>;
50
+ ucanAuth(requiredCapabilities?: UcanCap, options?: UcanAuthOptions): (context: HookContext) => Promise<any>;
51
+ allUcanAuth(methods: UcanAllArgs, options?: UcanAuthOptions): (context: HookContext) => Promise<any>;
52
+ }
53
+ export {};
@@ -0,0 +1 @@
1
+ export declare const updateUcan: () => (context: any) => Promise<any>;
package/lib/index.cjs ADDED
@@ -0,0 +1 @@
1
+ var e=require("symbol-ucan");function r(){return r=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},r.apply(this,arguments)}function t(e){return t=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},t(e)}function n(e,r){return n=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,r){return e.__proto__=r,e},n(e,r)}function o(e,r,t){return o=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct.bind():function(e,r,t){var o=[null];o.push.apply(o,r);var i=new(Function.bind.apply(e,o));return t&&n(i,t.prototype),i},o.apply(null,arguments)}function i(e){var r="function"==typeof Map?new Map:void 0;return i=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(e))return r.get(e);r.set(e,i)}function i(){return o(e,arguments,t(this).constructor)}return i.prototype=Object.create(e.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),n(i,e)},i(e)}var c=/*#__PURE__*/function(e){var r,t;function o(r){return e.call(this,r)||this}return t=e,(r=o).prototype=Object.create(t.prototype),r.prototype.constructor=r,n(r,t),o}(/*#__PURE__*/i(Error)),u=/*#__PURE__*/function(){function e(e,t,n){var o;this.context=void 0,this.service=void 0,this.core=void 0,this.service=e,this.context=t,this.core=r({},null==(o=t.params)?void 0:o.core,n)}var t=e.prototype;return t.get=function(e,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service).get(e,r({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},t.find=function(e){void 0===e&&(e={});try{var t,n=this;return Promise.resolve(null==(t=n.context.app)?void 0:t.service(n.service).find(r({},e,{core:n.core})))}catch(e){return Promise.reject(e)}},t.create=function(e,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service).create(e,r({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},t.patch=function(e,t,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service).patch(e,t,r({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},t.update=function(e,t,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service).update(e,t,r({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},t.remove=function(e,t){void 0===t&&(t={});try{var n,o=this;return null==(n=o.context.app)||n.service(o.service).remove(e,r({},t,{core:o.core})),Promise.resolve()}catch(e){return Promise.reject(e)}},t._get=function(e,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service)._get(e,r({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},t._find=function(e){void 0===e&&(e={});try{var t,n=this;return Promise.resolve(null==(t=n.context.app)?void 0:t.service(n.service)._find(r({},e,{core:n.core})))}catch(e){return Promise.reject(e)}},t._create=function(e,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service)._create(e,r({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},t._patch=function(e,t,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service)._patch(e,t,r({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},t._update=function(e,t,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service)._update(e,t,r({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},t._remove=function(e,t){void 0===t&&(t={});try{var n,o=this;return null==(n=o.context.app)||n.service(o.service)._remove(e,r({},t,{core:o.core})),Promise.resolve()}catch(e){return Promise.reject(e)}},e}(),a=["ucan"];function s(e,r,t){if(!e.s){if(t instanceof l){if(!t.s)return void(t.o=s.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(s.bind(null,e,r),s.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}const l=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){const n=new e,o=this.s;if(o){const e=1&o?r:t;if(e){try{s(n,1,e(this.v))}catch(e){s(n,2,e)}return n}return this}return this.o=function(e){try{const o=e.v;1&e.s?s(n,1,r?r(o):o):t?s(n,1,t(o)):s(n,2,o)}catch(e){s(n,2,e)}},n},e}();var v=/*#__PURE__*/function(){function r(e,r){this.authenticate=void 0,this.configuration={entity:"user",service:"users",defaultScheme:"symbol.storage",defaultHierPart:"*"},this.authenticate=e,r&&(this.configuration=r)}var t=r.prototype;return t.noThrowAuth=function(e){try{var r,t=null==(r=e.auth)?void 0:r.login;return t&&(e.core?e.core.login=t:e.core={login:t}),Promise.resolve(this.authenticate("jwt")(e).catch(function(r){return console.error("got error in no throw auth",r),e})).then(function(){return e})}catch(e){return Promise.reject(e)}},t.bareAuth=function(e){try{var r,t=null==(r=e.auth)?void 0:r.login;return t&&(e.core?e.core.login=t:e.core={login:t}),Promise.resolve(this.authenticate("jwt")(e))}catch(e){return Promise.reject(e)}},t.orVerifyLoop=function(r){try{var t,n={ok:!1,value:[]},o=function(o,i,c){var u=[];for(var v in o)u.push(v);return function(e,r,t){var n,o,i=-1;return function c(u){try{for(;++i<e.length&&(!t||!t());)if((u=r(i))&&u.then){if(!((a=u)instanceof l&&1&a.s))return void u.then(c,o||(o=s.bind(null,n=new l,2)));u=u.v}n?s(n,1,u):n=u}catch(e){s(n||(n=new l),2,e)}var a}(),n}(u,function(o){return function(o){var i=function(){var i;if(null==(i=n)||!i.ok){var c=r[o],u=c.ucan,s=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r.indexOf(t=i[n])>=0||(o[t]=e[t]);return o}(c,a);return Promise.resolve(function(r,t){try{return Promise.resolve(e.verifyUcan(r,t))}catch(e){return Promise.reject(e)}}(u,s)).then(function(e){n=e})}t=1}();if(i&&i.then)return i.then(function(){})}(u[o])},function(){return t})}(r);return Promise.resolve(o&&o.then?o.then(function(){return n}):n)}catch(e){return Promise.reject(e)}},t.verifyAgainstReqs=function(r,t,n,o){var i=this;return function(c){try{var u;return r&&t&&null!=o&&null!=(u=o.or)&&u.includes(c.method)?Promise.resolve(i.orVerifyLoop((n||[]).map(function(e){return{ucan:r,audience:t,requiredCapabilities:[e]}}))):Promise.resolve(e.verifyUcan(r,{audience:t,requiredCapabilities:n}))}catch(e){return Promise.reject(e)}}},t.ucanAuth=function(r,t){var n=this;return function(o){try{var i,c=function(c){return i?c:Promise.resolve(n.bareAuth(o)).then(function(i){var c,a;function s(){var r;if(null!=(r=v)&&r.ok)return o;var i=function(){function r(){if(v.ok)return o;throw console.error("Ucan capabilities requirements not met: ",v,o.type,o.path),new Error("Missing proper capabilities for this action: "+o.type+": "+o.path+" - "+o.method)}var i=function(){var r;if(null==(r=v)||!r.ok){var o=!1,i=[];h.forEach(function(r,t){var n=(e._get(r,"capability.can.namespace")||"").split(":");n[1]&&(r=e._set(r,"capability.can.namespace",n[0]),o=!0),i.push(r)});var c=function(){if(o)return Promise.resolve(n.verifyAgainstReqs(p,d,h,t)).then(function(e){v=e})}();if(c&&c.then)return c.then(function(){})}}();return i&&i.then?i.then(r):r()},c=t||{creatorPass:!1},a=c.creatorPass,s=c.loginPass,l=function(){if(a&&("*"===a||a.includes(o.method))||null!=s&&s.length&&("*"===s[1]||s[1].includes(o.method)))return Promise.resolve(new u(o.path,o,{skipJoins:!0}).get(o.id)).then(function(r){var t,n;if(a)v.ok=(null==r||null==(t=r.createdBy)?void 0:t.login)===((null==(n=o.login)?void 0:n._id)||"***");else if(s){var i,c=e._flatten(s[0].map(function(t){return e._get(r,t)}));v.ok=c.filter(function(e){return!!e}).includes(null==(i=o.login)?void 0:i._id)}})}();return l&&l.then?l.then(i):i()}if(o=i,"*"===r)return o;if(null!=t&&t.adminPass&&o.params.admin_pass)return o;var l=o.app.get("authentication"),v={ok:!1,value:[]},f=e.encodeKeyPair({secretKey:l.secret}).did(),h=(r||[]).map(function(r){var t={defaultScheme:n.configuration.defaultScheme,defaultHierPart:n.configuration.defaultHierPart};return{capability:Array.isArray(r)?e.genCapability({with:{scheme:n.configuration.defaultScheme,hierPart:n.configuration.defaultHierPart},can:{namespace:r[0],segments:"string"==typeof r[1]?[r[1]]:r[1]}},t):e.genCapability(r,t),rootIssuer:f}}),p=null==(c=o.params.core)?void 0:c.client_ucan,d=null==(a=o.params.core)?void 0:a.ucan_aud,m=function(){if(h.length)return Promise.resolve(n.verifyAgainstReqs(p,d,h,t)).then(function(e){v=e});v.ok=!0}();return m&&m.then?m.then(s):s()})},a=function(){if("$"===r)return Promise.resolve(n.noThrowAuth(o)).then(function(e){return i=1,e})}();return Promise.resolve(a&&a.then?a.then(c):c(a))}catch(e){return Promise.reject(e)}}},t.allUcanAuth=function(e,r){var t=this;return function(n){try{var o,i=null==(o=n.auth)?void 0:o.login;if(i&&(n.core?n.core.login=i:n.core={login:i}),"before"===n.type){var c=n.method;return Promise.resolve(e[c]||e.all?t.ucanAuth(e[c]||e.all,r)(n):n)}return Promise.resolve(n)}catch(e){return Promise.reject(e)}}},r}();exports.CoreCall=u,exports.NotAuthError=c,exports.UcanAuth=v,exports.anyAuth="*",exports.genAuthService=function(e,r){},exports.noThrow="$",exports.updateUcan=function(){return function(t){try{var n=t.data,o=n.add,i=void 0===o?[]:o,c=n.remove,a=void 0===c?[]:c;if(!(null!=i&&i.length||null!=a&&a.length))throw new Error("No new capabilities passed");var s=t.app.get("authentication").secret,l=e.encodeKeyPair({secretKey:s}).did(),v=e.stackAbilities([].concat(i,a));return Promise.resolve(e.verifyUcan(t.params.login.ucan,{audience:t.params.core.ucan_aud,requiredCapabilities:v.map(function(e){return{capability:e,rootIssuer:l}})})).then(function(n){if(null==n||!n.ok)throw new Error("You don't have sufficient capabilities to grant those capabilities");var o=t.id,c=t.data.service||"logins",l=t.data.path||"ucan";return Promise.resolve(new u(c,t,{skipJoins:!0}).get(o)).then(function(n){var v=e.parseUcan(e._get(n,l)).payload,f=v.aud,h=v.att,p=v.prf,d=[].concat(h);return null!=a&&a.length&&(d=e.reduceAbilities(a,h)),null!=i&&i.length&&(d=e.stackAbilities([].concat(h,i))),Promise.resolve(e.buildUcan(r({issuer:e.encodeKeyPair({secretKey:s}),audience:f,proofs:p},t.data,{capabilities:d}))).then(function(r){var n=e.ucanToken(r);return Promise.resolve(e.validateUcan(n)).then(function(e){var r;if(!e)throw new Error("Invalid ucan generated when updating");return Promise.resolve(new u(c,t).patch(o,(r={},r[l]=n,r))).then(function(e){return t.result={raw:t.data,encoded:n,subject:e},t})})})})})}catch(e){return Promise.reject(e)}}};
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './auth-service';
2
+ export * from './core';
3
+ export * from './hooks';
4
+ export * from './types';
@@ -0,0 +1 @@
1
+ import{verifyUcan as e,_get as r,_set as t,_flatten as n,encodeKeyPair as o,genCapability as i,stackAbilities as c,parseUcan as u,reduceAbilities as a,buildUcan as s,ucanToken as l,validateUcan as f}from"symbol-ucan";function v(){return v=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},v.apply(this,arguments)}function h(e){return h=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},h(e)}function p(e,r){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,r){return e.__proto__=r,e},p(e,r)}function d(e,r,t){return d=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct.bind():function(e,r,t){var n=[null];n.push.apply(n,r);var o=new(Function.bind.apply(e,n));return t&&p(o,t.prototype),o},d.apply(null,arguments)}function m(e){var r="function"==typeof Map?new Map:void 0;return m=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(e))return r.get(e);r.set(e,t)}function t(){return d(e,arguments,h(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),p(t,e)},m(e)}var y=/*#__PURE__*/function(e){var r,t;function n(r){return e.call(this,r)||this}return t=e,(r=n).prototype=Object.create(t.prototype),r.prototype.constructor=r,p(r,t),n}(/*#__PURE__*/m(Error)),P=function(e,r){},g=/*#__PURE__*/function(){function e(e,r,t){var n;this.context=void 0,this.service=void 0,this.core=void 0,this.service=e,this.context=r,this.core=v({},null==(n=r.params)?void 0:n.core,t)}var r=e.prototype;return r.get=function(e,r){void 0===r&&(r={});try{var t,n=this;return Promise.resolve(null==(t=n.context.app)?void 0:t.service(n.service).get(e,v({},r,{core:n.core})))}catch(e){return Promise.reject(e)}},r.find=function(e){void 0===e&&(e={});try{var r,t=this;return Promise.resolve(null==(r=t.context.app)?void 0:r.service(t.service).find(v({},e,{core:t.core})))}catch(e){return Promise.reject(e)}},r.create=function(e,r){void 0===r&&(r={});try{var t,n=this;return Promise.resolve(null==(t=n.context.app)?void 0:t.service(n.service).create(e,v({},r,{core:n.core})))}catch(e){return Promise.reject(e)}},r.patch=function(e,r,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service).patch(e,r,v({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},r.update=function(e,r,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service).update(e,r,v({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},r.remove=function(e,r){void 0===r&&(r={});try{var t,n=this;return null==(t=n.context.app)||t.service(n.service).remove(e,v({},r,{core:n.core})),Promise.resolve()}catch(e){return Promise.reject(e)}},r._get=function(e,r){void 0===r&&(r={});try{var t,n=this;return Promise.resolve(null==(t=n.context.app)?void 0:t.service(n.service)._get(e,v({},r,{core:n.core})))}catch(e){return Promise.reject(e)}},r._find=function(e){void 0===e&&(e={});try{var r,t=this;return Promise.resolve(null==(r=t.context.app)?void 0:r.service(t.service)._find(v({},e,{core:t.core})))}catch(e){return Promise.reject(e)}},r._create=function(e,r){void 0===r&&(r={});try{var t,n=this;return Promise.resolve(null==(t=n.context.app)?void 0:t.service(n.service)._create(e,v({},r,{core:n.core})))}catch(e){return Promise.reject(e)}},r._patch=function(e,r,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service)._patch(e,r,v({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},r._update=function(e,r,t){void 0===t&&(t={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service)._update(e,r,v({},t,{core:o.core})))}catch(e){return Promise.reject(e)}},r._remove=function(e,r){void 0===r&&(r={});try{var t,n=this;return null==(t=n.context.app)||t.service(n.service)._remove(e,v({},r,{core:n.core})),Promise.resolve()}catch(e){return Promise.reject(e)}},e}(),b=["ucan"];function j(e,r,t){if(!e.s){if(t instanceof w){if(!t.s)return void(t.o=j.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(j.bind(null,e,r),j.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}const w=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){const n=new e,o=this.s;if(o){const e=1&o?r:t;if(e){try{j(n,1,e(this.v))}catch(e){j(n,2,e)}return n}return this}return this.o=function(e){try{const o=e.v;1&e.s?j(n,1,r?r(o):o):t?j(n,1,t(o)):j(n,2,o)}catch(e){j(n,2,e)}},n},e}();var _="*",O="$",x=/*#__PURE__*/function(){function c(e,r){this.authenticate=void 0,this.configuration={entity:"user",service:"users",defaultScheme:"symbol.storage",defaultHierPart:"*"},this.authenticate=e,r&&(this.configuration=r)}var u=c.prototype;return u.noThrowAuth=function(e){try{var r,t=null==(r=e.auth)?void 0:r.login;return t&&(e.core?e.core.login=t:e.core={login:t}),Promise.resolve(this.authenticate("jwt")(e).catch(function(r){return console.error("got error in no throw auth",r),e})).then(function(){return e})}catch(e){return Promise.reject(e)}},u.bareAuth=function(e){try{var r,t=null==(r=e.auth)?void 0:r.login;return t&&(e.core?e.core.login=t:e.core={login:t}),Promise.resolve(this.authenticate("jwt")(e))}catch(e){return Promise.reject(e)}},u.orVerifyLoop=function(r){try{var t,n={ok:!1,value:[]},o=function(o,i,c){var u=[];for(var a in o)u.push(a);return function(e,r,t){var n,o,i=-1;return function c(u){try{for(;++i<e.length&&(!t||!t());)if((u=r(i))&&u.then){if(!((a=u)instanceof w&&1&a.s))return void u.then(c,o||(o=j.bind(null,n=new w,2)));u=u.v}n?j(n,1,u):n=u}catch(e){j(n||(n=new w),2,e)}var a}(),n}(u,function(o){return function(o){var i=function(){var i;if(null==(i=n)||!i.ok){var c=r[o],u=c.ucan,a=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r.indexOf(t=i[n])>=0||(o[t]=e[t]);return o}(c,b);return Promise.resolve(function(r,t){try{return Promise.resolve(e(r,t))}catch(e){return Promise.reject(e)}}(u,a)).then(function(e){n=e})}t=1}();if(i&&i.then)return i.then(function(){})}(u[o])},function(){return t})}(r);return Promise.resolve(o&&o.then?o.then(function(){return n}):n)}catch(e){return Promise.reject(e)}},u.verifyAgainstReqs=function(r,t,n,o){var i=this;return function(c){try{var u;return r&&t&&null!=o&&null!=(u=o.or)&&u.includes(c.method)?Promise.resolve(i.orVerifyLoop((n||[]).map(function(e){return{ucan:r,audience:t,requiredCapabilities:[e]}}))):Promise.resolve(e(r,{audience:t,requiredCapabilities:n}))}catch(e){return Promise.reject(e)}}},u.ucanAuth=function(e,c){var u=this;return function(a){try{var s,l=function(l){return s?l:Promise.resolve(u.bareAuth(a)).then(function(s){var l,f;function v(){var e;if(null!=(e=p)&&e.ok)return a;var o=function(){function e(){if(p.ok)return a;throw console.error("Ucan capabilities requirements not met: ",p,a.type,a.path),new Error("Missing proper capabilities for this action: "+a.type+": "+a.path+" - "+a.method)}var n=function(){var e;if(null==(e=p)||!e.ok){var n=!1,o=[];m.forEach(function(e,i){var c=(r(e,"capability.can.namespace")||"").split(":");c[1]&&(e=t(e,"capability.can.namespace",c[0]),n=!0),o.push(e)});var i=function(){if(n)return Promise.resolve(u.verifyAgainstReqs(y,P,m,c)).then(function(e){p=e})}();if(i&&i.then)return i.then(function(){})}}();return n&&n.then?n.then(e):e()},i=c||{creatorPass:!1},s=i.creatorPass,l=i.loginPass,f=function(){if(s&&("*"===s||s.includes(a.method))||null!=l&&l.length&&("*"===l[1]||l[1].includes(a.method)))return Promise.resolve(new g(a.path,a,{skipJoins:!0}).get(a.id)).then(function(e){var t,o;if(s)p.ok=(null==e||null==(t=e.createdBy)?void 0:t.login)===((null==(o=a.login)?void 0:o._id)||"***");else if(l){var i,c=n(l[0].map(function(t){return r(e,t)}));p.ok=c.filter(function(e){return!!e}).includes(null==(i=a.login)?void 0:i._id)}})}();return f&&f.then?f.then(o):o()}if(a=s,"*"===e)return a;if(null!=c&&c.adminPass&&a.params.admin_pass)return a;var h=a.app.get("authentication"),p={ok:!1,value:[]},d=o({secretKey:h.secret}).did(),m=(e||[]).map(function(e){var r={defaultScheme:u.configuration.defaultScheme,defaultHierPart:u.configuration.defaultHierPart};return{capability:Array.isArray(e)?i({with:{scheme:u.configuration.defaultScheme,hierPart:u.configuration.defaultHierPart},can:{namespace:e[0],segments:"string"==typeof e[1]?[e[1]]:e[1]}},r):i(e,r),rootIssuer:d}}),y=null==(l=a.params.core)?void 0:l.client_ucan,P=null==(f=a.params.core)?void 0:f.ucan_aud,b=function(){if(m.length)return Promise.resolve(u.verifyAgainstReqs(y,P,m,c)).then(function(e){p=e});p.ok=!0}();return b&&b.then?b.then(v):v()})},f=function(){if("$"===e)return Promise.resolve(u.noThrowAuth(a)).then(function(e){return s=1,e})}();return Promise.resolve(f&&f.then?f.then(l):l(f))}catch(e){return Promise.reject(e)}}},u.allUcanAuth=function(e,r){var t=this;return function(n){try{var o,i=null==(o=n.auth)?void 0:o.login;if(i&&(n.core?n.core.login=i:n.core={login:i}),"before"===n.type){var c=n.method;return Promise.resolve(e[c]||e.all?t.ucanAuth(e[c]||e.all,r)(n):n)}return Promise.resolve(n)}catch(e){return Promise.reject(e)}}},c}(),k=function(){return function(t){try{var n=t.data,i=n.add,h=void 0===i?[]:i,p=n.remove,d=void 0===p?[]:p;if(!(null!=h&&h.length||null!=d&&d.length))throw new Error("No new capabilities passed");var m=t.app.get("authentication").secret,y=o({secretKey:m}).did(),P=c([].concat(h,d));return Promise.resolve(e(t.params.login.ucan,{audience:t.params.core.ucan_aud,requiredCapabilities:P.map(function(e){return{capability:e,rootIssuer:y}})})).then(function(e){if(null==e||!e.ok)throw new Error("You don't have sufficient capabilities to grant those capabilities");var n=t.id,i=t.data.service||"logins",p=t.data.path||"ucan";return Promise.resolve(new g(i,t,{skipJoins:!0}).get(n)).then(function(e){var y=u(r(e,p)).payload,P=y.aud,b=y.att,j=y.prf,w=[].concat(b);return null!=d&&d.length&&(w=a(d,b)),null!=h&&h.length&&(w=c([].concat(b,h))),Promise.resolve(s(v({issuer:o({secretKey:m}),audience:P,proofs:j},t.data,{capabilities:w}))).then(function(e){var r=l(e);return Promise.resolve(f(r)).then(function(e){var o;if(!e)throw new Error("Invalid ucan generated when updating");return Promise.resolve(new g(i,t).patch(n,(o={},o[p]=r,o))).then(function(e){return t.result={raw:t.data,encoded:r,subject:e},t})})})})})}catch(e){return Promise.reject(e)}}};export{g as CoreCall,y as NotAuthError,x as UcanAuth,_ as anyAuth,P as genAuthService,O as noThrow,k as updateUcan};
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ import{verifyUcan as e,encodeKeyPair as t,genCapability as a,_flatten as r,_get as i,_set as n,stackAbilities as o,parseUcan as c,reduceAbilities as s,buildUcan as u,ucanToken as l,validateUcan as h}from"symbol-ucan";function p(){return p=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var r in a)Object.prototype.hasOwnProperty.call(a,r)&&(e[r]=a[r])}return e},p.apply(this,arguments)}function v(e,t){if(null==e)return{};var a,r,i={},n=Object.keys(e);for(r=0;r<n.length;r++)t.indexOf(a=n[r])>=0||(i[a]=e[a]);return i}class d extends Error{constructor(e){super(e)}}const f=(e,t)=>{};class g{constructor(e,t,a){var r;this.context=void 0,this.service=void 0,this.core=void 0,this.service=e,this.context=t,this.core=p({},null==(r=t.params)?void 0:r.core,a)}async get(e,t={}){var a;return await(null==(a=this.context.app)?void 0:a.service(this.service).get(e,p({},t,{core:this.core})))}async find(e={}){var t;return await(null==(t=this.context.app)?void 0:t.service(this.service).find(p({},e,{core:this.core})))}async create(e,t={}){var a;return await(null==(a=this.context.app)?void 0:a.service(this.service).create(e,p({},t,{core:this.core})))}async patch(e,t,a={}){var r;return await(null==(r=this.context.app)?void 0:r.service(this.service).patch(e,t,p({},a,{core:this.core})))}async update(e,t,a={}){var r;return await(null==(r=this.context.app)?void 0:r.service(this.service).update(e,t,p({},a,{core:this.core})))}async remove(e,t={}){var a;null==(a=this.context.app)||a.service(this.service).remove(e,p({},t,{core:this.core}))}async _get(e,t={}){var a;return await(null==(a=this.context.app)?void 0:a.service(this.service)._get(e,p({},t,{core:this.core})))}async _find(e={}){var t;return await(null==(t=this.context.app)?void 0:t.service(this.service)._find(p({},e,{core:this.core})))}async _create(e,t={}){var a;return await(null==(a=this.context.app)?void 0:a.service(this.service)._create(e,p({},t,{core:this.core})))}async _patch(e,t,a={}){var r;return await(null==(r=this.context.app)?void 0:r.service(this.service)._patch(e,t,p({},a,{core:this.core})))}async _update(e,t,a={}){var r;return await(null==(r=this.context.app)?void 0:r.service(this.service)._update(e,t,p({},a,{core:this.core})))}async _remove(e,t={}){var a;null==(a=this.context.app)||a.service(this.service)._remove(e,p({},t,{core:this.core}))}}const y=["ucan"],w="*",m="$";class b{constructor(e,t){this.authenticate=void 0,this.configuration={entity:"user",service:"users",defaultScheme:"symbol.storage",defaultHierPart:"*"},this.authenticate=e,t&&(this.configuration=t)}async noThrowAuth(e){var t;const a=null==(t=e.auth)?void 0:t.login;return a&&(e.core?e.core.login=a:e.core={login:a}),await this.authenticate("jwt")(e).catch(t=>(console.error("got error in no throw auth",t),e)),e}async bareAuth(e){var t;const a=null==(t=e.auth)?void 0:t.login;return a&&(e.core?e.core.login=a:e.core={login:a}),this.authenticate("jwt")(e)}async orVerifyLoop(t){let a={ok:!1,value:[]};const r=async function(t,a){return await e(t,a)};for(const e in t){var i;if(null!=(i=a)&&i.ok)break;{const i=t[e],{ucan:n}=i,o=v(i,y);a=await r(n,o)}}return a}verifyAgainstReqs(t,a,r,i){var n=this;return async function(o){var c;return t&&a&&null!=i&&null!=(c=i.or)&&c.includes(o.method)?await n.orVerifyLoop((r||[]).map(e=>({ucan:t,audience:a,requiredCapabilities:[e]}))):await e(t,{audience:a,requiredCapabilities:r})}}ucanAuth(e,o){var c=this;return async function(s){var u,l,h;if("$"===e)return await c.noThrowAuth(s);if(s=await c.bareAuth(s),"*"===e)return s;if(null!=o&&o.adminPass&&s.params.admin_pass)return s;const{secret:p}=s.app.get("authentication");let v={ok:!1,value:[]};const d=t({secretKey:p}).did(),f=(e||[]).map(e=>{const t={defaultScheme:c.configuration.defaultScheme,defaultHierPart:c.configuration.defaultHierPart};return{capability:Array.isArray(e)?a({with:{scheme:c.configuration.defaultScheme,hierPart:c.configuration.defaultHierPart},can:{namespace:e[0],segments:"string"==typeof e[1]?[e[1]]:e[1]}},t):a(e,t),rootIssuer:d}}),y=null==(u=s.params.core)?void 0:u.client_ucan,w=null==(l=s.params.core)?void 0:l.ucan_aud;if(f.length?v=await c.verifyAgainstReqs(y,w,f,o):v.ok=!0,null!=(h=v)&&h.ok)return s;{var m;const{creatorPass:e,loginPass:t}=o||{creatorPass:!1};if(e&&("*"===e||e.includes(s.method))||null!=t&&t.length&&("*"===t[1]||t[1].includes(s.method))){const a=await new g(s.path,s,{skipJoins:!0}).get(s.id);var b,_;if(e)v.ok=(null==a||null==(b=a.createdBy)?void 0:b.login)===((null==(_=s.login)?void 0:_._id)||"***");else if(t){var x;const e=r(t[0].map(e=>i(a,e)));v.ok=e.filter(e=>!!e).includes(null==(x=s.login)?void 0:x._id)}}if(null==(m=v)||!m.ok){let e=!1;f.forEach((t,a)=>{const r=(i(t,"capability.can.namespace")||"").split(":");r[1]&&(t=n(t,"capability.can.namespace",r[0]),e=!0)}),e&&(v=await c.verifyAgainstReqs(y,w,f,o))}if(v.ok)return s;throw console.error("Ucan capabilities requirements not met: ",v,s.type,s.path),new Error("Missing proper capabilities for this action: "+s.type+": "+s.path+" - "+s.method)}}}allUcanAuth(e,t){var a=this;return async function(r){var i;const n=null==(i=r.auth)?void 0:i.login;if(n&&(r.core?r.core.login=n:r.core={login:n}),"before"===r.type){const{method:i}=r;return e[i]||e.all?a.ucanAuth(e[i]||e.all,t)(r):r}return r}}}const _=()=>async a=>{const{add:r=[],remove:n=[]}=a.data;if(!(null!=r&&r.length||null!=n&&n.length))throw new Error("No new capabilities passed");const{secret:v}=a.app.get("authentication"),d=t({secretKey:v}).did(),f=o([...r,...n]),y=await e(a.params.login.ucan,{audience:a.params.core.ucan_aud,requiredCapabilities:f.map(e=>({capability:e,rootIssuer:d}))});if(null==y||!y.ok)throw new Error("You don't have sufficient capabilities to grant those capabilities");const w=a.id,m=a.data.service||"logins",b=a.data.path||"ucan",_=await new g(m,a,{skipJoins:!0}).get(w),x=c(i(_,b)),{aud:k,att:A,prf:P}=x.payload;let j=[...A];null!=n&&n.length&&(j=s(n,A)),null!=r&&r.length&&(j=o([...A,...r]));const q=await u(p({issuer:t({secretKey:v}),audience:k,proofs:P},a.data,{capabilities:j})),E=l(q);if(!await h(E))throw new Error("Invalid ucan generated when updating");const O=await new g(m,a).patch(w,{[b]:E});return a.result={raw:a.data,encoded:E,subject:O},a};export{g as CoreCall,d as NotAuthError,b as UcanAuth,w as anyAuth,f as genAuthService,m as noThrow,_ as updateUcan};
@@ -0,0 +1 @@
1
+ !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("symbol-ucan")):"function"==typeof define&&define.amd?define(["exports","symbol-ucan"],r):r((e||self).feathersUcan={},e.symbolUcan)}(this,function(e,r){function t(){return t=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var t=arguments[r];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e},t.apply(this,arguments)}function n(e){return n=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},n(e)}function o(e,r){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,r){return e.__proto__=r,e},o(e,r)}function i(e,r,t){return i=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct.bind():function(e,r,t){var n=[null];n.push.apply(n,r);var i=new(Function.bind.apply(e,n));return t&&o(i,t.prototype),i},i.apply(null,arguments)}function c(e){var r="function"==typeof Map?new Map:void 0;return c=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(e))return r.get(e);r.set(e,t)}function t(){return i(e,arguments,n(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),o(t,e)},c(e)}var u=/*#__PURE__*/function(e){var r,t;function n(r){return e.call(this,r)||this}return t=e,(r=n).prototype=Object.create(t.prototype),r.prototype.constructor=r,o(r,t),n}(/*#__PURE__*/c(Error)),a=/*#__PURE__*/function(){function e(e,r,n){var o;this.context=void 0,this.service=void 0,this.core=void 0,this.service=e,this.context=r,this.core=t({},null==(o=r.params)?void 0:o.core,n)}var r=e.prototype;return r.get=function(e,r){void 0===r&&(r={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service).get(e,t({},r,{core:o.core})))}catch(e){return Promise.reject(e)}},r.find=function(e){void 0===e&&(e={});try{var r,n=this;return Promise.resolve(null==(r=n.context.app)?void 0:r.service(n.service).find(t({},e,{core:n.core})))}catch(e){return Promise.reject(e)}},r.create=function(e,r){void 0===r&&(r={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service).create(e,t({},r,{core:o.core})))}catch(e){return Promise.reject(e)}},r.patch=function(e,r,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service).patch(e,r,t({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},r.update=function(e,r,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service).update(e,r,t({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},r.remove=function(e,r){void 0===r&&(r={});try{var n,o=this;return null==(n=o.context.app)||n.service(o.service).remove(e,t({},r,{core:o.core})),Promise.resolve()}catch(e){return Promise.reject(e)}},r._get=function(e,r){void 0===r&&(r={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service)._get(e,t({},r,{core:o.core})))}catch(e){return Promise.reject(e)}},r._find=function(e){void 0===e&&(e={});try{var r,n=this;return Promise.resolve(null==(r=n.context.app)?void 0:r.service(n.service)._find(t({},e,{core:n.core})))}catch(e){return Promise.reject(e)}},r._create=function(e,r){void 0===r&&(r={});try{var n,o=this;return Promise.resolve(null==(n=o.context.app)?void 0:n.service(o.service)._create(e,t({},r,{core:o.core})))}catch(e){return Promise.reject(e)}},r._patch=function(e,r,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service)._patch(e,r,t({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},r._update=function(e,r,n){void 0===n&&(n={});try{var o,i=this;return Promise.resolve(null==(o=i.context.app)?void 0:o.service(i.service)._update(e,r,t({},n,{core:i.core})))}catch(e){return Promise.reject(e)}},r._remove=function(e,r){void 0===r&&(r={});try{var n,o=this;return null==(n=o.context.app)||n.service(o.service)._remove(e,t({},r,{core:o.core})),Promise.resolve()}catch(e){return Promise.reject(e)}},e}(),s=["ucan"];function l(e,r,t){if(!e.s){if(t instanceof f){if(!t.s)return void(t.o=l.bind(null,e,r));1&r&&(r=t.s),t=t.v}if(t&&t.then)return void t.then(l.bind(null,e,r),l.bind(null,e,2));e.s=r,e.v=t;var n=e.o;n&&n(e)}}const f=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(r,t){const n=new e,o=this.s;if(o){const e=1&o?r:t;if(e){try{l(n,1,e(this.v))}catch(e){l(n,2,e)}return n}return this}return this.o=function(e){try{const o=e.v;1&e.s?l(n,1,r?r(o):o):t?l(n,1,t(o)):l(n,2,o)}catch(e){l(n,2,e)}},n},e}();var v=/*#__PURE__*/function(){function e(e,r){this.authenticate=void 0,this.configuration={entity:"user",service:"users",defaultScheme:"symbol.storage",defaultHierPart:"*"},this.authenticate=e,r&&(this.configuration=r)}var t=e.prototype;return t.noThrowAuth=function(e){try{var r,t=null==(r=e.auth)?void 0:r.login;return t&&(e.core?e.core.login=t:e.core={login:t}),Promise.resolve(this.authenticate("jwt")(e).catch(function(r){return console.error("got error in no throw auth",r),e})).then(function(){return e})}catch(e){return Promise.reject(e)}},t.bareAuth=function(e){try{var r,t=null==(r=e.auth)?void 0:r.login;return t&&(e.core?e.core.login=t:e.core={login:t}),Promise.resolve(this.authenticate("jwt")(e))}catch(e){return Promise.reject(e)}},t.orVerifyLoop=function(e){try{var t,n={ok:!1,value:[]},o=function(o,i,c){var u=[];for(var a in o)u.push(a);return function(e,r,t){var n,o,i=-1;return function c(u){try{for(;++i<e.length&&(!t||!t());)if((u=r(i))&&u.then){if(!((a=u)instanceof f&&1&a.s))return void u.then(c,o||(o=l.bind(null,n=new f,2)));u=u.v}n?l(n,1,u):n=u}catch(e){l(n||(n=new f),2,e)}var a}(),n}(u,function(o){return function(o){var i=function(){var i;if(null==(i=n)||!i.ok){var c=e[o],u=c.ucan,a=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r.indexOf(t=i[n])>=0||(o[t]=e[t]);return o}(c,s);return Promise.resolve(function(e,t){try{return Promise.resolve(r.verifyUcan(e,t))}catch(e){return Promise.reject(e)}}(u,a)).then(function(e){n=e})}t=1}();if(i&&i.then)return i.then(function(){})}(u[o])},function(){return t})}(e);return Promise.resolve(o&&o.then?o.then(function(){return n}):n)}catch(e){return Promise.reject(e)}},t.verifyAgainstReqs=function(e,t,n,o){var i=this;return function(c){try{var u;return e&&t&&null!=o&&null!=(u=o.or)&&u.includes(c.method)?Promise.resolve(i.orVerifyLoop((n||[]).map(function(r){return{ucan:e,audience:t,requiredCapabilities:[r]}}))):Promise.resolve(r.verifyUcan(e,{audience:t,requiredCapabilities:n}))}catch(e){return Promise.reject(e)}}},t.ucanAuth=function(e,t){var n=this;return function(o){try{var i,c=function(c){return i?c:Promise.resolve(n.bareAuth(o)).then(function(i){var c,u;function s(){var e;if(null!=(e=f)&&e.ok)return o;var i=function(){function e(){if(f.ok)return o;throw console.error("Ucan capabilities requirements not met: ",f,o.type,o.path),new Error("Missing proper capabilities for this action: "+o.type+": "+o.path+" - "+o.method)}var i=function(){var e;if(null==(e=f)||!e.ok){var o=!1,i=[];h.forEach(function(e,t){var n=(r._get(e,"capability.can.namespace")||"").split(":");n[1]&&(e=r._set(e,"capability.can.namespace",n[0]),o=!0),i.push(e)});var c=function(){if(o)return Promise.resolve(n.verifyAgainstReqs(p,d,h,t)).then(function(e){f=e})}();if(c&&c.then)return c.then(function(){})}}();return i&&i.then?i.then(e):e()},c=t||{creatorPass:!1},u=c.creatorPass,s=c.loginPass,l=function(){if(u&&("*"===u||u.includes(o.method))||null!=s&&s.length&&("*"===s[1]||s[1].includes(o.method)))return Promise.resolve(new a(o.path,o,{skipJoins:!0}).get(o.id)).then(function(e){var t,n;if(u)f.ok=(null==e||null==(t=e.createdBy)?void 0:t.login)===((null==(n=o.login)?void 0:n._id)||"***");else if(s){var i,c=r._flatten(s[0].map(function(t){return r._get(e,t)}));f.ok=c.filter(function(e){return!!e}).includes(null==(i=o.login)?void 0:i._id)}})}();return l&&l.then?l.then(i):i()}if(o=i,"*"===e)return o;if(null!=t&&t.adminPass&&o.params.admin_pass)return o;var l=o.app.get("authentication"),f={ok:!1,value:[]},v=r.encodeKeyPair({secretKey:l.secret}).did(),h=(e||[]).map(function(e){var t={defaultScheme:n.configuration.defaultScheme,defaultHierPart:n.configuration.defaultHierPart};return{capability:Array.isArray(e)?r.genCapability({with:{scheme:n.configuration.defaultScheme,hierPart:n.configuration.defaultHierPart},can:{namespace:e[0],segments:"string"==typeof e[1]?[e[1]]:e[1]}},t):r.genCapability(e,t),rootIssuer:v}}),p=null==(c=o.params.core)?void 0:c.client_ucan,d=null==(u=o.params.core)?void 0:u.ucan_aud,m=function(){if(h.length)return Promise.resolve(n.verifyAgainstReqs(p,d,h,t)).then(function(e){f=e});f.ok=!0}();return m&&m.then?m.then(s):s()})},u=function(){if("$"===e)return Promise.resolve(n.noThrowAuth(o)).then(function(e){return i=1,e})}();return Promise.resolve(u&&u.then?u.then(c):c(u))}catch(e){return Promise.reject(e)}}},t.allUcanAuth=function(e,r){var t=this;return function(n){try{var o,i=null==(o=n.auth)?void 0:o.login;if(i&&(n.core?n.core.login=i:n.core={login:i}),"before"===n.type){var c=n.method;return Promise.resolve(e[c]||e.all?t.ucanAuth(e[c]||e.all,r)(n):n)}return Promise.resolve(n)}catch(e){return Promise.reject(e)}}},e}();e.CoreCall=a,e.NotAuthError=u,e.UcanAuth=v,e.anyAuth="*",e.genAuthService=function(e,r){},e.noThrow="$",e.updateUcan=function(){return function(e){try{var n=e.data,o=n.add,i=void 0===o?[]:o,c=n.remove,u=void 0===c?[]:c;if(!(null!=i&&i.length||null!=u&&u.length))throw new Error("No new capabilities passed");var s=e.app.get("authentication").secret,l=r.encodeKeyPair({secretKey:s}).did(),f=r.stackAbilities([].concat(i,u));return Promise.resolve(r.verifyUcan(e.params.login.ucan,{audience:e.params.core.ucan_aud,requiredCapabilities:f.map(function(e){return{capability:e,rootIssuer:l}})})).then(function(n){if(null==n||!n.ok)throw new Error("You don't have sufficient capabilities to grant those capabilities");var o=e.id,c=e.data.service||"logins",l=e.data.path||"ucan";return Promise.resolve(new a(c,e,{skipJoins:!0}).get(o)).then(function(n){var f=r.parseUcan(r._get(n,l)).payload,v=f.aud,h=f.att,p=f.prf,d=[].concat(h);return null!=u&&u.length&&(d=r.reduceAbilities(u,h)),null!=i&&i.length&&(d=r.stackAbilities([].concat(h,i))),Promise.resolve(r.buildUcan(t({issuer:r.encodeKeyPair({secretKey:s}),audience:v,proofs:p},e.data,{capabilities:d}))).then(function(t){var n=r.ucanToken(t);return Promise.resolve(r.validateUcan(n)).then(function(r){var t;if(!r)throw new Error("Invalid ucan generated when updating");return Promise.resolve(new a(c,e).patch(o,(t={},t[l]=n,t))).then(function(r){return e.result={raw:e.data,encoded:n,subject:r},e})})})})})}catch(e){return Promise.reject(e)}}}});
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,72 @@
1
+ export type AnyObj = {
2
+ [key: string]: any;
3
+ };
4
+ export interface AuthenticationRequest {
5
+ strategy?: string;
6
+ [key: string]: any;
7
+ }
8
+ export interface JwtHeader {
9
+ alg: string | Algorithm;
10
+ typ?: string | undefined;
11
+ cty?: string | undefined;
12
+ crit?: Array<string | Exclude<keyof JwtHeader, 'crit'>> | undefined;
13
+ kid?: string | undefined;
14
+ jku?: string | undefined;
15
+ x5u?: string | string[] | undefined;
16
+ 'x5t#S256'?: string | undefined;
17
+ x5t?: string | undefined;
18
+ x5c?: string | string[] | undefined;
19
+ }
20
+ export interface SignOptions {
21
+ /**
22
+ * Signature algorithm. Could be one of these values :
23
+ * - HS256: HMAC using SHA-256 hash algorithm (default)
24
+ * - HS384: HMAC using SHA-384 hash algorithm
25
+ * - HS512: HMAC using SHA-512 hash algorithm
26
+ * - RS256: RSASSA using SHA-256 hash algorithm
27
+ * - RS384: RSASSA using SHA-384 hash algorithm
28
+ * - RS512: RSASSA using SHA-512 hash algorithm
29
+ * - ES256: ECDSA using P-256 curve and SHA-256 hash algorithm
30
+ * - ES384: ECDSA using P-384 curve and SHA-384 hash algorithm
31
+ * - ES512: ECDSA using P-521 curve and SHA-512 hash algorithm
32
+ * - none: No digital signature or MAC value included
33
+ */
34
+ algorithm?: Algorithm | undefined;
35
+ keyid?: string | undefined;
36
+ /** expressed in seconds or a string describing a time span [zeit/ms](https://github.com/zeit/ms.js). Eg: 60, "2 days", "10h", "7d" */
37
+ expiresIn?: string | number | undefined;
38
+ /** expressed in seconds or a string describing a time span [zeit/ms](https://github.com/zeit/ms.js). Eg: 60, "2 days", "10h", "7d" */
39
+ notBefore?: string | number | undefined;
40
+ audience?: string | string[] | undefined;
41
+ subject?: string | undefined;
42
+ issuer?: string | undefined;
43
+ jwtid?: string | undefined;
44
+ mutatePayload?: boolean | undefined;
45
+ noTimestamp?: boolean | undefined;
46
+ header?: JwtHeader | undefined;
47
+ encoding?: string | undefined;
48
+ allowInsecureKeySizes?: boolean | undefined;
49
+ allowInvalidAsymmetricKeyTypes?: boolean | undefined;
50
+ }
51
+ export interface Query {
52
+ [key: string]: any;
53
+ }
54
+ export interface Params<Q = Query> {
55
+ query?: Q;
56
+ provider?: string;
57
+ route?: {
58
+ [key: string]: any;
59
+ };
60
+ headers?: {
61
+ [key: string]: any;
62
+ };
63
+ }
64
+ export interface AuthenticationParams extends Params {
65
+ payload?: {
66
+ [key: string]: any;
67
+ };
68
+ jwtOptions?: SignOptions;
69
+ authStrategies?: string[];
70
+ secret?: string;
71
+ [key: string]: any;
72
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "feathers-ucan",
3
+ "version": "0.0.0",
4
+ "description": "Ucan extension of feathers jwt auth",
5
+ "source": "src/index.ts",
6
+ "unpkg": "lib/index.umd.js",
7
+ "main": "lib/index.js",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": "./lib/index.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "scripts": {
14
+ "test": "test",
15
+ "prebuild": "rimraf lib dist && node scripts/gen-version.js",
16
+ "build": "rm -rf lib && microbundle --tsconfig tsconfig.json --no-sourcemap",
17
+ "dev": "microbundle --watch --tsconfig tsconfig.json --no-sourcemap"
18
+ },
19
+ "files": [
20
+ "lib"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://gitlab.com/symbolsyntax/symbol-client.git"
25
+ },
26
+ "author": "iy foundation",
27
+ "license": "ISC",
28
+ "bugs": {
29
+ "url": "https://github.com/ha6755ad/symbol-utils/issues"
30
+ },
31
+ "homepage": "https://github.com/ha6755ad/symbol-utils#readme",
32
+ "devDependencies": {
33
+ "@types/ua-parser-js": "^0.7.36",
34
+ "@typescript-eslint/eslint-plugin": "^5.10.0",
35
+ "@typescript-eslint/parser": "^5.10.0",
36
+ "eslint": "^8.10.0",
37
+ "eslint-config-prettier": "^8.1.0",
38
+ "microbundle": "^0.15.1",
39
+ "prettier": "^2.5.1",
40
+ "typescript": "^4.5.4"
41
+ },
42
+ "dependencies": {
43
+ "@feathersjs/feathers": "^5.0.11",
44
+ "@ucans/ucans": "^0.12.0",
45
+ "radash": "^11.0.0",
46
+ "symbol-ucan": "^0.0.0"
47
+ }
48
+ }