@antelopejs/interface-auth 0.0.4 → 0.0.6
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/docs/1.introduction.md +27 -0
- package/docs/2.authentication.md +169 -0
- package/docs/3.token-handling.md +129 -0
- package/docs/4.parameter-decoration.md +172 -0
- package/package.json +14 -7
- package/skills/auth-interface/SKILL.md +83 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Interface Auth Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Interface Auth provides a decorator-based framework for implementing authentication and authorization in TypeScript applications. It offers token signing, verification, and flexible parameter decorators for securing API endpoints.
|
|
6
|
+
|
|
7
|
+
This interface depends on the [Interface API](https://github.com/AntelopeJS/interface-api) package, which provides the decorator infrastructure for parameter injection.
|
|
8
|
+
|
|
9
|
+
## Core concepts
|
|
10
|
+
|
|
11
|
+
The authentication system is built around three main layers:
|
|
12
|
+
|
|
13
|
+
- **Token handling** - Sign and verify authentication tokens using `SignRaw`, `ValidateRaw`, and `SignServerResponse`.
|
|
14
|
+
- **Authentication decorators** - The `@Authentication` decorator and `CreateAuthDecorator` function inject verified user data into handler parameters.
|
|
15
|
+
- **Customizable pipeline** - Configure custom sources, verifiers, and validators to adapt the authentication flow.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @antelopejs/interface-auth
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Documentation sections
|
|
24
|
+
|
|
25
|
+
- [Authentication Basics](./2.authentication.md) - Authentication flow, sources, verifiers, and validators
|
|
26
|
+
- [Token Handling](./3.token-handling.md) - Token generation and validation functions
|
|
27
|
+
- [Parameter Decoration](./4.parameter-decoration.md) - Authentication decorators and custom providers
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Authentication Basics
|
|
2
|
+
|
|
3
|
+
Authentication verifies the identity of users or systems accessing your API. The Interface Auth provides a complete system for token-based authentication with customizable sources, verifiers, and validators.
|
|
4
|
+
|
|
5
|
+
## Authentication flow
|
|
6
|
+
|
|
7
|
+
A typical authentication flow consists of four steps:
|
|
8
|
+
|
|
9
|
+
1. **Token generation** - Sign user data into a token using `SignRaw` or `SignServerResponse`.
|
|
10
|
+
2. **Token storage** - Store the token on the client (cookie, header, local storage).
|
|
11
|
+
3. **Token validation** - Verify the token when the client makes a request.
|
|
12
|
+
4. **Authorization** - Check whether the authenticated user has permission to access the requested resource.
|
|
13
|
+
|
|
14
|
+
### Example authentication flow
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { SignRaw, Authentication } from "@antelopejs/interface-auth";
|
|
18
|
+
import { Controller, Post, Get, JSONBody, HTTPResult } from "@antelopejs/interface-api";
|
|
19
|
+
|
|
20
|
+
class UserController extends Controller("/users") {
|
|
21
|
+
@Post("login")
|
|
22
|
+
async login(@JSONBody() credentials: { email: string; password: string }) {
|
|
23
|
+
// Validate credentials against your data store
|
|
24
|
+
const user = await validateUserCredentials(credentials);
|
|
25
|
+
|
|
26
|
+
// Step 1: Generate a token
|
|
27
|
+
const token = await SignRaw(
|
|
28
|
+
{ userId: user.id, role: user.role },
|
|
29
|
+
{ expiresIn: "1h" },
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Step 2: Return token to the client
|
|
33
|
+
const result = new HTTPResult(200, {
|
|
34
|
+
success: true,
|
|
35
|
+
user: { id: user.id, role: user.role },
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
result.addHeader(
|
|
39
|
+
"Set-Cookie",
|
|
40
|
+
`ANTELOPEJS_AUTH=${token}; HttpOnly; Path=/`,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Get("profile")
|
|
47
|
+
async getProfile(
|
|
48
|
+
@Authentication() userData: { userId: number; role: string },
|
|
49
|
+
) {
|
|
50
|
+
// Steps 3 & 4: Token is automatically validated
|
|
51
|
+
// If the token is invalid, an error is thrown before this code runs
|
|
52
|
+
return { user: await getUserProfile(userData.userId) };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Authentication sources
|
|
58
|
+
|
|
59
|
+
An `AuthSource` function extracts the authentication token from the incoming HTTP request. The default source checks two locations in order:
|
|
60
|
+
|
|
61
|
+
1. **Custom header** - The `x-antelopejs-auth` header
|
|
62
|
+
2. **Cookie** - The `ANTELOPEJS_AUTH` cookie
|
|
63
|
+
|
|
64
|
+
### Create a custom source
|
|
65
|
+
|
|
66
|
+
Implement the `AuthSource` type to extract tokens from a different location.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { CreateAuthDecorator, AuthSource } from "@antelopejs/interface-auth";
|
|
70
|
+
import type { IncomingMessage } from "node:http";
|
|
71
|
+
|
|
72
|
+
const bearerTokenSource: AuthSource = (req: IncomingMessage) => {
|
|
73
|
+
const header = req.headers.authorization;
|
|
74
|
+
if (header?.startsWith("Bearer ")) {
|
|
75
|
+
return header.slice(7);
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const BearerAuth = CreateAuthDecorator({
|
|
81
|
+
source: bearerTokenSource,
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The `AuthSource` type signature is:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
type AuthSource = (
|
|
89
|
+
req: IncomingMessage,
|
|
90
|
+
res: ServerResponse,
|
|
91
|
+
) => string | undefined;
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Authentication verifiers
|
|
95
|
+
|
|
96
|
+
An `AuthVerifier` function validates the token and extracts its payload. The default verifier uses `ValidateRaw`, which delegates to the underlying token verification implementation (typically JWT).
|
|
97
|
+
|
|
98
|
+
### Create a custom verifier
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { CreateAuthDecorator, AuthVerifier } from "@antelopejs/interface-auth";
|
|
102
|
+
|
|
103
|
+
const base64Verifier: AuthVerifier<{ userId: string }> = (data?: string) => {
|
|
104
|
+
if (!data) {
|
|
105
|
+
throw new Error("No authentication data provided");
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const decoded = Buffer.from(data, "base64").toString("utf-8");
|
|
109
|
+
return JSON.parse(decoded);
|
|
110
|
+
} catch {
|
|
111
|
+
throw new Error("Invalid authentication data");
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const Base64Auth = CreateAuthDecorator({
|
|
116
|
+
authenticator: base64Verifier,
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The `AuthVerifier` type signature is:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
type AuthVerifier<T = unknown> = (
|
|
124
|
+
data?: string,
|
|
125
|
+
options?: VerifyOptions,
|
|
126
|
+
) => Promise<T> | T;
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Authentication validators
|
|
130
|
+
|
|
131
|
+
An `AuthValidator` function performs additional checks on the verified data. Validators run after the verifier and can transform the result or throw an error to reject the request.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { CreateAuthDecorator, AuthValidator } from "@antelopejs/interface-auth";
|
|
135
|
+
|
|
136
|
+
interface UserPayload {
|
|
137
|
+
userId: number;
|
|
138
|
+
role: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const adminValidator: AuthValidator<UserPayload, UserPayload> = (userData) => {
|
|
142
|
+
if (!userData || userData.role !== "admin") {
|
|
143
|
+
throw new Error("Admin access required");
|
|
144
|
+
}
|
|
145
|
+
return userData;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const AdminOnly = CreateAuthDecorator({
|
|
149
|
+
validator: adminValidator,
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The `AuthValidator` type signature is:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
type AuthValidator<T = unknown, R = unknown> = (
|
|
157
|
+
data: T,
|
|
158
|
+
) => Promise<R> | R;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Authentication pipeline
|
|
162
|
+
|
|
163
|
+
The complete authentication pipeline processes the request through three stages:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
source(req, res) => authenticator(token, options) => validator(data) => Parameter
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Each stage is optional and falls back to the default behavior when not specified. The `source` extracts the token, the `authenticator` verifies it, and the `validator` performs any additional checks before the data is injected into the handler parameter.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Token Handling
|
|
2
|
+
|
|
3
|
+
The Interface Auth provides functions for generating and validating authentication tokens. These functions serve as the foundation for the authentication system.
|
|
4
|
+
|
|
5
|
+
## Token generation
|
|
6
|
+
|
|
7
|
+
### `SignRaw`
|
|
8
|
+
|
|
9
|
+
The `SignRaw` function signs arbitrary data and returns a token string.
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { SignRaw } from "@antelopejs/interface-auth";
|
|
13
|
+
|
|
14
|
+
const token = await SignRaw(
|
|
15
|
+
{ userId: 123, role: "admin" },
|
|
16
|
+
{ expiresIn: "1h" },
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
console.log(token); // Signed token string
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The function accepts two arguments:
|
|
23
|
+
|
|
24
|
+
| Argument | Type | Description |
|
|
25
|
+
| --------- | -------------------------------- | ------------------------------ |
|
|
26
|
+
| `data` | `string \| Buffer \| object` | The data to sign |
|
|
27
|
+
| `options` | `SignOptions` (optional) | Signing configuration options |
|
|
28
|
+
|
|
29
|
+
`SignRaw` returns a `Promise<string>` that resolves to the signed token.
|
|
30
|
+
|
|
31
|
+
### `SignOptions`
|
|
32
|
+
|
|
33
|
+
The `SignOptions` interface configures token generation.
|
|
34
|
+
|
|
35
|
+
| Property | Type | Description |
|
|
36
|
+
| ----------- | ------------------ | ---------------------------------------------------------------------- |
|
|
37
|
+
| `expiresIn` | `string \| number` | Token expiration time as seconds or a timespan string (e.g., `"1h"`, `"2d"`) |
|
|
38
|
+
| `notBefore` | `string \| number` | Duration before which the token is not valid |
|
|
39
|
+
|
|
40
|
+
### `SignServerResponse`
|
|
41
|
+
|
|
42
|
+
The `SignServerResponse` function signs data and attaches the resulting token as a cookie on the HTTP response.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { SignServerResponse } from "@antelopejs/interface-auth";
|
|
46
|
+
import type { ServerResponse } from "node:http";
|
|
47
|
+
|
|
48
|
+
async function login(res: ServerResponse) {
|
|
49
|
+
const userData = { userId: 123, role: "user" };
|
|
50
|
+
|
|
51
|
+
await SignServerResponse(
|
|
52
|
+
res,
|
|
53
|
+
userData,
|
|
54
|
+
{ expiresIn: "1h" },
|
|
55
|
+
{ httpOnly: true, secure: true, path: "/" },
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The function accepts four arguments:
|
|
61
|
+
|
|
62
|
+
| Argument | Type | Description |
|
|
63
|
+
| --------------- | ----------------------------- | ---------------------------------- |
|
|
64
|
+
| `res` | `ServerResponse` | The HTTP response object |
|
|
65
|
+
| `data` | `string \| Buffer \| object` | The data to sign |
|
|
66
|
+
| `signOptions` | `SignOptions` (optional) | Signing configuration options |
|
|
67
|
+
| `cookieOptions` | `CookieOptions` (optional) | Cookie configuration options |
|
|
68
|
+
|
|
69
|
+
The cookie is set with the name `ANTELOPEJS_AUTH` and the signed token as its value. The function returns a `Promise<ServerResponse>` that resolves to the same response object once the cookie header has been set.
|
|
70
|
+
|
|
71
|
+
### `CookieOptions`
|
|
72
|
+
|
|
73
|
+
The `CookieOptions` interface configures the authentication cookie.
|
|
74
|
+
|
|
75
|
+
| Property | Type | Description |
|
|
76
|
+
| ---------- | --------- | ---------------------------------------------------------- |
|
|
77
|
+
| `maxAge` | `number` | Maximum age in milliseconds |
|
|
78
|
+
| `signed` | `boolean` | Whether the cookie should be signed |
|
|
79
|
+
| `expires` | `Date` | Specific date when the cookie expires |
|
|
80
|
+
| `httpOnly` | `boolean` | Prevents client-side JavaScript from accessing the cookie |
|
|
81
|
+
| `path` | `string` | URL path for which the cookie is valid |
|
|
82
|
+
| `domain` | `string` | Domain for which the cookie is valid |
|
|
83
|
+
| `secure` | `boolean` | Only sends the cookie over HTTPS |
|
|
84
|
+
|
|
85
|
+
## Token validation
|
|
86
|
+
|
|
87
|
+
### `ValidateRaw`
|
|
88
|
+
|
|
89
|
+
The `ValidateRaw` function verifies a token and returns the data contained within it.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { ValidateRaw } from "@antelopejs/interface-auth";
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const userData = await ValidateRaw<{ userId: number; role: string }>(token);
|
|
96
|
+
console.log(userData); // { userId: 123, role: "admin" }
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error("Invalid token:", error.message);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The function accepts two arguments:
|
|
103
|
+
|
|
104
|
+
| Argument | Type | Description |
|
|
105
|
+
| --------- | --------------- | -------------------------------- |
|
|
106
|
+
| `token` | `string` (optional) | The signed token to verify |
|
|
107
|
+
| `options` | `VerifyOptions` (optional) | Verification configuration |
|
|
108
|
+
|
|
109
|
+
### `VerifyOptions`
|
|
110
|
+
|
|
111
|
+
The `VerifyOptions` interface configures token validation.
|
|
112
|
+
|
|
113
|
+
| Property | Type | Description |
|
|
114
|
+
| ------------------ | ------------------ | ---------------------------------------------------- |
|
|
115
|
+
| `ignoreExpiration` | `boolean` | If `true`, expired tokens are still considered valid |
|
|
116
|
+
| `ignoreNotBefore` | `boolean` | If `true`, tokens not yet valid are accepted |
|
|
117
|
+
| `maxAge` | `string \| number` | Maximum allowed age of the token |
|
|
118
|
+
|
|
119
|
+
### Example with verify options
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { ValidateRaw } from "@antelopejs/interface-auth";
|
|
123
|
+
|
|
124
|
+
// Accept tokens up to 30 minutes old, ignoring the not-before field
|
|
125
|
+
const userData = await ValidateRaw(token, {
|
|
126
|
+
maxAge: "30m",
|
|
127
|
+
ignoreNotBefore: true,
|
|
128
|
+
});
|
|
129
|
+
```
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Parameter Decoration
|
|
2
|
+
|
|
3
|
+
The Interface Auth provides decorators for integrating authentication into API controllers. These decorators extract, verify, and inject authentication data into handler parameters, class properties, and entire controller classes.
|
|
4
|
+
|
|
5
|
+
## The `@Authentication` decorator
|
|
6
|
+
|
|
7
|
+
The `@Authentication` decorator retrieves and validates a token from the default sources (header or cookie) and injects the verified payload into the parameter.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { Controller, Get } from "@antelopejs/interface-api";
|
|
11
|
+
import { Authentication } from "@antelopejs/interface-auth";
|
|
12
|
+
|
|
13
|
+
class UserController extends Controller("/users") {
|
|
14
|
+
@Get("profile")
|
|
15
|
+
async getProfile(@Authentication() user: { id: string; name: string }) {
|
|
16
|
+
return {
|
|
17
|
+
id: user.id,
|
|
18
|
+
name: user.name,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If the token is missing or invalid, the request fails with an error response before the handler executes.
|
|
25
|
+
|
|
26
|
+
### Inline validators
|
|
27
|
+
|
|
28
|
+
Pass a validator function directly to the `@Authentication` decorator for one-off validation logic.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { Controller, Post } from "@antelopejs/interface-api";
|
|
32
|
+
import { Authentication } from "@antelopejs/interface-auth";
|
|
33
|
+
|
|
34
|
+
class PaymentController extends Controller("/payments") {
|
|
35
|
+
@Post()
|
|
36
|
+
async createPayment(
|
|
37
|
+
@Authentication((user: any) => {
|
|
38
|
+
if (!user.paymentPermissions) {
|
|
39
|
+
throw new Error("Payment permissions required");
|
|
40
|
+
}
|
|
41
|
+
return user;
|
|
42
|
+
})
|
|
43
|
+
user: any,
|
|
44
|
+
) {
|
|
45
|
+
// Process payment
|
|
46
|
+
return { success: true };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Create custom decorators with `CreateAuthDecorator`
|
|
52
|
+
|
|
53
|
+
The `CreateAuthDecorator` function creates a reusable authentication decorator with custom source, authenticator, and validator functions.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { CreateAuthDecorator } from "@antelopejs/interface-auth";
|
|
57
|
+
import type { IncomingMessage } from "node:http";
|
|
58
|
+
|
|
59
|
+
// Admin-only decorator
|
|
60
|
+
export const AdminAuth = CreateAuthDecorator({
|
|
61
|
+
validator: (user: any) => {
|
|
62
|
+
if (!user || user.role !== "admin") {
|
|
63
|
+
throw new Error("Admin access required");
|
|
64
|
+
}
|
|
65
|
+
return user;
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// API key decorator with custom source and authenticator
|
|
70
|
+
export const ApiKeyAuth = CreateAuthDecorator({
|
|
71
|
+
source: (req: IncomingMessage) => req.headers["x-api-key"] as string,
|
|
72
|
+
authenticator: async (apiKey?: string) => {
|
|
73
|
+
if (!apiKey) return null;
|
|
74
|
+
const user = await validateApiKey(apiKey);
|
|
75
|
+
return user;
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `CreateAuthDecorator` options
|
|
81
|
+
|
|
82
|
+
The function accepts an object with the following properties:
|
|
83
|
+
|
|
84
|
+
| Property | Type | Description |
|
|
85
|
+
| ---------------------- | --------------------- | -------------------------------------------------------- |
|
|
86
|
+
| `source` | `AuthSource` | Extracts the token from the request (defaults to header/cookie) |
|
|
87
|
+
| `authenticator` | `AuthVerifier<T>` | Verifies the token and returns the payload |
|
|
88
|
+
| `authenticatorOptions` | `VerifyOptions` | Options passed to the authenticator |
|
|
89
|
+
| `validator` | `AuthValidator<T, R>` | Validates and transforms the authenticated data |
|
|
90
|
+
|
|
91
|
+
All properties are optional. When omitted, the default behavior is used.
|
|
92
|
+
|
|
93
|
+
## Class-level authentication
|
|
94
|
+
|
|
95
|
+
The `@Authentication` decorator can be applied to an entire controller class. This ensures that all routes within that controller require authentication, without decorating each handler individually.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { Controller, Get, Post } from "@antelopejs/interface-api";
|
|
99
|
+
import { Authentication } from "@antelopejs/interface-auth";
|
|
100
|
+
|
|
101
|
+
@Authentication()
|
|
102
|
+
class UserController extends Controller("/users") {
|
|
103
|
+
@Get("profile")
|
|
104
|
+
async getProfile() {
|
|
105
|
+
// Only authenticated users can access this endpoint
|
|
106
|
+
return { message: "Authenticated profile access" };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@Post("settings")
|
|
110
|
+
async updateSettings() {
|
|
111
|
+
// This route is also protected
|
|
112
|
+
return { success: true };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Class-level with role-based access
|
|
118
|
+
|
|
119
|
+
Combine class-level authentication with a validator to enforce role-based access for all routes in a controller.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { Controller } from "@antelopejs/interface-api";
|
|
123
|
+
import { Authentication } from "@antelopejs/interface-auth";
|
|
124
|
+
|
|
125
|
+
@Authentication((user: any) => {
|
|
126
|
+
if (!user || user.role !== "admin") {
|
|
127
|
+
throw new Error("Admin access required");
|
|
128
|
+
}
|
|
129
|
+
return user;
|
|
130
|
+
})
|
|
131
|
+
class AdminController extends Controller("/admin") {
|
|
132
|
+
// All routes require admin authentication
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Property-level authentication
|
|
137
|
+
|
|
138
|
+
Apply `@Authentication` to a class property to access the authenticated user data throughout the controller. The property is populated automatically for each request.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { Controller, Get } from "@antelopejs/interface-api";
|
|
142
|
+
import { Authentication } from "@antelopejs/interface-auth";
|
|
143
|
+
|
|
144
|
+
class UserController extends Controller("/users") {
|
|
145
|
+
@Authentication()
|
|
146
|
+
private user!: { id: string; name: string };
|
|
147
|
+
|
|
148
|
+
@Get("profile")
|
|
149
|
+
async getProfile() {
|
|
150
|
+
return {
|
|
151
|
+
id: this.user.id,
|
|
152
|
+
name: this.user.name,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@Get("settings")
|
|
157
|
+
async getSettings() {
|
|
158
|
+
// The same user data is available in all handlers
|
|
159
|
+
return { userId: this.user.id, theme: "dark" };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Decorator scope summary
|
|
165
|
+
|
|
166
|
+
The `@Authentication` decorator (and any custom decorator created with `CreateAuthDecorator`) can be applied at three levels:
|
|
167
|
+
|
|
168
|
+
| Scope | Effect |
|
|
169
|
+
| ----------- | ------------------------------------------------------------------- |
|
|
170
|
+
| Parameter | Injects the verified payload into a single handler parameter |
|
|
171
|
+
| Property | Populates a class property with the verified payload for all handlers |
|
|
172
|
+
| Class | Requires authentication for every route in the controller |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-auth",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "AntelopeJS interface for JWT authentication and session management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antelopejs",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"main": "dist/index.js",
|
|
18
18
|
"types": "dist/index.d.ts",
|
|
19
19
|
"files": [
|
|
20
|
-
"dist"
|
|
20
|
+
"dist",
|
|
21
|
+
"docs",
|
|
22
|
+
"skills"
|
|
21
23
|
],
|
|
22
24
|
"exports": {
|
|
23
25
|
".": {
|
|
@@ -35,11 +37,9 @@
|
|
|
35
37
|
"release": "pnpm run lint && pnpm run prepack && release-it",
|
|
36
38
|
"test": "pnpm run build && ajs module test ."
|
|
37
39
|
},
|
|
38
|
-
"dependencies": {
|
|
39
|
-
"@antelopejs/interface-api": "^0.0.3",
|
|
40
|
-
"@antelopejs/interface-core": "^0.0.3"
|
|
41
|
-
},
|
|
42
40
|
"devDependencies": {
|
|
41
|
+
"@antelopejs/interface-api": "^0.0.5",
|
|
42
|
+
"@antelopejs/interface-core": "^0.0.5",
|
|
43
43
|
"@biomejs/biome": "2.3.2",
|
|
44
44
|
"@types/chai": "^4.3.20",
|
|
45
45
|
"@types/mocha": "^10.0.10",
|
|
@@ -52,10 +52,17 @@
|
|
|
52
52
|
"rimraf": "^6.1.3",
|
|
53
53
|
"typescript": "^5.9.3"
|
|
54
54
|
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@antelopejs/interface-api": ">=0.0.3 <1.0.0",
|
|
57
|
+
"@antelopejs/interface-core": ">=0.0.3 <1.0.0"
|
|
58
|
+
},
|
|
55
59
|
"publishConfig": {
|
|
56
60
|
"access": "public"
|
|
57
61
|
},
|
|
58
62
|
"antelopeJs": {
|
|
59
|
-
"test": "src/antelope.test.ts"
|
|
63
|
+
"test": "src/antelope.test.ts",
|
|
64
|
+
"skills": [
|
|
65
|
+
"./skills"
|
|
66
|
+
]
|
|
60
67
|
}
|
|
61
68
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auth-interface
|
|
3
|
+
description: AntelopeJS interface for token-based authentication - signing and verifying auth tokens (SignRaw, ValidateRaw, SignServerResponse) and injecting the verified payload into interface-api controllers via the @Authentication decorator or custom decorators from CreateAuthDecorator. Use when code imports "@antelopejs/interface-auth", when securing controller routes, generating or validating auth/JWT tokens, injecting authenticated user data into handler parameters, or when implementing an auth provider for internal.Verify/internal.Sign.
|
|
4
|
+
category: antelopejs-interface
|
|
5
|
+
tags: [antelopejs, auth, jwt, tokens, decorators]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# @antelopejs/interface-auth
|
|
9
|
+
|
|
10
|
+
Token authentication for AntelopeJS modules. Two layers:
|
|
11
|
+
|
|
12
|
+
- **Proxy crossings** (need a provider module loaded, e.g. a JWT module): `internal.Verify` and `internal.Sign`, wrapped by `SignRaw`, `ValidateRaw`, and `SignServerResponse`. Always async.
|
|
13
|
+
- **Consumer-side helpers** (no crossing by themselves): `Authentication` and `CreateAuthDecorator`, which build parameter providers on top of `@antelopejs/interface-api`.
|
|
14
|
+
|
|
15
|
+
## Imports
|
|
16
|
+
|
|
17
|
+
All symbols come from the package root (the exports map exposes no other code subpaths):
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import {
|
|
21
|
+
Authentication, CreateAuthDecorator,
|
|
22
|
+
SignRaw, ValidateRaw, SignServerResponse,
|
|
23
|
+
internal, // provider side only
|
|
24
|
+
type AuthSource, type AuthVerifier, type AuthValidator,
|
|
25
|
+
type SignOptions, type VerifyOptions, type CookieOptions,
|
|
26
|
+
} from "@antelopejs/interface-auth";
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`@antelopejs/interface-api` and `@antelopejs/interface-core` are peerDependencies — the consuming module must have them installed.
|
|
30
|
+
|
|
31
|
+
## Consuming
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { Controller, Get, Post } from "@antelopejs/interface-api";
|
|
35
|
+
import { Authentication, SignRaw } from "@antelopejs/interface-auth";
|
|
36
|
+
|
|
37
|
+
interface LibrarianSession { id: string; branch: string; }
|
|
38
|
+
|
|
39
|
+
class LibrarianController extends Controller("/librarians") {
|
|
40
|
+
@Post("login")
|
|
41
|
+
async login() {
|
|
42
|
+
// Sign a payload into a token (proxy call to the auth provider)
|
|
43
|
+
return SignRaw({ id: "lib-7", branch: "riverside" }, { expiresIn: "1h" });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Get("desk")
|
|
47
|
+
async getDesk(@Authentication() librarian: LibrarianSession) {
|
|
48
|
+
// Token was read from the request, verified, and injected
|
|
49
|
+
return { id: librarian.id, branch: librarian.branch };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Custom pipelines use `CreateAuthDecorator({ source?, authenticator?, authenticatorOptions?, validator? })`; the callbacks run as `source(req, res)` → `authenticator(data, authenticatorOptions)` → `validator(data)` → injected parameter.
|
|
55
|
+
|
|
56
|
+
## Providing
|
|
57
|
+
|
|
58
|
+
An auth backend module implements the two proxy points:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { ImplementInterface } from "@antelopejs/interface-core";
|
|
62
|
+
import { internal } from "@antelopejs/interface-auth";
|
|
63
|
+
|
|
64
|
+
ImplementInterface(internal, {
|
|
65
|
+
Verify: (token, options) => decodeAndVerify(token, options), // return payload, throw on invalid
|
|
66
|
+
Sign: (data, options) => signToken(data, options), // return token string
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Declare `"antelopeJs": { "implements": ["@antelopejs/interface-auth"] }` in the provider's package.json.
|
|
71
|
+
|
|
72
|
+
## Gotchas
|
|
73
|
+
|
|
74
|
+
- `SignRaw` / `ValidateRaw` / `SignServerResponse` are interface proxy calls: they return Promises and only resolve once a provider module is attached. While a provider module is loaded but not yet attached, earlier calls are queued, not failed — always `await`. But when no loaded module provides the interface (e.g. a stubbed `optionalDependencies` entry), the core neutralizes the proxies and those calls reject instead of queuing.
|
|
75
|
+
- Default token source (`internal.defaultSource`): the `x-antelopejs-auth` request header, falling back to the `ANTELOPEJS_AUTH` cookie. `SignServerResponse` sets that same cookie via `Set-Cookie`.
|
|
76
|
+
- `@Authentication(validator?)` accepts an optional validator at the use site; it overrides any validator configured in `CreateAuthDecorator`.
|
|
77
|
+
- Decorators from `CreateAuthDecorator` (including `Authentication`) apply to parameters, properties, and whole classes (class-level registers a provider for the controller) — NOT to methods; decorating a method silently registers nothing and can break other parameter decorators on that handler.
|
|
78
|
+
- `expiresIn` / `notBefore` (SignOptions) and `maxAge` (VerifyOptions) accept a number of seconds or a timespan string such as `"1h"`.
|
|
79
|
+
- Rejection is exception-based: a failed verification or validator throws, it does not return `undefined`.
|
|
80
|
+
|
|
81
|
+
## Deeper reference
|
|
82
|
+
|
|
83
|
+
See this package's `docs/` chapters — Introduction, Authentication Basics, Token Handling, Parameter Decoration — and the shipped `dist/index.d.ts` for full TSDoc signatures. Do not duplicate them here.
|