@travetto/auth 5.0.16 → 6.0.0-rc.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 CHANGED
@@ -17,20 +17,23 @@ This module provides the high-level backdrop for managing security principals.
17
17
  * Standard Types
18
18
  * Authentication Contract
19
19
  * Authorization Contract
20
- * Common security-related utilities for
21
- * Checking permissions
22
- * Generating passwords
20
+ * Authorization Services
21
+ * Authorization Context
23
22
 
24
23
  ## Standard Types
25
- The module's goal is to be as flexible as possible. To that end, the primary contract that this module defines, is that of the [Principal Structure](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L8).
24
+ The module's goal is to be as flexible as possible. To that end, the primary contract that this module defines, is that of the [Principal Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L8).
26
25
 
27
- **Code: Principal Structure**
26
+ **Code: Principal Contract**
28
27
  ```typescript
29
28
  export interface Principal<D = AnyMap> {
30
29
  /**
31
30
  * Primary identifier for a user
32
31
  */
33
- id: string;
32
+ readonly id: string;
33
+ /**
34
+ * Unique identifier for the principal's lifecycle
35
+ */
36
+ readonly sessionId?: string;
34
37
  /**
35
38
  * Date of expiration
36
39
  */
@@ -39,37 +42,32 @@ export interface Principal<D = AnyMap> {
39
42
  * Date of issuance
40
43
  */
41
44
  issuedAt?: Date;
42
- /**
43
- * Max age in seconds a principal is valid
44
- */
45
- maxAge?: number;
46
45
  /**
47
46
  * The source of the issuance
48
47
  */
49
- issuer?: string;
48
+ readonly issuer?: string;
50
49
  /**
51
50
  * Supplemental details
52
51
  */
53
- details: D;
52
+ readonly details: D;
54
53
  /**
55
54
  * List of all provided permissions
56
55
  */
57
- permissions?: string[];
56
+ readonly permissions?: string[];
58
57
  }
59
58
  ```
60
59
 
61
- As referenced above, a [Principal Structure](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L8) is defined as a user with respect to a security context. This can be information the application knows about the user (authorized) or what a separate service may know about a user (3rd-party authentication).
60
+ As referenced above, a [Principal Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L8) is defined as a user with respect to a security context. This can be information the application knows about the user (authorized) or what a separate service may know about a user (3rd-party authentication).
62
61
 
63
- ## Authentication
62
+ ## Authentication Contract
64
63
 
65
- **Code: Authenticator**
64
+ **Code: Authenticator Contract**
66
65
  ```typescript
67
- export interface Authenticator<T = unknown, P extends Principal = Principal, C = unknown> {
66
+ export interface Authenticator<T = unknown, C = unknown, P extends Principal = Principal> {
68
67
  /**
69
- * Allows for the authenticator to be initialized if needed
70
- * @param ctx
68
+ * Retrieve the authenticator state for the given request
71
69
  */
72
- initialize?(ctx: C): Promise<void>;
70
+ getState?(context?: C): Promise<AuthenticatorState | undefined> | AuthenticatorState | undefined;
73
71
 
74
72
  /**
75
73
  * Verify the payload, ensuring the payload is correctly identified.
@@ -78,32 +76,31 @@ export interface Authenticator<T = unknown, P extends Principal = Principal, C =
78
76
  * @returns undefined if authentication is valid, but incomplete (multi-step)
79
77
  * @throws AppError if authentication fails
80
78
  */
81
- authenticate(payload: T, ctx?: C): Promise<P | undefined> | P | undefined;
79
+ authenticate(payload: T, context?: C): Promise<P | undefined> | P | undefined;
82
80
  }
83
81
  ```
84
82
 
85
- The [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L8) only requires one method to be defined, and that is `authenticate`. This method receives a generic payload, and a supplemental context as an input. The interface is responsible for converting that to an authenticated principal.
83
+ The [Authenticator Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L14) only requires one method to be defined, and that is `authenticate`. This method receives a generic payload, and a supplemental context as an input. The interface is responsible for converting that to an authenticated principal.
86
84
 
87
85
  ### Example
