@atlasauth/backend 0.14.1 → 0.16.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/access-control.d.ts +53 -0
  3. package/dist/access-control.js +46 -0
  4. package/dist/access-control.js.map +1 -0
  5. package/dist/algs.d.ts +7 -0
  6. package/dist/algs.js +11 -0
  7. package/dist/algs.js.map +1 -0
  8. package/dist/botid.d.ts +70 -0
  9. package/dist/botid.js +88 -0
  10. package/dist/botid.js.map +1 -0
  11. package/dist/client/action-gallery.d.ts +215 -0
  12. package/dist/client/action-gallery.js +66 -0
  13. package/dist/client/action-gallery.js.map +1 -0
  14. package/dist/client/actions.d.ts +21 -0
  15. package/dist/client/actions.js.map +1 -1
  16. package/dist/client/api-keys.d.ts +49 -4
  17. package/dist/client/api-keys.js +6 -2
  18. package/dist/client/api-keys.js.map +1 -1
  19. package/dist/client/app-roles.d.ts +76 -0
  20. package/dist/client/app-roles.js +39 -0
  21. package/dist/client/app-roles.js.map +1 -0
  22. package/dist/client/attack-protection.d.ts +33 -1
  23. package/dist/client/attack-protection.js.map +1 -1
  24. package/dist/client/billing-plans.d.ts +93 -0
  25. package/dist/client/billing-plans.js +31 -0
  26. package/dist/client/billing-plans.js.map +1 -1
  27. package/dist/client/custom-oauth-providers.d.ts +243 -0
  28. package/dist/client/custom-oauth-providers.js +60 -0
  29. package/dist/client/custom-oauth-providers.js.map +1 -0
  30. package/dist/client/email-templates.d.ts +1 -1
  31. package/dist/client/email-templates.js.map +1 -1
  32. package/dist/client/index.d.ts +157 -3
  33. package/dist/client/index.js +11 -0
  34. package/dist/client/index.js.map +1 -1
  35. package/dist/client/instance-security.d.ts +104 -0
  36. package/dist/client/instance-security.js +28 -0
  37. package/dist/client/instance-security.js.map +1 -1
  38. package/dist/client/notifications.d.ts +1 -1
  39. package/dist/client/notifications.js.map +1 -1
  40. package/dist/client/oauth-clients.d.ts +84 -2
  41. package/dist/client/oauth-clients.js +13 -0
  42. package/dist/client/oauth-clients.js.map +1 -1
  43. package/dist/client/referrals.d.ts +1 -1
  44. package/dist/client/resource-servers.d.ts +34 -5
  45. package/dist/client/resource-servers.js.map +1 -1
  46. package/dist/client/risk-based-mfa.d.ts +3 -0
  47. package/dist/client/risk-based-mfa.js.map +1 -1
  48. package/dist/client/scim-tokens.d.ts +18 -0
  49. package/dist/client/scim-tokens.js +4 -0
  50. package/dist/client/scim-tokens.js.map +1 -1
  51. package/dist/client/sessions.d.ts +16 -0
  52. package/dist/client/sessions.js +15 -0
  53. package/dist/client/sessions.js.map +1 -1
  54. package/dist/client/sso-connections.d.ts +105 -0
  55. package/dist/client/sso-connections.js +29 -0
  56. package/dist/client/sso-connections.js.map +1 -1
  57. package/dist/client/users.d.ts +40 -4
  58. package/dist/client/users.js +8 -3
  59. package/dist/client/users.js.map +1 -1
  60. package/dist/index.d.ts +4 -0
  61. package/dist/index.js +18 -1
  62. package/dist/index.js.map +1 -1
  63. package/dist/logout-token.d.ts +1 -1
  64. package/dist/logout-token.js +3 -2
  65. package/dist/logout-token.js.map +1 -1
  66. package/dist/oauth-resource.d.ts +225 -0
  67. package/dist/oauth-resource.js +469 -0
  68. package/dist/oauth-resource.js.map +1 -0
  69. package/dist/oidc.d.ts +1 -1
  70. package/dist/oidc.js +5 -3
  71. package/dist/oidc.js.map +1 -1
  72. package/dist/referral-test-calls.d.ts +7 -7
  73. package/dist/referral-test-calls.js +2 -2
  74. package/dist/testing.d.ts +6 -4
  75. package/dist/testing.js +7 -6
  76. package/dist/testing.js.map +1 -1
  77. package/dist/verify.d.ts +11 -0
  78. package/dist/verify.js +15 -1
  79. package/dist/verify.js.map +1 -1
  80. package/package.json +3 -3
