@travetto/auth 6.0.0-rc.0 → 6.0.0-rc.2
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 +12 -25
- package/__index__.ts +8 -8
- package/package.json +2 -2
- package/src/context.ts +20 -26
- package/src/service.ts +9 -9
- package/src/types/authenticator.ts +4 -2
- package/src/types/authorizer.ts +2 -2
- package/src/types/principal.ts +1 -2
- package/src/types/token.ts +8 -1
- package/src/internal/types.ts +0 -11
package/README.md
CHANGED
|
@@ -21,9 +21,9 @@ This module provides the high-level backdrop for managing security principals.
|
|
|
21
21
|
* Authorization Context
|
|
22
22
|
|
|
23
23
|
## Standard Types
|
|
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
|
|
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](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L7).
|
|
25
25
|
|
|
26
|
-
**Code: Principal
|
|
26
|
+
**Code: Principal**
|
|
27
27
|
```typescript
|
|
28
28
|
export interface Principal<D = AnyMap> {
|
|
29
29
|
/**
|
|
@@ -57,11 +57,11 @@ export interface Principal<D = AnyMap> {
|
|
|
57
57
|
}
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
As referenced above, a [Principal
|
|
60
|
+
As referenced above, a [Principal](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L7) 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).
|
|
61
61
|
|
|
62
62
|
## Authentication Contract
|
|
63
63
|
|
|
64
|
-
**Code: Authenticator
|
|
64
|
+
**Code: Authenticator**
|
|
65
65
|
```typescript
|
|
66
66
|
export interface Authenticator<T = unknown, C = unknown, P extends Principal = Principal> {
|
|
67
67
|
/**
|
|
@@ -80,14 +80,11 @@ export interface Authenticator<T = unknown, C = unknown, P extends Principal = P
|
|
|
80
80
|
}
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
The [Authenticator
|
|
84
|
-
|
|
85
|
-
### Example
|
|
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.
|
|
83
|
+
The [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L9) 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.
|
|
87
84
|
|
|
88
85
|
## Authorization Contract
|
|
89
86
|
|
|
90
|
-
**Code: Authorizer
|
|
87
|
+
**Code: Authorizer**
|
|
91
88
|
```typescript
|
|
92
89
|
export interface Authorizer<P extends Principal = Principal> {
|
|
93
90
|
/**
|
|
@@ -100,7 +97,7 @@ export interface Authorizer<P extends Principal = Principal> {
|
|
|
100
97
|
|
|
101
98
|
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.
|
|
102
99
|
|
|
103
|
-
The [Authorizer
|
|
100
|
+
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 `authorize`. This method receives an authenticated principal as an input, and is responsible for converting that to an authorized principal.
|
|
104
101
|
|
|
105
102
|
### Example
|
|
106
103
|
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.
|
|
@@ -137,34 +134,24 @@ export class AuthService {
|
|
|
137
134
|
}
|
|
138
135
|
```
|
|
139
136
|
|
|
140
|
-
The [AuthService](https://github.com/travetto/travetto/tree/main/module/auth/src/service.ts#
|
|
137
|
+
The [AuthService](https://github.com/travetto/travetto/tree/main/module/auth/src/service.ts#L13) 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
138
|
|
|
142
|
-
The service allows for storing and retrieving the active [Principal
|
|
139
|
+
The service allows for storing and retrieving the active [Principal](https://github.com/travetto/travetto/tree/main/module/auth/src/types/principal.ts#L7), and/or the actively persisted auth token. This is extremely useful for other parts of the framework that may request authenticated information (if available). [Web Auth](https://github.com/travetto/travetto/tree/main/module/auth-web#readme "Web authentication integration support for the Travetto framework") makes heavy use of this state for enforcing endpoints when authentication is required.
|
|
143
140
|
|
|
144
141
|
### 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#
|
|
142
|
+
"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#L13) operates in this fashion, in which a set of credentials and potential [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L9)s are submitted, and the service will attempt to authenticate.
|
|
146
143
|
|
|
147
|
-
Upon successful authentication, an optional [Authorizer
|
|
144
|
+
Upon successful authentication, an optional [Authorizer](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authorizer.ts#L8) may be invoked to authorize the authenticated user. The [Authenticator](https://github.com/travetto/travetto/tree/main/module/auth/src/types/authenticator.ts#L9) is assumed to be only one within the system, and should be tied to the specific product you are building for. The [Authorizer](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
145
|
|
|
149
146
|
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
147
|
|
|
151
148
|
## 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#
|
|
149
|
+
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#L14), object.
|
|
153
150
|
|
|
154
151
|
**Code: Auth Context Outline**
|
|
155
152
|
```typescript
|
|
156
|
-
type AuthContextShape = {
|
|
157
|
-
principal?: Principal;
|
|
158
|
-
authToken?: AuthToken;
|
|
159
|
-
authenticatorState?: AuthenticatorState;
|
|
160
|
-
};
|
|
161
|
-
@Injectable()
|
|
162
153
|
export class AuthContext {
|
|
163
154
|
@Inject()
|
|
164
|
-
/**
|
|
165
|
-
* Get the principal, if set
|
|
166
|
-
*/
|
|
167
|
-
get principal(): Principal | undefined;
|
|
168
155
|
/**
|
|
169
156
|
* Set principal
|
|
170
157
|
*/
|
package/__index__.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from './src/service';
|
|
2
|
-
export * from './src/context';
|
|
3
|
-
export * from './src/config';
|
|
4
|
-
export * from './src/types/authenticator';
|
|
5
|
-
export * from './src/types/authorizer';
|
|
6
|
-
export * from './src/types/principal';
|
|
7
|
-
export * from './src/types/error';
|
|
8
|
-
export * from './src/types/token';
|
|
1
|
+
export * from './src/service.ts';
|
|
2
|
+
export * from './src/context.ts';
|
|
3
|
+
export * from './src/config.ts';
|
|
4
|
+
export * from './src/types/authenticator.ts';
|
|
5
|
+
export * from './src/types/authorizer.ts';
|
|
6
|
+
export * from './src/types/principal.ts';
|
|
7
|
+
export * from './src/types/error.ts';
|
|
8
|
+
export * from './src/types/token.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/auth",
|
|
3
|
-
"version": "6.0.0-rc.
|
|
3
|
+
"version": "6.0.0-rc.2",
|
|
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/context": "^6.0.0-rc.
|
|
26
|
+
"@travetto/context": "^6.0.0-rc.2"
|
|
27
27
|
},
|
|
28
28
|
"travetto": {
|
|
29
29
|
"displayName": "Authentication"
|
package/src/context.ts
CHANGED
|
@@ -1,73 +1,65 @@
|
|
|
1
|
-
|
|
2
1
|
import { Inject, Injectable } from '@travetto/di';
|
|
3
2
|
import { AsyncContext, AsyncContextValue } from '@travetto/context';
|
|
4
3
|
|
|
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
|
-
};
|
|
4
|
+
import { AuthToken } from './types/token.ts';
|
|
5
|
+
import { Principal } from './types/principal.ts';
|
|
6
|
+
import { AuthenticatorState } from './types/authenticator.ts';
|
|
14
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Provides the primary context for the authenticated state
|
|
10
|
+
*
|
|
11
|
+
* Will silently fail on reads, but will error on writes if the context is not established.
|
|
12
|
+
*/
|
|
15
13
|
@Injectable()
|
|
16
14
|
export class AuthContext {
|
|
17
15
|
|
|
18
|
-
#
|
|
16
|
+
#principal = new AsyncContextValue<Principal>(this, { failIfUnbound: { write: true } });
|
|
17
|
+
#authToken = new AsyncContextValue<AuthToken>(this, { failIfUnbound: { write: true } });
|
|
18
|
+
#authState = new AsyncContextValue<AuthenticatorState>(this, { failIfUnbound: { write: true } });
|
|
19
19
|
|
|
20
20
|
@Inject()
|
|
21
21
|
context: AsyncContext;
|
|
22
22
|
|
|
23
|
-
/**
|
|
24
|
-
* Initialize context
|
|
25
|
-
* @private
|
|
26
|
-
*/
|
|
27
|
-
init(): void {
|
|
28
|
-
this.#value.set({});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
23
|
/**
|
|
32
24
|
* Get the principal, if set
|
|
33
25
|
*/
|
|
34
26
|
get principal(): Principal | undefined {
|
|
35
|
-
return this.#
|
|
27
|
+
return this.#principal.get();
|
|
36
28
|
}
|
|
37
29
|
|
|
38
30
|
/**
|
|
39
31
|
* Set principal
|
|
40
32
|
*/
|
|
41
33
|
set principal(p: Principal | undefined) {
|
|
42
|
-
this.#
|
|
34
|
+
this.#principal.set(p);
|
|
43
35
|
}
|
|
44
36
|
|
|
45
37
|
/**
|
|
46
38
|
* Get the authentication token, if it exists
|
|
47
39
|
*/
|
|
48
40
|
get authToken(): AuthToken | undefined {
|
|
49
|
-
return this.#
|
|
41
|
+
return this.#authToken.get();
|
|
50
42
|
}
|
|
51
43
|
|
|
52
44
|
/**
|
|
53
45
|
* Set/overwrite the user's authentication token
|
|
54
46
|
*/
|
|
55
47
|
set authToken(token: AuthToken | undefined) {
|
|
56
|
-
this.#
|
|
48
|
+
this.#authToken.set(token);
|
|
57
49
|
}
|
|
58
50
|
|
|
59
51
|
/**
|
|
60
52
|
* Get the authenticator state, if it exists
|
|
61
53
|
*/
|
|
62
54
|
get authenticatorState(): AuthenticatorState | undefined {
|
|
63
|
-
return this.#
|
|
55
|
+
return this.#authState.get();
|
|
64
56
|
}
|
|
65
57
|
|
|
66
58
|
/**
|
|
67
59
|
* Set/overwrite the authenticator state
|
|
68
60
|
*/
|
|
69
61
|
set authenticatorState(state: AuthenticatorState | undefined) {
|
|
70
|
-
this.#
|
|
62
|
+
this.#authState.set(state);
|
|
71
63
|
}
|
|
72
64
|
|
|
73
65
|
/**
|
|
@@ -75,6 +67,8 @@ export class AuthContext {
|
|
|
75
67
|
* @private
|
|
76
68
|
*/
|
|
77
69
|
async clear(): Promise<void> {
|
|
78
|
-
this.#
|
|
70
|
+
this.#principal.set(undefined);
|
|
71
|
+
this.#authToken.set(undefined);
|
|
72
|
+
this.#authState.set(undefined);
|
|
79
73
|
}
|
|
80
74
|
}
|
package/src/service.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
import { DependencyRegistry, Inject, Injectable } from '@travetto/di';
|
|
3
|
-
import { TimeUtil } from '@travetto/runtime';
|
|
3
|
+
import { toConcrete, TimeUtil } from '@travetto/runtime';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { AuthConfig } from './config';
|
|
5
|
+
import { Principal } from './types/principal.ts';
|
|
6
|
+
import { Authenticator } from './types/authenticator.ts';
|
|
7
|
+
import { Authorizer } from './types/authorizer.ts';
|
|
8
|
+
import { AuthenticationError } from './types/error.ts';
|
|
9
|
+
import { AuthContext } from './context.ts';
|
|
10
|
+
import { AuthConfig } from './config.ts';
|
|
12
11
|
|
|
13
12
|
@Injectable()
|
|
14
13
|
export class AuthService {
|
|
@@ -26,8 +25,9 @@ export class AuthService {
|
|
|
26
25
|
|
|
27
26
|
async postConstruct(): Promise<void> {
|
|
28
27
|
// Find all authenticators
|
|
28
|
+
const AuthenticatorTarget = toConcrete<Authenticator>();
|
|
29
29
|
for (const source of DependencyRegistry.getCandidateTypes(AuthenticatorTarget)) {
|
|
30
|
-
const dep = DependencyRegistry.getInstance
|
|
30
|
+
const dep = DependencyRegistry.getInstance(AuthenticatorTarget, source.qualifier);
|
|
31
31
|
this.#authenticators.set(source.qualifier, dep);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { AnyMap } from '@travetto/runtime';
|
|
2
|
-
import { Principal } from './principal';
|
|
2
|
+
import { Principal } from './principal.ts';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Represents the general shape of additional login context, usually across multiple calls
|
|
6
|
+
*
|
|
7
|
+
* @concrete
|
|
6
8
|
*/
|
|
7
9
|
export interface AuthenticatorState extends AnyMap { }
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Supports validation payload of type T into an authenticated principal
|
|
11
13
|
*
|
|
12
|
-
* @concrete
|
|
14
|
+
* @concrete
|
|
13
15
|
*/
|
|
14
16
|
export interface Authenticator<T = unknown, C = unknown, P extends Principal = Principal> {
|
|
15
17
|
/**
|
package/src/types/authorizer.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Principal } from './principal';
|
|
1
|
+
import { Principal } from './principal.ts';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Definition of an authorization source, which validates a principal into an authorized principal
|
|
5
5
|
*
|
|
6
|
-
* @concrete
|
|
6
|
+
* @concrete
|
|
7
7
|
*/
|
|
8
8
|
export interface Authorizer<P extends Principal = Principal> {
|
|
9
9
|
/**
|
package/src/types/principal.ts
CHANGED
package/src/types/token.ts
CHANGED
package/src/internal/types.ts
DELETED