@antelopejs/interface-auth 0.1.0 → 0.2.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
@@ -1,20 +1,22 @@
1
- # @antelopejs/interface-auth
1
+ # `@antelopejs/interface-auth`
2
2
 
3
3
  <div align="center">
4
- <a href="https://www.npmjs.com/package/@antelopejs/interface-auth"><img alt="npm" src="https://img.shields.io/npm/v/@antelopejs/interface-auth?style=for-the-badge&labelColor=000000&color=000000"></a>
5
- <a href="./LICENSE"><img alt="License" src="https://img.shields.io/npm/l/@antelopejs/interface-auth?style=for-the-badge&labelColor=000000&color=000000"></a>
6
- <a href="https://discord.gg/sjK28QHrA7"><img alt="Discord" src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000"></a>
7
- <a href="https://interfaces.antelopejs.com/docs/auth"><img alt="Docs" src="https://img.shields.io/badge/Docs-18181B?style=for-the-badge&color=000000"></a>
4
+ <a href="https://www.npmjs.com/package/@antelopejs/interface-auth"><img data-illustration alt="npm" src="https://img.shields.io/npm/v/@antelopejs/interface-auth?style=for-the-badge&labelColor=000000&color=000000"></a>
5
+ <a href="./LICENSE"><img data-illustration alt="License" src="https://img.shields.io/npm/l/@antelopejs/interface-auth?style=for-the-badge&labelColor=000000&color=000000"></a>
6
+ <a href="https://discord.gg/g4pFt6eXqu"><img data-illustration alt="Discord" src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000"></a>
7
+ <a href="https://interfaces.antelopejs.com/docs/auth"><img data-illustration alt="Docs" src="https://img.shields.io/badge/Docs-18181B?style=for-the-badge&color=000000"></a>
8
8
  </div>
9
9
 
10
10
  The AntelopeJS contract for token authentication: sign and verify tokens, and inject the verified payload into API handlers with a decorator.
11
11
 