@@ -0,0 +1,225 @@
1
+ import { type Jwks } from './jwks-cache';
2
+ /**
3
+ * Protecting YOUR API — or your own MCP server — with access tokens Atlas
4
+ * issues to OAuth clients (authorization code, device, client credentials,
5
+ * token exchange). Atlas is the authorization server; your API is the
6
+ * resource server. This module:
7
+ * - verifies the access token locally against the instance JWKS (cached;
8
+ * no call to Atlas on the hot path): signature, `iss`, `exp`/`nbf`, that it
9
+ * IS an access token, and that its `aud` names your API (RFC 8707);
10
+ * - enforces required scopes;
11
+ * - enforces sender constraint: a DPoP-bound token (`cnf.jkt`) must arrive
12
+ * with a valid DPoP proof for the same key (RFC 9449), and is never accepted
13
+ * as a plain Bearer token;
14
+ * - answers failures with the RFC 6750 / RFC 9728 `WWW-Authenticate`
15
+ * challenge (`resource_metadata`, `insufficient_scope` + the scopes needed),
16
+ * which is exactly what an MCP client needs to discover how to sign in;
17
+ * - builds the RFC 9728 protected-resource metadata document to serve at
18
+ * `/.well-known/oauth-protected-resource` on your API's host.
19
+ * - accepts OPAQUE access tokens too (an API, client or instance set to the
20
+ * `opaque` format): with `introspection` configured, a token that is not a
21
+ * JWT is validated at Atlas's introspection endpoint (RFC 7662) with your
22
+ * API's own client credentials, and the answer is cached briefly;
23
+ * Framework-agnostic: hand it any request with `method`, `url` and `headers`.
24
+ */
25
+ /** Clock skew tolerated on `exp`/`nbf` and on DPoP proof `iat`. */
26
+ export declare const ACCESS_TOKEN_CLOCK_SKEW_SECONDS = 5;
27
+ /** How old a DPoP proof may be. */
28
+ export declare const DPOP_PROOF_MAX_AGE_SECONDS = 300;
29
+ export interface AccessTokenClaims {
30
+ iss: string;
31
+ sub: string;
32
+ aud?: string | string[];
33
+ exp: number;
34
+ iat?: number;
35
+ scope?: string;
36
+ client_id?: string;
37
+ azp?: string;
38
+ permissions?: string[];
39
+ cnf?: {
40
+ jkt?: string;
41
+ 'x5t#S256'?: string;
42
+ };
43
+ token_use?: string;
44
+ [claim: string]: unknown;
45
+ }
46
+ export interface ResourceRequestLike {
47
+ method?: string;
48
+ /** Absolute URL, or a path (combined with `resource` origin for the DPoP `htu` check). */
49
+ url?: string;
50
+ headers: Record<string, string | string[] | undefined> | {
51
+ get(name: string): string | null;
52
+ };
53
+ }
54
+ /** Replay guard for DPoP proof `jti`s. The in-memory one is for a single process. */
55
+ export interface DpopReplayStore {
56
+ /** Record `jti` until `expiresAt` (ms); return false when it was already seen. */
57
+ claim(jti: string, expiresAt: number): Promise<boolean> | boolean;
58
+ }
59
+ /**
60
+ * Server-provided DPoP nonces (RFC 9449 §8). `current()` is the nonce the API
61
+ * hands out in the `DPoP-Nonce` response header; `valid()` accepts the nonces
62
+ * still in force. A verifier given a source requires every DPoP proof to carry
63
+ * one, answering `use_dpop_nonce` (with a fresh nonce) otherwise.
64
+ */
65
+ export interface DpopNonceSource {
66
+ current(): string | Promise<string>;
67
+ valid(nonce: string): boolean | Promise<boolean>;
68
+ }
69
+ /**
70
+ * An in-process nonce source: a random nonce per window; the current and the
71
+ * previous window's nonce are accepted. Use it when one process serves the API
72
+ * (or with sticky routing); behind several processes, use
73
+ * {@link hmacDpopNonceSource} with a shared secret.
74
+ */
75
+ export declare function memoryDpopNonceSource(options?: {
76
+ windowSeconds?: number;
77
+ now?: () => number;
78
+ }): DpopNonceSource;
79
+ /**
80
+ * A stateless nonce source shared by every process holding the same secret (at
81
+ * least 32 bytes): the nonce for a window is base64url(HMAC-SHA256(secret,
82
+ * "atlas-dpop-nonce:" ‖ uint64-BE(window number))). A nonce is good in the window
83
+ * it was issued in and the next one. The derivation is the same in every Atlas
84
+ * server SDK, so services in different languages sharing the secret agree.
85
+ */
86
+ export declare function hmacDpopNonceSource(secret: string | Uint8Array, options?: {
87
+ windowSeconds?: number;
88
+ now?: () => number;
89
+ }): DpopNonceSource;
90
+ export declare function memoryDpopReplayStore(max?: number): DpopReplayStore;
91
+ export interface AccessTokenVerifierOptions {
92
+ /** Your Atlas instance's issuer (frontend API origin), e.g. https://clerk.example.com. */
93
+ issuer: string;
94
+ /**
95
+ * Your API's identifier (the Resource Server identifier registered in Atlas,
96
+ * RFC 8707 `resource`). The token's `aud` must contain one of these. Pass
97
+ * `false` only to accept tokens with no audience (userinfo-style tokens).
98
+ */
99
+ audience: string | readonly string[] | false;
100
+ /** Scopes every request must carry (all of them). */
101
+ requiredScopes?: readonly string[];
102
+ /** The JWKS URL; default `${issuer}/.well-known/jwks.json`. */
103
+ jwksUrl?: string;
104
+ /** A static key set (tests / offline). Mutually exclusive with `jwksUrl`. */
105
+ jwks?: Jwks;
106
+ /**
107
+ * Where your protected-resource metadata lives, advertised in every 401 as
108
+ * `resource_metadata` so an MCP / OAuth client can discover Atlas. Typically
109
+ * `https://api.example.com/.well-known/oauth-protected-resource`.
110
+ */
111
+ resourceMetadataUrl?: string;
112
+ /** Require a DPoP-bound token on every request (never accept plain Bearer). */
113
+ requireDpop?: boolean;
114
+ /** The public origin of this API, for DPoP `htu` when `request.url` is a path. */
115
+ publicOrigin?: string;
116
+ dpopReplayStore?: DpopReplayStore;
117
+ /**
118
+ * Require a server-provided nonce in every DPoP proof (RFC 9449 §8). A proof
119
+ * without a valid one is refused with `use_dpop_nonce`; every result carries
120
+ * `dpopNonce`, to send as the `DPoP-Nonce` response header (the framework
121
+ * adapters do). See {@link memoryDpopNonceSource} / {@link hmacDpopNonceSource}.
122
+ */
123
+ dpopNonces?: DpopNonceSource;
124
+ /** `WWW-Authenticate` realm. */
125
+ realm?: string;
126
+ /**
127
+ * Validate opaque access tokens (and, with `introspectJwts`, JWTs too) at
128
+ * Atlas's introspection endpoint. The client must be a confidential client
129
+ * your API lists in its `introspection_client_ids` (or the client the tokens
130
+ * are issued to).
131
+ */
132
+ introspection?: IntrospectionOptions;
133
+ fetchImpl?: typeof fetch;
134
+ now?: () => number;
135
+ }
136
+ export interface IntrospectionOptions {
137
+ clientId: string;
138
+ clientSecret: string;
139
+ /** Default `${issuer}/oauth2/introspect`. */
140
+ endpoint?: string;
141
+ /** How long an active answer is reused, in seconds (default 60; never past the token's `exp`). */
142
+ cacheTtlSeconds?: number;
143
+ /** How long an inactive answer is reused, in seconds (default 10; 0 disables). */
144
+ negativeCacheTtlSeconds?: number;
145
+ /** Most answers kept (default 10 000). */
146
+ cacheMax?: number;
147
+ /**
148
+ * Also introspect JWT access tokens, so a revoked grant or a banned user is
149
+ * refused before the token expires (one cached call per token). Default false:
150
+ * JWTs are verified locally.
151
+ */
152
+ introspectJwts?: boolean;
153
+ }
154
+ /**
155
+ * RFC 7662 introspection with a small TTL cache keyed by the token's SHA-256
156
+ * (the token itself is never kept). Returns the claims of an active token, or
157
+ * null for an inactive one; throws when Atlas could not be reached.
158
+ */
159
+ export declare function createIntrospector(issuer: string, options: IntrospectionOptions, deps?: {
160
+ fetchImpl?: typeof fetch;
161
+ now?: () => number;
162
+ }): (token: string) => Promise<AccessTokenClaims | null>;
163
+ export type AccessTokenErrorCode = 'invalid_request' | 'invalid_token' | 'insufficient_scope' | 'invalid_dpop_proof' | 'use_dpop_nonce';
164
+ export type AccessTokenResult = {
165
+ ok: true;
166
+ claims: AccessTokenClaims;
167
+ scopes: string[];
168
+ subject: string;
169
+ clientId: string | null;
170
+ dpopBound: boolean;
171
+ /** With `dpopNonces`: send as the `DPoP-Nonce` response header. */
172
+ dpopNonce?: string;
173
+ } | {
174
+ ok: false;
175
+ status: 400 | 401 | 403;
176
+ error: AccessTokenErrorCode | null;
177
+ description: string;
178
+ /** Set this response header verbatim. */
179
+ wwwAuthenticate: string;
180
+ /** With `dpopNonces`: send as the `DPoP-Nonce` response header (always, on `use_dpop_nonce`). */
181
+ dpopNonce?: string;
182
+ };
183
+ /**
184
+ * Build an RFC 6750 / RFC 9449 / RFC 9728 `WWW-Authenticate` challenge.
185
+ * Without an `error`, it is the bare "authentication required" challenge
186
+ * (no token was sent), as RFC 6750 §3.1 asks.
187
+ */
188
+ export declare function buildWwwAuthenticate(opts: {
189
+ scheme?: 'Bearer' | 'DPoP';
190
+ realm?: string;
191
+ error?: AccessTokenErrorCode | null;
192
+ description?: string;
193
+ scope?: readonly string[];
194
+ resourceMetadataUrl?: string;
195
+ dpopAlgs?: readonly string[];
196
+ }): string;
197
+ /**
198
+ * A reusable verifier (one JWKS cache for the life of the process). Call it per
199
+ * request; it never throws for a bad token — it returns the status + challenge.
200
+ */
201
+ export declare function createAccessTokenVerifier(options: AccessTokenVerifierOptions): (request: ResourceRequestLike, extra?: {
202
+ requiredScopes?: readonly string[];
203
+ }) => Promise<AccessTokenResult>;
204
+ /** One-shot form of {@link createAccessTokenVerifier} (builds a fresh JWKS cache each call — prefer the factory). */
205
+ export declare function verifyAccessToken(request: ResourceRequestLike, options: AccessTokenVerifierOptions): Promise<AccessTokenResult>;
206
+ /**
207
+ * The RFC 9728 protected-resource metadata document for your API. Serve it as
208
+ * JSON at `https://<your api host>/.well-known/oauth-protected-resource` (and,
209
+ * for a resource with a path, at `/.well-known/oauth-protected-resource<path>`),
210
+ * and point `resourceMetadataUrl` at it. Atlas can also serve this document for
211
+ * you when the API is registered with metadata publishing turned on.
212
+ */
213
+ export declare function protectedResourceMetadata(opts: {
214
+ /** Your API's identifier (the same value as the verifier's `audience`). */
215
+ resource: string;
216
+ /** Your Atlas instance issuer. */
217
+ issuer: string;
218
+ scopesSupported?: readonly string[];
219
+ resourceName?: string;
220
+ resourceDocumentation?: string;
221
+ /** Advertise that tokens must be DPoP-bound. */
222
+ dpopBoundAccessTokensRequired?: boolean;
223
+ }): Record<string, unknown>;
224
+ /** The RFC 9728 well-known path for a resource identifier (path-inserted form). */
225
+ export declare function protectedResourceMetadataPath(resource: string): string;