88
86
  The [JWT](https://github.com/travetto/travetto/tree/main/module/jwt#readme "JSON Web Token implementation") module is a good example of an authenticator. This is a common use case for simple internal auth.
89
87
 
90
- ## Authorization
88
+ ## Authorization Contract
91
89
 
92
- **Code: Authorizer**
90
+ **Code: Authorizer Contract**
93
91
  ```typescript
94
92
  export interface Authorizer<P extends Principal = Principal> {
95
93
  /**
96
94
  * Authorize inbound principal, verifying it's permission to access the system.
97
- * @param principal
98
95
  * @returns New principal that conforms to the required principal shape
99
96
  */
100
- authorize(principal: Principal): Promise<P> | P;
97
+ authorize(principal: P): Promise<P> | P;
101
98
  }
102
99
  ```
103
100
 
104
101
  Authorizers are generally seen as a secondary step post-authentication. Authentication acts as a very basic form of authorization, assuming the principal store is owned by the application.
105
102
 
106
- The [Authorizer](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) only requires one method to be defined, and that is `authorizer`. This method receives an authenticated principal as an input, and is responsible for converting that to an authorized principal.
103
+ The [Authorizer Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) only requires one method to be defined, and that is `authorizer`. This method receives an authenticated principal as an input, and is responsible for converting that to an authorized principal.
107
104
 
108
105
  ### Example
109
106
  The [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") extension is a good example of an authenticator. This is a common use case for simple internal auth.
@@ -113,48 +110,84 @@ Overall, the structure is simple, but drives home the primary use cases of the f
113
110
  * To have a reference to a user's set of permissions
114
111
  * To have access to the principal
115
112
 
116
- ## Common Utilities
117
- The [AuthUtil](https://github.com/travetto/travetto/tree/main/module/auth/src/util.ts#L11) provides the following functionality:
113
+ ## Authorization Services
118
114
 
119
- **Code: Auth util structure**
115
+ **Code: Authorization Service**
120
116
  ```typescript
121
- import crypto from 'node:crypto';
122
- import util from 'node:util';
123
- import { AppError, Util } from '@travetto/runtime';
124
- const pbkdf2 = util.promisify(crypto.pbkdf2);
125
- /**
126
- * Standard auth utilities
127
- */
128
- export class AuthUtil {
129
- /**
130
- * Generate a hash for a given value
131
- *
132
- * @param value Value to hash
133
- * @param salt The salt value
134
- * @param iterations Number of iterations on hashing
135
- * @param keylen Length of hash
136
- * @param digest Digest method
117
+ export class AuthService {
118
+ @Inject()
119
+ /**
120
+ * Get authenticators by keys
137
121
  */
138
- static generateHash(value: string, salt: string, iterations = 25000, keylen = 256, digest = 'sha256'): Promise<string>;
122
+ async getAuthenticators<T = unknown, C = unknown>(keys: symbol[]): Promise<Authenticator<T, C>[]>;
139
123
  /**
140
- * Generate a salted password, with the ability to validate the password
141
- *
142
- * @param password
143
- * @param salt Salt value, or if a number, length of salt
144
- * @param validator Optional function to validate your password
124
+ * Authenticate. Supports multi-step login.
125
+ * @param ctx The authenticator context
126
+ * @param authenticators List of valid authentication sources
127
+ */
128
+ async authenticate<T, C>(payload: T, context: C, authenticators: symbol[]): Promise<Principal | undefined>;
129
+ /**
130
+ * Manage expiry state, renewing if allowed
145
131
  */
146
- static async generatePassword(password: string, salt: number | string = 32): Promise<{ salt: string, hash: string }>;
132
+ manageExpiry(p?: Principal): void;
133
+ /**
134
+ * Enforce expiry, invalidating the principal if expired
135
+ */
136
+ enforceExpiry(p?: Principal): Principal | undefined;
147
137
  }
148
138
  ```
149
139
 
150
- `roleMatcher` is probably the only functionality that needs to be explained. The function extends the core allow/deny matcher functionality from [Runtime](https://github.com/travetto/travetto/tree/main/module/runtime#readme "Runtime for travetto applications.")'s Util class.
151
-
152
- An example of role checks could be:
153
- * Admin
154
- * !Editor
155
- * Owner+Author
156
- The code would check the list in order, which would result in the following logic:
157
- * If the user is an admin, always allow
158
- * If the user has the editor role, deny
159
- * If the user is both an owner and an author allow
160
- * By default, deny due to the presence of positive checks
140
+ The [AuthService](https://github.com/travetto/travetto/tree/main/module/auth/src/service.ts#L14) operates as the owner of the current auth state for a given "request". "Request" here implies a set of operations over a period of time, with the http request/response model being an easy point of reference. This could also tie to a CLI operation, or any other invocation that requires some concept of authentication and authorization.
141
+
142
+ The service allows for storing and retrieving the active [Principal Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L8), and/or the actively persisted auth token. This is extremely useful for other parts of the framework that may request authenticated information (if available). [Rest Auth](https://github.com/travetto/travetto/tree/main/module/auth-rest#readme "Rest authentication integration support for the Travetto framework") makes heavy use of this state for enforcing routes when authentication is required.
143
+
144
+ ### Login
145
+ "Logging in" can be thought of going through the action of finding a single source that can authenticate the identity for the request credentials. Some times there may be more than one valid source of authentication that you want to leverage, and the first one to authenticate wins. The [AuthService](https://github.com/travetto/travetto/tree/main/module/auth/src/service.ts#L14) operates in this fashion, in which a set of credentials and potential [Authenticator Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L14)s are submitted, and the service will attempt to authenticate.
146
+
147
+ Upon successful authentication, an optional [Authorizer Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) may be invoked to authorize the authenticated user. The [Authenticator Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L14) is assumed to be only one within the system, and should be tied to the specific product you are building for. The [Authorizer Contract](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) should be assumed to have multiple sources, and are generally specific to external third parties. All of these values are collected via the [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support.") module and will be auto-registered on startup.
148
+
149
+ If this process is too cumbersome or restrictive, manually authenticating and authorizing is still more than permissible, and setting the principal within the service is a logical equivalent to login.
150
+
151
+ ## Authorization Context
152
+ When working with framework's authentication, the authenticated information is exposed via the [AuthContext](https://github.com/travetto/travetto/tree/main/module/auth/src/context.ts#L16), object.
153
+
154
+ **Code: Auth Context Outline**
155
+ ```typescript
156
+ type AuthContextShape = {
157
+ principal?: Principal;
158
+ authToken?: AuthToken;
159
+ authenticatorState?: AuthenticatorState;
160
+ };
161
+ @Injectable()
162
+ export class AuthContext {
163
+ @Inject()
164
+ /**
165
+ * Get the principal, if set
166
+ */
167
+ get principal(): Principal | undefined;
168
+ /**
169
+ * Set principal
170
+ */
171
+ set principal(p: Principal | undefined);
172
+ /**
173
+ * Get the authentication token, if it exists
174
+ */
175
+ get authToken(): AuthToken | undefined;
176
+ /**
177
+ * Set/overwrite the user's authentication token
178
+ */
179
+ set authToken(token: AuthToken | undefined);
180
+ /**
181
+ * Get the authenticator state, if it exists
182
+ */
183
+ get authenticatorState(): AuthenticatorState | undefined;
184
+ /**
185
+ * Set/overwrite the authenticator state
186
+ */
187
+ set authenticatorState(state: AuthenticatorState | undefined);
188
+ /**
189
+ * Clear context
190
+ */
191
+ async clear(): Promise<void>;
192
+ }
193
+ ```
package/__index__.ts CHANGED
@@ -1,5 +1,8 @@
1
- export * from './src/util';
1
+ export * from './src/service';
2
+ export * from './src/context';
3
+ export * from './src/config';
2
4
  export * from './src/types/authenticator';
3
5
  export * from './src/types/authorizer';
4
6
  export * from './src/types/principal';
5
- export * from './src/types/error';
7
+ export * from './src/types/error';
8
+ export * from './src/types/token';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/auth",
3
- "version": "5.0.16",
3
+ "version": "6.0.0-rc.0",
4
4
  "description": "Authentication scaffolding for the Travetto framework",
5
5
  "keywords": [
6
6
  "authentication",
@@ -23,7 +23,7 @@
23
23
  "directory": "module/auth"
24
24
  },
25
25
  "dependencies": {
26
- "@travetto/runtime": "^5.0.16"
26
+ "@travetto/context": "^6.0.0-rc.0"
27
27
  },
28
28
  "travetto": {
29
29
  "displayName": "Authentication"
package/src/config.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { Config } from '@travetto/config';
2
+ import { TimeSpan, TimeUtil } from '@travetto/runtime';
3
+ import { Ignore } from '@travetto/schema';
4
+
5
+ @Config('auth')
6
+ export class AuthConfig {
7
+
8
+ maxAge: TimeSpan | number = '1h';
9
+ rollingRenew: boolean = true;
10
+
11
+ @Ignore()
12
+ maxAgeMs: number;
13
+
14
+ postConstruct(): void {
15
+ this.maxAgeMs = TimeUtil.asMillis(this.maxAge);
16
+ }
17
+ }
package/src/context.ts ADDED
@@ -0,0 +1,80 @@
1
+
2
+ import { Inject, Injectable } from '@travetto/di';
3
+ import { AsyncContext, AsyncContextValue } from '@travetto/context';
4
+
5
+ import { AuthToken } from './types/token';
6
+ import { Principal } from './types/principal';
7
+ import { AuthenticatorState } from './types/authenticator';
8
+
9
+ type AuthContextShape = {
10
+ principal?: Principal;
11
+ authToken?: AuthToken;
12
+ authenticatorState?: AuthenticatorState;
13
+ };
14
+
15
+ @Injectable()
16
+ export class AuthContext {
17
+
18
+ #value = new AsyncContextValue<AuthContextShape>(this);
19
+
20
+ @Inject()
21
+ context: AsyncContext;
22
+
23
+ /**
24
+ * Initialize context
25
+ * @private
26
+ */
27
+ init(): void {
28
+ this.#value.set({});
29
+ }
30
+
31
+ /**
32
+ * Get the principal, if set
33
+ */
34
+ get principal(): Principal | undefined {
35
+ return this.#value.get()?.principal;
36
+ }
37
+
38
+ /**
39
+ * Set principal
40
+ */
41
+ set principal(p: Principal | undefined) {
42
+ this.#value.get()!.principal = p;
43
+ }
44
+
45
+ /**
46
+ * Get the authentication token, if it exists
47
+ */
48
+ get authToken(): AuthToken | undefined {
49
+ return this.#value.get()?.authToken;
50
+ }
51
+
52
+ /**
53
+ * Set/overwrite the user's authentication token
54
+ */
55
+ set authToken(token: AuthToken | undefined) {
56
+ this.#value.get()!.authToken = token;
57
+ }
58
+
59
+ /**
60
+ * Get the authenticator state, if it exists
61
+ */
62
+ get authenticatorState(): AuthenticatorState | undefined {
63
+ return this.#value.get()?.authenticatorState;
64
+ }
65
+
66
+ /**
67
+ * Set/overwrite the authenticator state
68
+ */
69
+ set authenticatorState(state: AuthenticatorState | undefined) {
70
+ this.#value.get()!.authenticatorState = state;
71
+ }
72
+
73
+ /**
74
+ * Clear context
75
+ * @private
76
+ */
77
+ async clear(): Promise<void> {
78
+ this.#value.set(undefined);
79
+ }
80
+ }
@@ -9,4 +9,3 @@ export class PrincipalTarget {
9
9
  }
10
10
  export class AuthorizerTarget { }
11
11
  export class AuthenticatorTarget { }
12
- export class PrincipalSerializerTarget { }
package/src/service.ts ADDED
@@ -0,0 +1,114 @@
1
+
2
+ import { DependencyRegistry, Inject, Injectable } from '@travetto/di';
3
+ import { TimeUtil } from '@travetto/runtime';
4
+
5
+ import { AuthenticatorTarget } from './internal/types';
6
+ import { Principal } from './types/principal';
7
+ import { Authenticator } from './types/authenticator';
8
+ import { Authorizer } from './types/authorizer';
9
+ import { AuthenticationError } from './types/error';
10
+ import { AuthContext } from './context';
11
+ import { AuthConfig } from './config';
12
+
13
+ @Injectable()
14
+ export class AuthService {
15
+
16
+ @Inject()
17
+ authContext: AuthContext;
18
+
19
+ @Inject()
20
+ config: AuthConfig;
21
+
22
+ #authenticators = new Map<symbol, Promise<Authenticator>>();
23
+
24
+ @Inject()
25
+ authorizer?: Authorizer;
26
+
27
+ async postConstruct(): Promise<void> {
28
+ // Find all authenticators
29
+ for (const source of DependencyRegistry.getCandidateTypes(AuthenticatorTarget)) {
30
+ const dep = DependencyRegistry.getInstance<Authenticator>(AuthenticatorTarget, source.qualifier);
31
+ this.#authenticators.set(source.qualifier, dep);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Get authenticators by keys
37
+ */
38
+ async getAuthenticators<T = unknown, C = unknown>(keys: symbol[]): Promise<Authenticator<T, C>[]> {
39
+ return await Promise.all(keys.map(key => this.#authenticators.get(key)!));
40
+ }
41
+
42
+ /**
43
+ * Authenticate. Supports multi-step login.
44
+ * @param ctx The authenticator context
45
+ * @param authenticators List of valid authentication sources
46
+ */
47
+ async authenticate<T, C>(payload: T, context: C, authenticators: symbol[]): Promise<Principal | undefined> {
48
+ let lastError: Error | undefined;
49
+
50
+ /**
51
+ * Attempt to authenticate, checking with multiple authentication sources
52
+ */
53
+ for (const idp of await this.getAuthenticators<T, C>(authenticators)) {
54
+ try {
55
+ const principal = await idp.authenticate(payload, context);
56
+
57
+ if (idp.getState) {
58
+ this.authContext.authenticatorState = await idp.getState(context);
59
+ }
60
+
61
+ if (!principal) { // Multi-step login process
62
+ return;
63
+ }
64
+ return this.authContext.principal = (await this.authorizer?.authorize(principal)) ?? principal;
65
+ } catch (err) {
66
+ if (!(err instanceof Error)) {
67
+ throw err;
68
+ }
69
+ lastError = err;
70
+ }
71
+ }
72
+
73
+ if (lastError) {
74
+ console.warn('Failed to authenticate', { error: lastError, sources: authenticators.map(x => x.toString()) });
75
+ }
76
+
77
+ // Take the last error and return
78
+ throw new AuthenticationError('Unable to authenticate', { cause: lastError });
79
+ }
80
+
81
+ /**
82
+ * Manage expiry state, renewing if allowed
83
+ */
84
+ manageExpiry(p?: Principal): void {
85
+ if (!p) {
86
+ return;
87
+ }
88
+
89
+ if (this.config.maxAgeMs) {
90
+ p.expiresAt ??= TimeUtil.fromNow(this.config.maxAgeMs);
91
+ }
92
+
93
+ p.issuedAt ??= new Date();
94
+
95
+ if (p.expiresAt && this.config.maxAgeMs && this.config.rollingRenew) { // Session behavior
96
+ const end = p.expiresAt.getTime();
97
+ const midPoint = end - this.config.maxAgeMs / 2;
98
+ if (Date.now() > midPoint) { // If we are past the half way mark, renew the token
99
+ p.issuedAt = new Date();
100
+ p.expiresAt = TimeUtil.fromNow(this.config.maxAgeMs); // This will trigger a re-send
101
+ }
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Enforce expiry, invalidating the principal if expired
107
+ */
108
+ enforceExpiry(p?: Principal): Principal | undefined {
109
+ if (p && p.expiresAt && p.expiresAt.getTime() < Date.now()) {
110
+ return undefined;
111
+ }
112
+ return p;
113
+ }
114
+ }
@@ -1,16 +1,21 @@
1
+ import { AnyMap } from '@travetto/runtime';
1
2
  import { Principal } from './principal';
2
3
 
4
+ /**
5
+ * Represents the general shape of additional login context, usually across multiple calls
6
+ */
7
+ export interface AuthenticatorState extends AnyMap { }
8
+
3
9
  /**
4
10
  * Supports validation payload of type T into an authenticated principal
5
11
  *
6
12
  * @concrete ../internal/types#AuthenticatorTarget
7
13
  */
8
- export interface Authenticator<T = unknown, P extends Principal = Principal, C = unknown> {
14
+ export interface Authenticator<T = unknown, C = unknown, P extends Principal = Principal> {
9
15
  /**
10
- * Allows for the authenticator to be initialized if needed
11
- * @param ctx
16
+ * Retrieve the authenticator state for the given request
12
17
  */
13
- initialize?(ctx: C): Promise<void>;
18
+ getState?(context?: C): Promise<AuthenticatorState | undefined> | AuthenticatorState | undefined;
14
19
 
15
20
  /**
16
21
  * Verify the payload, ensuring the payload is correctly identified.
@@ -19,5 +24,5 @@ export interface Authenticator<T = unknown, P extends Principal = Principal, C =
19
24
  * @returns undefined if authentication is valid, but incomplete (multi-step)
20
25
  * @throws AppError if authentication fails
21
26
  */
22
- authenticate(payload: T, ctx?: C): Promise<P | undefined> | P | undefined;
27
+ authenticate(payload: T, context?: C): Promise<P | undefined> | P | undefined;
23
28
  }
@@ -8,8 +8,7 @@ import { Principal } from './principal';
8
8
  export interface Authorizer<P extends Principal = Principal> {
9
9
  /**
10
10
  * Authorize inbound principal, verifying it's permission to access the system.
11
- * @param principal
12
11
  * @returns New principal that conforms to the required principal shape
13
12
  */
14
- authorize(principal: Principal): Promise<P> | P;
13
+ authorize(principal: P): Promise<P> | P;
15
14
  }
@@ -2,14 +2,18 @@ import { AnyMap } from '@travetto/runtime';
2
2
 
3
3
  /**
4
4
  * A user principal, including permissions and details
5
- * @concrete ../internal/types#PrincipalTarget
6
5
  * @augments `@travetto/rest:Context`
6
+ * @concrete ../internal/types#PrincipalTarget
7
7
  */
8
8
  export interface Principal<D = AnyMap> {
9
9
  /**
10
10
  * Primary identifier for a user
11
11
  */
12
- id: string;
12
+ readonly id: string;
13
+ /**
14
+ * Unique identifier for the principal's lifecycle
15
+ */
16
+ readonly sessionId?: string;
13
17
  /**
14
18
  * Date of expiration
15
19
  */
@@ -18,20 +22,16 @@ export interface Principal<D = AnyMap> {
18
22
  * Date of issuance
19
23
  */
20
24
  issuedAt?: Date;
21
- /**
22
- * Max age in seconds a principal is valid
23
- */
24
- maxAge?: number;
25
25
  /**
26
26
  * The source of the issuance
27
27
  */
28
- issuer?: string;
28
+ readonly issuer?: string;
29
29
  /**
30
30
  * Supplemental details
31
31
  */
32
- details: D;
32
+ readonly details: D;
33
33
  /**
34
34
  * List of all provided permissions
35
35
  */
36
- permissions?: string[];
36
+ readonly permissions?: string[];
37
37
  }
@@ -0,0 +1 @@
1
+ export type AuthToken = { value: string, type: string };
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2020 ArcSine Technologies
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/src/util.ts DELETED
@@ -1,44 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import util from 'node:util';
3
-
4
- import { AppError, Util } from '@travetto/runtime';
5
-
6
- const pbkdf2 = util.promisify(crypto.pbkdf2);
7
-
8
- /**
9
- * Standard auth utilities
10
- */
11
- export class AuthUtil {
12
-
13
- /**
14
- * Generate a hash for a given value
15
- *
16
- * @param value Value to hash
17
- * @param salt The salt value
18
- * @param iterations Number of iterations on hashing
19
- * @param keylen Length of hash
20
- * @param digest Digest method
21
- */
22
- static generateHash(value: string, salt: string, iterations = 25000, keylen = 256, digest = 'sha256'): Promise<string> {
23
- const half = Math.trunc(Math.ceil(keylen / 2));
24
- return pbkdf2(value, salt, iterations, half, digest).then(x => x.toString('hex').substring(0, keylen));
25
- }
26
-
27
- /**
28
- * Generate a salted password, with the ability to validate the password
29
- *
30
- * @param password
31
- * @param salt Salt value, or if a number, length of salt
32
- * @param validator Optional function to validate your password
33
- */
34
- static async generatePassword(password: string, salt: number | string = 32): Promise<{ salt: string, hash: string }> {
35
- if (!password) {
36
- throw new AppError('Password is required', { category: 'data' });
37
- }
38
-
39
- salt = typeof salt === 'number' ? Util.uuid(salt) : salt;
40
- const hash = await this.generateHash(password, salt);
41
-
42
- return { salt, hash };
43
- }
44
- }