12
+ Part of [AntelopeJS](https://github.com/AntelopeJS/antelopejs), the TypeScript framework where modules depend on contracts and the application chooses the provider. Built by the team behind [AntelopeJS DMS](https://github.com/AntelopeJS/dms).
13
+
12
14
  ## What it offers
13
15
 
14
16
  - `SignRaw` and `ValidateRaw` sign a payload into a token and verify a token back into its payload.
15
17
  - `SignServerResponse` signs a payload and attaches the token to a response as a cookie.
16
- - `@Authentication()` reads the token from the `x-antelopejs-auth` header, falling back to the `ANTELOPEJS_AUTH` cookie when the header is absent, verifies it and injects the payload into a handler parameter.
17
- - `CreateAuthDecorator` builds your own decorator with a custom source, verifier and validator.
18
+ - `@Authentication()` reads the token from the `x-antelopejs-auth` header, or from the `ANTELOPEJS_AUTH` cookie when the header is absent. It verifies the token and injects the payload into a handler parameter.
19
+ - `CreateAuthDecorator` builds your own decorator with a custom source, verifier, and validator.
18
20
 
19
21
  ## Implementations
20
22
 
@@ -59,7 +61,9 @@ export class SessionController extends Controller("/session") {
59
61
  }
60
62
  ```
61
63
 
62
- A request to `GET /session/me` without a valid token fails before the handler runs. Send the token unchanged in `x-antelopejs-auth`, without a `Bearer ` prefix. The login method only demonstrates signing; validate credentials before issuing tokens in a real application.
64
+ A request to `GET /session/me` without a valid token fails before the handler runs. Send the token unchanged in `x-antelopejs-auth`, without a `Bearer ` prefix. The `login` method only shows signing. In a real application, check the credentials before you issue a token.
65
+
66
+ The `Session` annotation describes the payload the application expects. It does not check it, so `session.id` is whatever the verified token carries. Add a [shape-checking verifier](./docs/2.authentication.md#create-a-custom-verifier) before you rely on claims from tokens whose format nothing enforces.
63
67
 
64
68
  ## Documentation
65
69
 
@@ -70,14 +74,16 @@ A request to `GET /session/me` without a valid token fails before the handler ru
70
74
 
71
75
  ## Compatibility
72
76
 
73
- Use with `@antelopejs/core` 1.x and the following peer dependencies:
77
+ The module declares these peer dependencies:
78
+
79
+ <!-- antelopejs-docs-compat:start -->
74
80
 
75
- <!-- docs-compat: ./package.json#peerDependencies -->
81
+ | Package | Supported | Tested with |
82
+ | ---------------------------- | ----------------- | ----------- |
83
+ | `@antelopejs/interface-api` | `>=0.0.15 <1.0.0` | `0.2.0` |
84
+ | `@antelopejs/interface-core` | `>=0.2.4 <1.0.0` | `0.4.0` |
76
85
 
77
- | Package | Range |
78
- | ---------------------------- | ----------------- |
79
- | `@antelopejs/interface-api` | `>=0.0.15 <1.0.0` |
80
- | `@antelopejs/interface-core` | `>=0.2.4 <1.0.0` |
86
+ <!-- antelopejs-docs-compat:end -->
81
87
 
82
88
  ## Contributing
83
89
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import { type Class } from "@antelopejs/interface-core/decorators";
2
3
  /**
3
4
  * A value JSON can represent: a string, number, boolean, `null`, an array of
4
5
  * JSON values, or a {@link JsonObject}. `Date`, `Buffer`, functions and class
@@ -97,6 +98,13 @@ export interface CookieOptions {
97
98
  domain?: string;
98
99
  secure?: boolean;
99
100
  }
101
+ type TimeSpanUnit = "Years" | "Year" | "Yrs" | "Yr" | "Y" | "Weeks" | "Week" | "W" | "Days" | "Day" | "D" | "Hours" | "Hour" | "Hrs" | "Hr" | "H" | "Minutes" | "Minute" | "Mins" | "Min" | "M" | "Seconds" | "Second" | "Secs" | "Sec" | "s" | "Milliseconds" | "Millisecond" | "Msecs" | "Msec" | "Ms";
102
+ /**
103
+ * A timespan string in the grammar of the `ms` package: a number, optionally
104
+ * followed by a unit in any case, with or without a space (`"90"`, `"2h"`,
105
+ * `"7 days"`). A bare number string counts milliseconds.
106
+ */
107
+ export type TimeSpan = `${number}` | `${number}${TimeSpanUnit | Uppercase<TimeSpanUnit> | Lowercase<TimeSpanUnit>}` | `${number} ${TimeSpanUnit | Uppercase<TimeSpanUnit> | Lowercase<TimeSpanUnit>}`;
100
108
  /**
101
109
  * Options for signing authentication tokens.
102
110
  *
@@ -113,13 +121,13 @@ export interface CookieOptions {
113
121
  */
114
122
  export interface SignOptions {
115
123
  /**
116
- * Expiration as a number of seconds or a timespan string.
124
+ * Expiration as a number of seconds or a {@link TimeSpan}.
117
125
  */
118
- expiresIn?: string | number;
126
+ expiresIn?: number | TimeSpan;
119
127
  /**
120
- * Not-before field as a number of seconds or a timespan string.
128
+ * Not-before field as a number of seconds or a {@link TimeSpan}.
121
129
  */
122
- notBefore?: string | number;
130
+ notBefore?: number | TimeSpan;
123
131
  }
124
132
  /**
125
133
  * Options for verifying authentication tokens.
@@ -150,7 +158,10 @@ export interface VerifyOptions {
150
158
  */
151
159
  maxAge?: string | number;
152
160
  }
153
- type AuthPayload = string | Buffer | JsonObject;
161
+ /**
162
+ * What a token signs: a string, a `Buffer`, or a {@link JsonObject}.
163
+ */
164
+ export type AuthPayload = string | Buffer | JsonObject;
154
165
  interface AuthDecoratorOptions<T, R> {
155
166
  source?: AuthSource;
156
167
  authenticatorOptions?: VerifyOptions;
@@ -168,7 +179,7 @@ interface ResolvedAuthDecoratorCallbacks<T, R> {
168
179
  authenticatorOptions: VerifyOptions;
169
180
  validator: AuthValidator<T, R> | undefined;
170
181
  }
171
- declare function buildAuthDecorator<T, R>(callbacks: ResolvedAuthDecoratorCallbacks<T, R>): (validator?: AuthValidator<T, R> | undefined) => import("@antelopejs/interface-core/decorators").ClassDecorator<import("@antelopejs/interface-core/decorators").Class<any, any[]>> & import("@antelopejs/interface-core/decorators").PropertyDecorator & import("@antelopejs/interface-core/decorators").ParameterDecorator;
182
+ declare function buildAuthDecorator<T, R>(callbacks: ResolvedAuthDecoratorCallbacks<T, R>): (validator?: AuthValidator<T, R> | undefined) => import("@antelopejs/interface-core/decorators").PropertyDecorator & import("@antelopejs/interface-core/decorators").ClassDecorator<Class<object, any[]>> & import("@antelopejs/interface-core/decorators").ParameterDecorator;
172
183
  type AuthDecoratorFactory<T, R> = ReturnType<typeof buildAuthDecorator<T, R>>;
173
184
  /**
174
185
  * @internal
@@ -317,5 +328,5 @@ export declare function CreateAuthDecorator<T, R = unknown>(callbacks: CustomAut
317
328
  *
318
329
  * @see {@link CreateAuthDecorator}
319
330
  */
320
- export declare const Authentication: (validator?: AuthValidator<AuthClaims, unknown> | undefined) => import("@antelopejs/interface-core/decorators").ClassDecorator<import("@antelopejs/interface-core/decorators").Class<any, any[]>> & import("@antelopejs/interface-core/decorators").PropertyDecorator & import("@antelopejs/interface-core/decorators").ParameterDecorator;
331
+ export declare const Authentication: (validator?: AuthValidator<AuthClaims, unknown> | undefined) => import("@antelopejs/interface-core/decorators").PropertyDecorator & import("@antelopejs/interface-core/decorators").ClassDecorator<Class<object, any[]>> & import("@antelopejs/interface-core/decorators").ParameterDecorator;
321
332
  export {};
package/dist/index.js CHANGED
@@ -61,15 +61,26 @@ function createAuthParameterProvider(callbacks, validator) {
61
61
  validator,
62
62
  });
63
63
  }
64
- function registerClassParameterProvider(target, provider) {
65
- (0, interface_api_1.SetParameterProvider)(target.prototype, Symbol(ClassParameterProviderSymbolDescription), undefined, provider);
64
+ function isDecoratorTarget(value) {
65
+ return (typeof value === "object" &&
66
+ value !== null &&
67
+ "constructor" in value &&
68
+ typeof value.constructor === "function");
69
+ }
70
+ /** The prototype of the class a class decorator receives, where its handlers' parameters live. */
71
+ function classPrototype(target) {
72
+ const prototype = "prototype" in target ? target.prototype : undefined;
73
+ if (!isDecoratorTarget(prototype)) {
74
+ throw new TypeError("A class decorator applies to a class.");
75
+ }
76
+ return prototype;
66
77
  }
67
78
  function buildAuthDecorator(callbacks) {
68
79
  return (0, decorators_1.MakeParameterAndPropertyAndClassDecorator)((target, key, index, validator) => {
69
80
  const authValidator = validator ?? callbacks.validator;
70
81
  const provider = createAuthParameterProvider(callbacks, authValidator);
71
82
  if (key === undefined) {
72
- registerClassParameterProvider(target, provider);
83
+ (0, interface_api_1.SetParameterProvider)(classPrototype(target), Symbol(ClassParameterProviderSymbolDescription), undefined, provider);
73
84
  return;
74
85
  }
75
86
  (0, interface_api_1.SetParameterProvider)(target, key, index, provider);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const __1 = require("..");
5
+ class Guarded {
6
+ }
7
+ const WITHOUT_PROTOTYPE = Guarded.bind(null);
8
+ describe("class decorator target", () => {
9
+ it("refuses a class that has no prototype object", () => {
10
+ (0, chai_1.expect)(() => {
11
+ (0, __1.Authentication)()(WITHOUT_PROTOTYPE);
12
+ }).to.throw(TypeError, "A class decorator applies to a class.");
13
+ });
14
+ it("accepts a class with a prototype object", () => {
15
+ (0, chai_1.expect)(() => {
16
+ (0, __1.Authentication)()(Guarded);
17
+ }).not.to.throw();
18
+ });
19
+ });
20
+ //# sourceMappingURL=class-decorator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-decorator.test.js","sourceRoot":"","sources":["../../src/tests/class-decorator.test.ts"],"names":[],"mappings":";;AAAA,+BAA8B;AAC9B,0BAAoC;AAEpC,MAAM,OAAO;CAAG;AAEhB,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAE7C,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,IAAA,aAAM,EAAC,GAAG,EAAE;YACV,IAAA,kBAAc,GAAE,CAAC,iBAAiB,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,uCAAuC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,IAAA,aAAM,EAAC,GAAG,EAAE;YACV,IAAA,kBAAc,GAAE,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,18 +1,22 @@
1
- # Authenticate API requests
1
+ ---
2
+ title: Authenticate API requests
3
+ description: Install the auth interface, protect a first endpoint with a verified token, and pick where to plug in your own source, verifier, or validator.
4
+ mode: how-to
5
+ ---
2
6
 
3
7
  ## Overview
4
8
 
5
- Use `@antelopejs/interface-auth` to sign tokens and inject verified payloads into API handlers. Your application still owns credential checks, payload validation, and permission rules: a valid signature alone does not grant access to a resource.
9
+ Use `@antelopejs/interface-auth` to sign tokens and inject verified payloads into API handlers. Your application still owns credential checks, payload validation, and permission rules. A valid signature alone does not grant access to a resource.
6
10
 
7
- This interface depends on the [Interface API](https://github.com/AntelopeJS/interface-api) package, which provides the decorator infrastructure for parameter injection.
11
+ This interface depends on the [interface-api](https://github.com/AntelopeJS/interface-api) package, which provides the decorators that inject parameters.
8
12
 
9
13
  ## Core concepts
10
14
 
11
- The authentication system is built around three main layers:
15
+ The interface has three layers:
12
16
 
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.
17
+ - Token handling. `SignRaw`, `ValidateRaw`, and `SignServerResponse` sign and verify tokens.
18
+ - Authentication decorators. The `@Authentication` decorator and the `CreateAuthDecorator` function inject verified payloads into handler parameters.
19
+ - A pipeline you can change. Custom sources, verifiers, and validators replace each step of the flow.
16
20
 
17
21
  ## Installation
18
22
 
@@ -22,9 +26,9 @@ pnpm add @antelopejs/interface-auth
22
26
 
23
27
  ## Protect an endpoint
24
28
 
25
- Start with a running AntelopeJS API module and an authentication provider bound to this interface. Installing the package does not configure signing keys or attach a token implementation.
29
+ Start with a running AntelopeJS API module and an authentication module that implements this interface. Installing the package does not configure signing keys or attach a token implementation.
26
30
 
27
- This controller requires a verified token for `GET /account`. It returns no claims, so you can first check that your provider and transport work before adding payload validation.
31
+ This controller requires a verified token for `GET /account`. It returns no claims, so you can check that your provider and transport work before you add payload validation.
28
32
 
29
33
  ```ts docs-check
30
34
  import { Controller, Get } from "@antelopejs/interface-api";
@@ -39,25 +43,25 @@ class AccountController extends Controller("/account") {
39
43
  }
40
44
  ```
41
45
 
42
- Send an issued token in `x-antelopejs-auth` to receive `{ "authenticated": true }`. A missing or invalid token must fail verification before the handler runs. This checks authentication only, not permission to read another user's account.
46
+ Send an issued token in `x-antelopejs-auth` to receive `{ "authenticated": true }`. A missing or invalid token must fail verification before the handler runs. This route checks authentication only, not permission to read another user's account.
43
47
 
44
- 1. **Issue a token after checking credentials.** Use [token handling](./3.token-handling.md) to choose `SignRaw` or `SignServerResponse` and set an expiry.
48
+ 1. **Issue a token after you check the credentials.** Use [token handling](./3.token-handling.md) to choose `SignRaw` or `SignServerResponse` and set an expiry.
45
49
  2. **Choose one transport.** The default source reads a raw token from `x-antelopejs-auth`, then tries `ANTELOPEJS_AUTH` only when the header is absent. For `Authorization: Bearer`, use the [custom source example](./2.authentication.md#create-a-custom-source).
46
50
  3. **Require authentication.** Add [a parameter, property, or class decorator](./4.parameter-decoration.md) to the controller.
47
- 4. **Enforce your policy.** Validate the payload shape and throw when the caller lacks permission. A validator returning `false` injects `false`; it does not deny access.
51
+ 4. **Enforce your policy.** Validate the payload shape, and throw when the caller lacks permission. A validator that returns `false` injects `false`. It does not deny access.
48
52
 
49
53
  ## Choose where to customize
50
54
 
51
- | You need to change… | Customize | Keep this boundary |
55
+ | You need to change | Customize | Keep this boundary |
52
56
  | -------------------------- | --------------- | -------------------------------------------- |
53
57
  | Where the token comes from | `source` | Extraction does not establish trust. |
54
- | How the token is verified | `authenticator` | Verify before returning a payload. |
55
- | Who may use the endpoint | `validator` | Throw to reject; return the value to inject. |
58
+ | How the token is verified | `authenticator` | Verify before you return a payload. |
59
+ | Who may use the endpoint | `validator` | Throw to reject. Return the value to inject. |
56
60
 
57
- Before exposing the route, check a missing token, an invalid token, and a valid token without the required permission—not only the successful request. See [authentication basics](./2.authentication.md) for the complete pipeline.
61
+ Before you expose the route, test a missing token, an invalid token, and a valid token without the required permission, as well as the successful request. See [authentication and authorization](./2.authentication.md) for the complete pipeline.
58
62
 
59
63
  ## Documentation sections
60
64
 
61
- - [Authentication Basics](./2.authentication.md) - Authentication flow, sources, verifiers, and validators
62
- - [Token Handling](./3.token-handling.md) - Token generation and validation functions
63
- - [Parameter Decoration](./4.parameter-decoration.md) - Authentication decorators and custom providers
65
+ - [Authentication and authorization](./2.authentication.md) covers the flow, sources, verifiers, and validators.
66
+ - [Token handling](./3.token-handling.md) covers the functions that sign and verify tokens.
67
+ - [Require authentication in controllers](./4.parameter-decoration.md) covers the decorators and custom decorators.
@@ -1,21 +1,25 @@
1
- # Authentication and authorization
1
+ ---
2
+ title: Authentication and authorization
3
+ description: How the auth interface turns a request into an injected payload, through a source, an authenticator, and an optional validator, and which part of the policy stays in your application.
4
+ mode: explanation
5
+ ---
2
6
 
3
- Authentication establishes trust in a token. Authorization decides what its holder may do. This interface connects token verification to API parameter injection; your application supplies credential checks, payload validation, and access rules.
7
+ Authentication establishes trust in a token. Authorization decides what its holder may do. This interface connects token verification to API parameter injection. Your application supplies credential checks, payload validation, and access rules.
4
8
 
5
9
  ## Authentication flow
6
10
 
7
- A typical authentication flow consists of four steps:
11
+ An authentication flow has four steps:
8
12
 
9
- 1. **Token generation** - Sign user data into a token using `SignRaw` or `SignServerResponse`.
10
- 2. **Token transport** - Have the client send the token in the chosen header or cookie. Choose storage and CSRF protection for your client; they are not configured by this interface.
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
+ 1. Token generation. `SignRaw` or `SignServerResponse` signs user data into a token.
14
+ 2. Token transport. The client sends the token in the chosen header or cookie. You choose the client's storage and CSRF protection. This interface configures neither.
15
+ 3. Token validation. The server verifies the token on each request.
16
+ 4. Authorization. Your code checks whether the authenticated user may access the requested resource.
13
17
 
14
18
  ### Example authentication flow
15
19
 
16
- The persistence functions in this example (`validateUserCredentials` and `getUserProfile`) belong to your application. The profile route verifies a token; add a validator for payload shape and resource permissions. For production cookies, also decide Secure, SameSite, expiry, and CSRF policy for your deployment.
20
+ The persistence functions in this example, `validateUserCredentials` and `getUserProfile`, belong to your application. The profile route verifies a token. A validator would add the payload shape and resource permissions. For production cookies, you also decide the Secure, SameSite, expiry, and CSRF policy of your deployment.
17
21
 
18
- ```typescript
22
+ ```typescript fragment
19
23
  import { SignRaw, Authentication } from "@antelopejs/interface-auth";
20
24
  import {
21
25
  Controller,
@@ -55,23 +59,23 @@ class UserController extends Controller("/users") {
55
59
  async getProfile(
56
60
  @Authentication() userData: { userId: number; role: string },
57
61
  ) {
58
- // Step 3: Token is verified; resource authorization is application policy
59
- // If the token is invalid, an error is thrown before this code runs
62
+ // Step 3: the token is verified. Resource authorization is application policy.
63
+ // An invalid token rejects the request before this code runs.
60
64
  return { user: await getUserProfile(userData.userId) };
61
65
  }
62
66
  }
63
67
  ```
64
68
 
65
- This cookie example requires HTTPS. `SameSite=Lax` is a starting policy for same-site browser use, not a substitute for deciding CSRF protection or cross-site requirements. The helpers named above are application code, not a complete login implementation.
69
+ This cookie example requires HTTPS. `SameSite=Lax` is a starting policy for same-site browser use. It does not replace a decision on CSRF protection or cross-site requirements. The helpers named above are application code, not a complete login implementation.
66
70
 
67
71
  ## Authentication sources
68
72
 
69
73
  An `AuthSource` function extracts the authentication token from the incoming HTTP request. The default source checks two locations in order:
70
74
 
71
- 1. **Custom header** - The `x-antelopejs-auth` header
72
- 2. **Cookie** - The `ANTELOPEJS_AUTH` cookie
75
+ 1. The `x-antelopejs-auth` header.
76
+ 2. The `ANTELOPEJS_AUTH` cookie.
73
77
 
74
- The header contains the raw token, not `Bearer <token>`. A present header takes precedence even when it is empty or invalid; authentication does not retry with the cookie after verification fails. The default source does not read `Authorization`.
78
+ The header contains the raw token, not `Bearer <token>`. A present header takes precedence even when it is empty or invalid. Authentication does not retry with the cookie after verification fails. The default source does not read `Authorization`.
75
79
 
76
80
  ### Create a custom source
77
81
 
@@ -97,6 +101,8 @@ const BearerAuth = CreateAuthDecorator({
97
101
  The `AuthSource` type signature is:
98
102
 
99
103
  ```typescript
104
+ import type { IncomingMessage, ServerResponse } from "node:http";
105
+
100
106
  type AuthSource = (
101
107
  req: IncomingMessage,
102
108
  res: ServerResponse,
@@ -105,7 +111,7 @@ type AuthSource = (
105
111
 
106
112
  ## Authentication verifiers
107
113
 
108
- 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).
114
+ An `AuthVerifier` function validates the token and extracts its payload. The default verifier is `ValidateRaw`, which calls the module that implements this interface, such as `@antelopejs/auth-jwt` for JSON Web Tokens.
109
115
 
110
116
  ### Create a custom verifier
111
117
 
@@ -132,11 +138,13 @@ const UserAuth = CreateAuthDecorator({
132
138
  });
133
139
  ```
134
140
 
135
- A verifier must establish trust in the token before returning its payload. Decoding Base64 or parsing JSON alone does not authenticate a request. `ValidateRaw` returns an `AuthClaims` (`string | JsonObject`): the interface does not know the shape of what you signed, so a field read needs a check like the one above, and the verifier's return type is what a configured validator receives as its input.
141
+ A verifier must establish trust in the token before it returns the payload. Decoding Base64 or parsing JSON alone does not authenticate a request. `ValidateRaw` returns an `AuthClaims`, which is `string | JsonObject`. The interface does not know the shape of what you signed, so reading a field needs a check like the one above. A configured validator receives the verifier's return type as its input.
136
142
 
137
143
  The `AuthVerifier` type signature is:
138
144
 
139
145
  ```typescript
146
+ import type { AuthClaims, VerifyOptions } from "@antelopejs/interface-auth";
147
+
140
148
  type AuthVerifier<T = AuthClaims> = (
141
149
  data?: string,
142
150
  options?: VerifyOptions,
@@ -145,7 +153,7 @@ type AuthVerifier<T = AuthClaims> = (
145
153
 
146
154
  ## Authentication validators
147
155
 
148
- 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.
156
+ An `AuthValidator` function runs extra checks on the verified data. Validators run after the verifier. A validator can transform the result, or throw an error to reject the request.
149
157
 
150
158
  ```typescript
151
159
  import { CreateAuthDecorator, AuthValidator } from "@antelopejs/interface-auth";
@@ -165,6 +173,8 @@ const AdminOnly = CreateAuthDecorator({
165
173
  The `AuthValidator` type signature is:
166
174
 
167
175
  ```typescript
176
+ import type { AuthClaims } from "@antelopejs/interface-auth";
177
+
168
178
  type AuthValidator<T = AuthClaims, R = unknown> = (data: T) => Promise<R> | R;
169
179
  ```
170
180
 
@@ -172,16 +182,16 @@ Without an `authenticator`, a validator receives the `AuthClaims` the default ve
172
182
 
173
183
  ## Authentication pipeline
174
184
 
175
- The complete authentication pipeline processes the request through three stages:
185
+ The pipeline takes the request through three stages:
176
186
 
177
- ![The source extracts a token, the authenticator verifies it, and an optional validator enforces policy before injection. A thrown error stops injection.](./assets/authentication-pipeline.svg){width="480"}
187
+ ![The source extracts a token, the authenticator verifies it, and an optional validator enforces policy before injection. A thrown error stops injection.](./assets/authentication-pipeline.svg "illustration"){width="480"}
178
188
 
179
- Omitted `source` and `authenticator` callbacks use the defaults. There is no default policy validator: without one, the verified payload is injected unchanged.
189
+ An omitted `source` or `authenticator` callback uses the default. There is no default policy validator. Without one, the decorator injects the verified payload unchanged.
180
190
 
181
191
  | Stage | Input | Output | Failure boundary |
182
192
  | --------------- | ------------------------------ | -------------------- | -------------------------------------------------------------- |
183
193
  | `source` | Request and response | Token or `undefined` | Missing input still reaches the authenticator. |
184
194
  | `authenticator` | Token and verification options | Verified payload | A thrown error or rejected promise stops processing. |
185
- | `validator` | Verified payload | Value to inject | Throw to deny access; a falsy return value is not a rejection. |
195
+ | `validator` | Verified payload | Value to inject | Throw to deny access. A falsy return value is not a rejection. |
186
196
 
187
- A validator passed to a decorator invocation replaces the configured validator; it does not run after it as an extra check. Keep shared policy in a function you explicitly call when composing validators.
197
+ A validator passed to a decorator call replaces the configured validator. It does not run after it as an extra check. To compose validators, keep the shared policy in a function that each validator calls.
@@ -1,6 +1,10 @@
1
- # Token Handling
1
+ ---
2
+ title: Token handling
3
+ description: Reference for SignRaw, SignServerResponse, and ValidateRaw, with their options, argument types, return values, and cookie serialization limits.
4
+ mode: reference
5
+ ---
2
6
 
3
- The Interface Auth provides functions for generating and validating authentication tokens. These functions serve as the foundation for the authentication system.
7
+ `@antelopejs/interface-auth` exports three functions that sign and verify tokens. The decorators call `ValidateRaw` by default.
4
8
 
5
9
  ## Token generation
6
10
 
@@ -26,7 +30,7 @@ The function accepts two arguments:
26
30
  | `data` | `string \| Buffer \| JsonObject` | The data to sign |
27
31
  | `options` | `SignOptions` (optional) | Signing configuration options |
28
32
 
29
- `JsonObject` maps string keys to JSON values (`string`, `number`, `boolean`, `null`, arrays and nested objects). A `Date`, a class instance or a function is a compile error: convert it first (for example `date.toISOString()`). A key whose value is `undefined` is accepted and dropped by serialization. An object typed with an `interface` has no index signature and is not assignable: declare it with a `type` alias or spread it into a literal.
33
+ `JsonObject` maps string keys to JSON values: `string`, `number`, `boolean`, `null`, arrays, and nested objects. A `Date`, a class instance, or a function is a compile error. Convert it first, for example with `date.toISOString()`. A key whose value is `undefined` is accepted, and serialization drops it. An object typed with an `interface` has no index signature and is not assignable. Declare it with a `type` alias, or spread it into a literal.
30
34
 
31
35
  `SignRaw` returns a `Promise<string>` that resolves to the signed token.
32
36
 
@@ -34,10 +38,12 @@ The function accepts two arguments:
34
38
 
35
39
  The `SignOptions` interface configures token generation.
36
40
 
37
- | Property | Type | Description |
38
- | ----------- | ------------------ | ---------------------------------------------------------------------------- |
39
- | `expiresIn` | `string \| number` | Token expiration time as seconds or a timespan string (e.g., `"1h"`, `"2d"`) |
40
- | `notBefore` | `string \| number` | Duration before which the token is not valid |
41
+ | Property | Type | Description |
42
+ | ----------- | -------------------- | ------------------------------------------------------------------------------- |
43
+ | `expiresIn` | `number \| TimeSpan` | Token expiration time as seconds or a timespan string, such as `"1h"` or `"2d"` |
44
+ | `notBefore` | `number \| TimeSpan` | Duration before which the token is not valid |
45
+
46
+ `TimeSpan` is the timespan grammar of the `ms` package. It is a number followed by an optional unit in any case, with or without a space, such as `"90"`, `"2h"`, or `"7 days"`. A bare number string counts milliseconds. A string outside this grammar, such as `"soon"`, does not compile.
41
47
 
42
48
  ### `SignServerResponse`
43
49
 
@@ -72,19 +78,19 @@ The cookie is set with the name `ANTELOPEJS_AUTH` and the signed token as its va
72
78
 
73
79
  ### `CookieOptions`
74
80
 
75
- The `CookieOptions` interface supplies attributes to the authentication cookie. The current serializer writes keys literally, omits `false` and `undefined`, writes `true` as a standalone directive, and converts other values with `String(value)`.
81
+ The `CookieOptions` interface supplies attributes to the authentication cookie. The serializer writes keys literally and omits `false` and `undefined` values. It writes `true` as a standalone directive and converts other values with `String(value)`.
76
82
 
77
- | Property | Type | Description |
78
- | ---------- | --------- | ------------------------------------------------------------------------------- |
79
- | `maxAge` | `number` | Written as `maxAge=<number>`; not converted to the standard `Max-Age` attribute |
80
- | `signed` | `boolean` | Written as a directive when true; does not add a cookie signature |
81
- | `expires` | `Date` | Written using `String(date)`, not an explicit HTTP-date formatter |
82
- | `httpOnly` | `boolean` | Prevents client-side JavaScript from accessing the cookie |
83
- | `path` | `string` | URL path for which the cookie is valid |
84
- | `domain` | `string` | Domain for which the cookie is valid |
85
- | `secure` | `boolean` | Only sends the cookie over HTTPS |
83
+ | Property | Type | Description |
84
+ | ---------- | --------- | --------------------------------------------------------------------- |
85
+ | `maxAge` | `number` | Written as `maxAge=<number>`, not as the standard `Max-Age` attribute |
86
+ | `signed` | `boolean` | Written as a directive when true. It does not add a cookie signature. |
87
+ | `expires` | `Date` | Written using `String(date)`, not an explicit HTTP-date formatter |
88
+ | `httpOnly` | `boolean` | Prevents client-side JavaScript from accessing the cookie |
89
+ | `path` | `string` | URL path for which the cookie is valid |
90
+ | `domain` | `string` | Domain for which the cookie is valid |
91
+ | `secure` | `boolean` | Only sends the cookie over HTTPS |
86
92
 
87
- Do not rely on `maxAge`, `signed`, or `expires` for browser lifetime or extra signing guarantees in this implementation. Use a standards-compliant cookie serializer when those features are required, and keep token expiration in `SignOptions`. No cookie attributes are added by default.
93
+ `maxAge`, `signed`, and `expires` do not set the browser lifetime or add a signature. When you need those features, use a standards-compliant cookie serializer, and keep token expiration in `SignOptions`. The function adds no cookie attributes by default.
88
94
 
89
95
  `CookieOptions` has no `sameSite` field. If your deployment requires SameSite, serialize the cookie yourself and set the response header, as in the [authentication flow](./2.authentication.md#example-authentication-flow). Do not cast unsupported options into this type.
90
96
 
@@ -97,14 +103,16 @@ The `ValidateRaw` function verifies a token and returns the data contained withi
97
103
  ```typescript
98
104
  import { ValidateRaw } from "@antelopejs/interface-auth";
99
105
 
100
- try {
101
- const claims = await ValidateRaw(token);
102
- console.log(claims); // { userId: 123, role: "admin" }
103
- } catch (error) {
104
- console.error(
105
- "Invalid token:",
106
- error instanceof Error ? error.message : String(error),
107
- );
106
+ async function inspect(token: string) {
107
+ try {
108
+ const claims = await ValidateRaw(token);
109
+ console.log(claims); // { userId: 123, role: "admin", iat: ..., exp: ... } with auth-jwt
110
+ } catch (error) {
111
+ console.error(
112
+ "Invalid token:",
113
+ error instanceof Error ? error.message : String(error),
114
+ );
115
+ }
108
116
  }
109
117
  ```
110
118
 
@@ -115,7 +123,9 @@ The function accepts two arguments:
115
123
  | `token` | `string` (optional) | The signed token to verify |
116
124
  | `options` | `VerifyOptions` (optional) | Verification configuration |
117
125
 
118
- `ValidateRaw` returns a `Promise<AuthClaims>`, where `AuthClaims` is `string | JsonObject`: the signed string, or the JSON object that was signed. It has no type parameter. Read a field only after checking it, or hand the result to a parser of your own; a [custom verifier](./2.authentication.md#create-a-custom-verifier) is the place to do that once.
126
+ `ValidateRaw` returns a `Promise<AuthClaims>`, where `AuthClaims` is `string | JsonObject`. The value is the signed string, or the JSON object that was signed. `ValidateRaw` has no type parameter. Read a field only after you check it, or pass the result to a parser of your own. A [custom verifier](./2.authentication.md#create-a-custom-verifier) does that once for every route.
127
+
128
+ The promise rejects when the token is missing or fails verification. The rejection value comes from the implementation and is not always an `Error`. `@antelopejs/auth-jwt` rejects with an `HTTPResult`: status 401 for a missing token and 403 for an invalid or expired one. The example above handles both kinds of value.
119
129
 
120
130
  ### `VerifyOptions`
121
131
 
@@ -133,9 +143,11 @@ The `VerifyOptions` interface configures token validation.
133
143
  import { ValidateRaw } from "@antelopejs/interface-auth";
134
144
 
135
145
  // Limit token age without bypassing expiration or not-before checks.
136
- const claims = await ValidateRaw(token, {
137
- maxAge: "30m",
138
- });
146
+ async function verifyRecent(token: string) {
147
+ return ValidateRaw(token, {
148
+ maxAge: "30m",
149
+ });
150
+ }
139
151
  ```
140
152
 
141
- Leave `ignoreExpiration` and `ignoreNotBefore` unset for normal authentication. They deliberately bypass time checks; use them only when you have a separate, explicit policy for accepting such tokens. A successful `ValidateRaw` verifies the token through your provider; it does not check the shape of the payload.
153
+ Leave `ignoreExpiration` and `ignoreNotBefore` unset for normal authentication. They bypass the time checks. Set them only when a separate, explicit policy accepts such tokens. A successful `ValidateRaw` call verifies the token through your provider. It does not check the shape of the payload.
@@ -1,10 +1,14 @@
1
- # Require authentication in controllers
1
+ ---
2
+ title: Require authentication in controllers
3
+ description: Protect a handler, a property, or a whole controller with @Authentication, and build reusable decorators with CreateAuthDecorator.
4
+ mode: how-to
5
+ ---
2
6
 
3
- Use a parameter decorator when one handler needs the payload, a property decorator when several methods need it, or a class decorator when every route must authenticate without receiving the payload. These are alternative scopes, not three steps you must combine.
7
+ Use a parameter decorator when one handler needs the payload. Use a property decorator when several methods need it. Use a class decorator when every route must authenticate without receiving the payload. Pick one scope per need. You do not have to combine them.
4
8
 
5
9
  ## The `@Authentication` decorator
6
10
 
7
- The `@Authentication` decorator retrieves and validates a token from `x-antelopejs-auth`, or from the `ANTELOPEJS_AUTH` cookie when the header is absent, and injects the verified payload into the parameter.
11
+ The `@Authentication` decorator reads a token from `x-antelopejs-auth`, or from the `ANTELOPEJS_AUTH` cookie when the header is absent. It verifies the token and injects the verified payload into the parameter.
8
12
 
9
13
  ```typescript
10
14
  import { Controller, Get } from "@antelopejs/interface-api";
@@ -21,9 +25,9 @@ class UserController extends Controller("/users") {
21
25
  }
22
26
  ```
23
27
 
24
- If the token is missing or invalid, the request fails with an error response before the handler executes.
28
+ If the token is missing or invalid, the verifier rejects and the handler does not run. With `@antelopejs/auth-jwt`, the response is a 401 for a missing token and a 403 for an invalid one.
25
29
 
26
- The payload annotations in these examples describe the application's expected token format. They do not check it. Add a [shape-checking verifier](./2.authentication.md#create-a-custom-verifier) before reading claims from tokens whose format is not already enforced. The API provider determines how ordinary thrown errors become HTTP responses; throwing `Error` does not itself specify a 401 or 403 status.
30
+ The payload annotations in these examples describe the token format the application expects. They do not check it. Add a [shape-checking verifier](./2.authentication.md#create-a-custom-verifier) before you read claims from tokens whose format nothing enforces yet. The API provider decides how an ordinary thrown error becomes an HTTP response. Throwing an `Error` does not set a 401 or 403 status.
27
31
 
28
32
  ### Inline validators
29
33
 
@@ -54,9 +58,9 @@ class PaymentController extends Controller("/payments") {
54
58
 
55
59
  ## Create custom decorators with `CreateAuthDecorator`
56
60
 
57
- The `CreateAuthDecorator` function creates a reusable authentication decorator with custom source, authenticator, and validator functions.
61
+ The `CreateAuthDecorator` function creates a reusable authentication decorator from custom source, authenticator, and validator functions. `validateApiKey` in the example below belongs to your application.
58
62
 
59
- ```typescript
63
+ ```typescript fragment
60
64
  import { CreateAuthDecorator } from "@antelopejs/interface-auth";
61
65
  import type { IncomingMessage } from "node:http";
62
66
 
@@ -85,28 +89,28 @@ export const ApiKeyAuth = CreateAuthDecorator({
85
89
  });
86
90
  ```
87
91
 
88
- `validateApiKey` is your application's lookup and verification function. Returning `null` for a missing or invalid key would allow the handler to run with `null`; this example throws instead.
92
+ `validateApiKey` is your application's lookup and verification function. If the authenticator returned `null` for a missing or invalid key, the handler would run with `null`. This example throws instead.
89
93
 
90
94
  ### `CreateAuthDecorator` options
91
95
 
92
96
  The function accepts an object with the following properties:
93
97
 
94
- | Property | Type | Description |
95
- | ---------------------- | --------------------- | --------------------------------------------------------------- |
96
- | `source` | `AuthSource` | Extracts the token from the request (defaults to header/cookie) |
97
- | `authenticator` | `AuthVerifier<T>` | Verifies the token and returns the payload |
98
- | `authenticatorOptions` | `VerifyOptions` | Options passed to the authenticator |
99
- | `validator` | `AuthValidator<T, R>` | Validates and transforms the authenticated data |
98
+ | Property | Type | Description |
99
+ | ---------------------- | --------------------- | --------------------------------------------------------------------- |
100
+ | `source` | `AuthSource` | Extracts the token from the request. Defaults to header, then cookie. |
101
+ | `authenticator` | `AuthVerifier<T>` | Verifies the token and returns the payload |
102
+ | `authenticatorOptions` | `VerifyOptions` | Options passed to the authenticator |
103
+ | `validator` | `AuthValidator<T, R>` | Validates and transforms the authenticated data |
100
104
 
101
- All properties are optional. The default source reads the header/cookie, the default authenticator calls `ValidateRaw`, and the default verification options are `{}`. Without a validator, the verified payload is passed through unchanged.
105
+ All properties are optional. The default source reads the header, then the cookie. The default authenticator calls `ValidateRaw`, and the default verification options are `{}`. Without a validator, the decorator injects the verified payload unchanged.
102
106
 
103
- `T` and `R` follow from the callbacks. Without an `authenticator`, `T` is `AuthClaims` (`string | JsonObject`), so a validator checks the claims before reading them, as in `AdminAuth` above. With an `authenticator`, `T` is what it returns, and the validator receives that type. Naming the type arguments explicitly is `CreateAuthDecorator<T, R>` with an `authenticator`; a single type argument names `R` when there is no `authenticator` and `T` when there is one.
107
+ TypeScript infers `T` and `R` from the callbacks. Without an `authenticator`, `T` is `AuthClaims`, which is `string | JsonObject`. A validator then checks the claims before it reads them, as in `AdminAuth` above. With an `authenticator`, `T` is what the authenticator returns, and the validator receives that type. To name both type arguments, write `CreateAuthDecorator<T, R>` with an `authenticator`. A single type argument names `R` when there is no `authenticator`, and `T` when there is one.
104
108
 
105
- A validator passed to a decorator call replaces the configured validator; the two do not compose. Return a transformed value to inject it, or throw to deny access. Returning `false` or `null` does not reject the request. A custom authenticator that accepts a missing token also permits it unless a validator throws.
109
+ A validator passed to a decorator call replaces the configured validator. The two do not compose. Return a transformed value to inject it, or throw to deny access. Returning `false` or `null` does not reject the request. A custom authenticator that accepts a missing token lets the request through unless a validator throws.
106
110
 
107
111
  ## Class-level authentication
108
112
 
109
- 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.
113
+ Apply the `@Authentication` decorator to a controller class to require authentication on every route of that controller. You do not need to decorate each handler.
110
114
 
111
115
  ```typescript
112
116
  import { Controller, Get, Post } from "@antelopejs/interface-api";
@@ -149,7 +153,7 @@ class AdminController extends Controller("/admin") {
149
153
 
150
154
  ## Property-level authentication
151
155
 
152
- Apply `@Authentication` to a class property to access the authenticated user data throughout the controller. The property is populated automatically for each request.
156
+ Apply `@Authentication` to a class property to read the authenticated user data in every handler of the controller. The API module sets the property on each request.
153
157
 
154
158
  ```typescript
155
159
  import { Controller, Get } from "@antelopejs/interface-api";
@@ -177,7 +181,7 @@ class UserController extends Controller("/users") {
177
181
 
178
182
  ## Decorator scope summary
179
183
 
180
- The `@Authentication` decorator (and any custom decorator created with `CreateAuthDecorator`) can be applied at three levels:
184
+ The `@Authentication` decorator, and any custom decorator that `CreateAuthDecorator` creates, applies at three levels:
181
185
 
182
186
  | Scope | Effect |
183
187
  | --------- | --------------------------------------------------------------------- |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/interface-auth",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "AntelopeJS interface for token authentication: sign and verify tokens and inject the verified payload into API handlers",
5
5
  "keywords": [
6
6
  "antelopejs",
@@ -59,9 +59,9 @@
59
59
  "devDependencies": {
60
60
  "@antelopejs/auth-jwt": "1.0.3",
61
61
  "@antelopejs/core": "^1.16.0",
62
- "@antelopejs/interface-api": "^0.0.15",
63
- "@antelopejs/interface-core": "^0.2.4",
64
- "@antelopejs/tooling-configs": "^0.2.11",
62
+ "@antelopejs/interface-api": "^0.2.0",
63
+ "@antelopejs/interface-core": "^0.4.0",
64
+ "@antelopejs/tooling-configs": "^0.2.17",
65
65
  "@types/chai": "^4.3.20",
66
66
  "@types/mocha": "^10.0.10",
67
67
  "@types/node": "^22.19.15",
@@ -84,10 +84,19 @@
84
84
  "@antelopejs/interface-core": ">=0.2.4 <1.0.0"
85
85
  },
86
86
  "packageManager": "pnpm@10.6.5",
87
+ "pnpm": {
88
+ "overrides": {
89
+ "@antelopejs/auth-jwt>@antelopejs/interface-auth": "link:.",
90
+ "@antelopejs/interface-core": "0.4.0"
91
+ }
92
+ },
87
93
  "antelopeJs": {
88
94
  "test": "src/antelope.test.ts",
89
95
  "skills": [
90
96
  "./skills"
91
- ]
97
+ ],
98
+ "docs": {
99
+ "standard": true
100
+ }
92
101
  }
93
102
  }