@moon-x/node-sdk 0.1.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 +152 -0
- package/dist/index.d.mts +163 -0
- package/dist/index.d.ts +163 -0
- package/dist/index.js +493 -0
- package/dist/index.mjs +454 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @moon-x/node-sdk
|
|
2
|
+
|
|
3
|
+
MoonX server-side SDK for Node.js. Verify MoonX-issued access and identity tokens with **zero runtime dependencies**.
|
|
4
|
+
|
|
5
|
+
Works in Node 18+, Cloudflare Workers, Vercel Edge, Bun, and Deno — anywhere `globalThis.crypto.subtle` and `fetch` are available.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i @moon-x/node-sdk
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @moon-x/node-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { MoonXClient } from "@moon-x/node-sdk";
|
|
19
|
+
|
|
20
|
+
const moonx = new MoonXClient({
|
|
21
|
+
publishableKey: process.env.MOONX_PUBLISHABLE_KEY!,
|
|
22
|
+
issuer: process.env.MOONX_AUTH_ISSUER, // optional, defaults to https://api.moonx-dev.com
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// In a Next.js route / Express handler / etc.
|
|
26
|
+
const session = await moonx.auth.verifySession({
|
|
27
|
+
accessToken: req.headers["x-moonx-access-token"]!,
|
|
28
|
+
identityToken: req.headers["x-moonx-identity-token"],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// session.access.sub — user id
|
|
32
|
+
// session.access.sid — session id
|
|
33
|
+
// session.identity?.email — OIDC profile claim (present when identity token forwarded)
|
|
34
|
+
// session.identity?.name
|
|
35
|
+
// session.identity?.picture
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## What it does
|
|
39
|
+
|
|
40
|
+
When a MoonX-authenticated user calls your backend, the request carries one or both of:
|
|
41
|
+
|
|
42
|
+
| Header | Token | Carries |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `X-MoonX-Access-Token` | Access token | Minimal authorization claims (`sub`, `sid`, `aud`, `iss`, `exp`) |
|
|
45
|
+
| `X-MoonX-Identity-Token` | Identity token | OIDC profile claims (`email`, `name`, `picture`, etc.) |
|
|
46
|
+
|
|
47
|
+
`verifySession()` runs the full canonical check on both:
|
|
48
|
+
|
|
49
|
+
1. Pin **audience** to your app id (rejects tokens from other MoonX apps even if cryptographically valid).
|
|
50
|
+
2. Pin **issuer** to your configured MoonX deployment.
|
|
51
|
+
3. Fetch the per-app public **JWKS** from MoonX (cached 5 min by default).
|
|
52
|
+
4. Verify the **ES256 signature** against the fetched key.
|
|
53
|
+
5. Check the token hasn't **expired**.
|
|
54
|
+
6. (Identity token path) Verify the identity token's `sub` matches the access token's `sub` — closes the swap-in-someone-else's-identity-token attack.
|
|
55
|
+
|
|
56
|
+
No shared secret with MoonX is required. The verification runs entirely against the public JWKS.
|
|
57
|
+
|
|
58
|
+
## API
|
|
59
|
+
|
|
60
|
+
### `new MoonXClient(config)`
|
|
61
|
+
|
|
62
|
+
Construct once per process. Holds in-memory caches; reuse across requests.
|
|
63
|
+
|
|
64
|
+
| Field | Type | Required | Default |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| `publishableKey` | `string` | Yes | — |
|
|
67
|
+
| `secretKey` | `string` | No (v0.1 unused) | — |
|
|
68
|
+
| `issuer` | `string` | No | `https://api.moonx-dev.com` |
|
|
69
|
+
| `baseUrl` | `string` | No | Same as `issuer` |
|
|
70
|
+
| `jwksTtlMs` | `number` | No | `300_000` (5 min) |
|
|
71
|
+
| `appResolveTtlMs` | `number` | No | `3_600_000` (1 hour) |
|
|
72
|
+
| `fetch` | `typeof fetch` | No | `globalThis.fetch` |
|
|
73
|
+
|
|
74
|
+
The publishable key (`moon_pk_*`) is the same one your iframe / browser SDK uses. It's safe to put in any env var, but in node-sdk it typically reads from a server-only env var alongside the secret key. The secret key (`moon_sk_*`) field is reserved for v0.2 (data + swaps modules).
|
|
75
|
+
|
|
76
|
+
### `client.auth.verifyAccessToken(token)`
|
|
77
|
+
|
|
78
|
+
Returns `Promise<AccessTokenClaims>`. Throws a `MoonXError` subclass on any failure.
|
|
79
|
+
|
|
80
|
+
### `client.auth.verifyIdentityToken(token)`
|
|
81
|
+
|
|
82
|
+
Returns `Promise<IdentityTokenClaims>`. Throws a `MoonXError` subclass on any failure.
|
|
83
|
+
|
|
84
|
+
### `client.auth.verifySession({ accessToken, identityToken? })`
|
|
85
|
+
|
|
86
|
+
Returns `Promise<{ access: AccessTokenClaims, identity: IdentityTokenClaims | null }>`. Identity is `null` when the caller didn't forward an identity token.
|
|
87
|
+
|
|
88
|
+
Canonical entry point — use this from request handlers. Cross-checks the two tokens' subjects when both are present.
|
|
89
|
+
|
|
90
|
+
## Errors
|
|
91
|
+
|
|
92
|
+
All thrown errors extend `MoonXError`, which carries a `.code` property for programmatic handling:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import {
|
|
96
|
+
MoonXError,
|
|
97
|
+
ExpiredTokenError,
|
|
98
|
+
InvalidTokenError,
|
|
99
|
+
AudienceMismatchError,
|
|
100
|
+
SubjectMismatchError,
|
|
101
|
+
// ...
|
|
102
|
+
} from "@moon-x/node-sdk";
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
await moonx.auth.verifySession({ accessToken, identityToken });
|
|
106
|
+
} catch (err) {
|
|
107
|
+
if (err instanceof ExpiredTokenError) {
|
|
108
|
+
return new Response("session expired", { status: 401 });
|
|
109
|
+
}
|
|
110
|
+
if (err instanceof MoonXError) {
|
|
111
|
+
return new Response(err.message, { status: 401 });
|
|
112
|
+
}
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Error codes
|
|
118
|
+
|
|
119
|
+
| Class | `.code` | Meaning |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `MalformedTokenError` | `malformed_token` | Not a well-formed JWT |
|
|
122
|
+
| `InvalidTokenError` | `invalid_signature` | Signature didn't verify against the JWKS |
|
|
123
|
+
| `ExpiredTokenError` | `expired_token` | `exp` claim is in the past |
|
|
124
|
+
| `AudienceMismatchError` | `audience_mismatch` | Token's `aud` ≠ this client's app id |
|
|
125
|
+
| `IssuerMismatchError` | `issuer_mismatch` | Token's `iss` ≠ configured issuer |
|
|
126
|
+
| `SubjectMismatchError` | `subject_mismatch` | Identity token's `sub` ≠ access token's `sub` |
|
|
127
|
+
| `KidMismatchError` | `kid_mismatch` | Token's `kid` ≠ current JWKS key id (likely rotation) |
|
|
128
|
+
| `UnsupportedAlgorithmError` | `unsupported_algorithm` | Token uses something other than ES256 |
|
|
129
|
+
| `JwksFetchError` | `jwks_fetch_failed` | Couldn't fetch the JWKS from MoonX |
|
|
130
|
+
| `AppResolutionError` | `app_resolution_failed` | Publishable-key → app-id lookup failed |
|
|
131
|
+
| `ConfigurationError` | `configuration_error` | Bad `MoonXClient` config (e.g. swapped pk/sk) |
|
|
132
|
+
|
|
133
|
+
### Type imports
|
|
134
|
+
|
|
135
|
+
`AccessTokenClaims`, `IdentityTokenClaims`, `BaseTokenClaims`, and `VerifiedSession` are also exported from `@moon-x/core/types` — the single source of truth shared with the browser + RN SDKs. Either import path works:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
// From node-sdk (convenience re-export):
|
|
139
|
+
import type { AccessTokenClaims } from "@moon-x/node-sdk";
|
|
140
|
+
|
|
141
|
+
// From core directly (matches the browser SDK call sites):
|
|
142
|
+
import type { AccessTokenClaims } from "@moon-x/core/types";
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Why no JWT library?
|
|
146
|
+
|
|
147
|
+
Auth providers ship server SDKs partly to abstract away `jose`-style JWT libraries, but every dependency is a supply-chain surface. This SDK uses only Web Crypto (`globalThis.crypto.subtle`) and `fetch`, both Node 18+ standard library. Result: a single `npm install` line on your audit.
|
|
148
|
+
|
|
149
|
+
## Roadmap
|
|
150
|
+
|
|
151
|
+
- **v0.1 (current)** — auth: `verifyAccessToken`, `verifyIdentityToken`, `verifySession`.
|
|
152
|
+
- **v0.2 (pending [MX-124](https://linear.app/moonpay/issue/MX-124))** — adds `client.tokens.*`, `client.wallets.*`, `client.swaps.*` once the backend's secret-key middleware lands.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { AccessTokenClaims, IdentityTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
2
|
+
export { AccessTokenClaims, BaseTokenClaims, IdentityTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
3
|
+
|
|
4
|
+
interface AuthOptions {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
publishableKey: string;
|
|
7
|
+
expectedIssuer: string;
|
|
8
|
+
jwksTtlMs?: number;
|
|
9
|
+
appResolveTtlMs?: number;
|
|
10
|
+
fetch?: typeof fetch;
|
|
11
|
+
}
|
|
12
|
+
declare class Auth {
|
|
13
|
+
private readonly resolver;
|
|
14
|
+
private readonly jwks;
|
|
15
|
+
private readonly expectedIssuer;
|
|
16
|
+
constructor(opts: AuthOptions);
|
|
17
|
+
/**
|
|
18
|
+
* Verify an access token. Returns the claims on success; throws a
|
|
19
|
+
* typed `MoonXError` subclass on any failure.
|
|
20
|
+
*/
|
|
21
|
+
verifyAccessToken(token: string): Promise<AccessTokenClaims>;
|
|
22
|
+
/**
|
|
23
|
+
* Verify an identity token. Returns the OIDC profile claims on
|
|
24
|
+
* success; throws a typed `MoonXError` subclass on any failure.
|
|
25
|
+
*/
|
|
26
|
+
verifyIdentityToken(token: string): Promise<IdentityTokenClaims>;
|
|
27
|
+
/**
|
|
28
|
+
* Verify both tokens (identity optional). Cross-checks that the
|
|
29
|
+
* identity token's subject matches the access token's subject so a
|
|
30
|
+
* caller can't swap in another user's (still-valid) identity token.
|
|
31
|
+
*
|
|
32
|
+
* Canonical entry point for "this request is authorized AND we know
|
|
33
|
+
* who the user is" — call this from your request handlers.
|
|
34
|
+
*/
|
|
35
|
+
verifySession(args: {
|
|
36
|
+
accessToken: string;
|
|
37
|
+
identityToken?: string | null;
|
|
38
|
+
}): Promise<VerifiedSession>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface MoonXClientConfig {
|
|
42
|
+
/**
|
|
43
|
+
* Required. The publishable key (`moon_pk_*`) for your MoonX app.
|
|
44
|
+
* Used to resolve the app id (which scopes audience pinning and
|
|
45
|
+
* JWKS lookups). Safe to also expose to the browser — that's what
|
|
46
|
+
* publishable keys are for — but in node-sdk it typically reads
|
|
47
|
+
* from a server env var.
|
|
48
|
+
*/
|
|
49
|
+
publishableKey: string;
|
|
50
|
+
/**
|
|
51
|
+
* Optional. The secret key (`moon_sk_*`) for your MoonX app. Required
|
|
52
|
+
* for privileged endpoints (datalayer, swaps) — not used by v0.1
|
|
53
|
+
* (auth-only). Reserved for the v0.2 surface expansion.
|
|
54
|
+
*
|
|
55
|
+
* NEVER hardcode. NEVER expose to the browser. Always read from a
|
|
56
|
+
* server-only env var.
|
|
57
|
+
*/
|
|
58
|
+
secretKey?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Optional. The MoonX deployment that issued your tokens. Defaults
|
|
61
|
+
* to `https://api.moonx-dev.com`. Override when running against a
|
|
62
|
+
* different environment.
|
|
63
|
+
*
|
|
64
|
+
* If unset and the default doesn't match your deployment, every
|
|
65
|
+
* token will fail the issuer check with a clean `IssuerMismatchError`
|
|
66
|
+
* — easier to debug than a silent 401.
|
|
67
|
+
*/
|
|
68
|
+
issuer?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Optional. Base URL for MoonX API calls. Defaults to the same value
|
|
71
|
+
* as `issuer` when unset.
|
|
72
|
+
*/
|
|
73
|
+
baseUrl?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Optional. JWKS cache TTL in milliseconds. Default 5 minutes. Lower
|
|
76
|
+
* if you're concerned about key rotation responsiveness; higher if
|
|
77
|
+
* you want fewer round-trips.
|
|
78
|
+
*/
|
|
79
|
+
jwksTtlMs?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Optional. Cache TTL in milliseconds for the publishable-key → app-id
|
|
82
|
+
* lookup. Default 1 hour. The mapping is effectively immutable, so a
|
|
83
|
+
* long TTL is safe.
|
|
84
|
+
*/
|
|
85
|
+
appResolveTtlMs?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Optional. Override `fetch`. Useful in tests. Defaults to
|
|
88
|
+
* `globalThis.fetch`.
|
|
89
|
+
*/
|
|
90
|
+
fetch?: typeof fetch;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* MoonXClient is the entry point for the node SDK. Construct once per
|
|
95
|
+
* process and reuse across requests — the client holds in-memory caches
|
|
96
|
+
* for the publishable-key → app-id mapping and the per-app JWKS.
|
|
97
|
+
*
|
|
98
|
+
* import { MoonXClient } from "@moon-x/node-sdk";
|
|
99
|
+
*
|
|
100
|
+
* const moonx = new MoonXClient({
|
|
101
|
+
* publishableKey: process.env.MOONX_PUBLISHABLE_KEY!,
|
|
102
|
+
* issuer: process.env.MOONX_AUTH_ISSUER,
|
|
103
|
+
* });
|
|
104
|
+
*
|
|
105
|
+
* // In a Next.js route handler / Express handler / etc.
|
|
106
|
+
* const session = await moonx.auth.verifySession({
|
|
107
|
+
* accessToken: req.headers["x-moonx-access-token"]!,
|
|
108
|
+
* identityToken: req.headers["x-moonx-identity-token"],
|
|
109
|
+
* });
|
|
110
|
+
* // session.access.sub — user id
|
|
111
|
+
* // session.access.sid — session id
|
|
112
|
+
* // session.identity?.email — OIDC profile claim (when identity token sent)
|
|
113
|
+
* // session.identity?.name — etc.
|
|
114
|
+
*
|
|
115
|
+
* v0.1 ships the `auth` namespace only. The `tokens`, `wallets`, and
|
|
116
|
+
* `swaps` namespaces will land in v0.2 once the secret-key middleware
|
|
117
|
+
* (MX-124) ships on the backend.
|
|
118
|
+
*/
|
|
119
|
+
declare class MoonXClient {
|
|
120
|
+
readonly auth: Auth;
|
|
121
|
+
constructor(input: MoonXClientConfig);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type MoonXErrorCode = "malformed_token" | "invalid_signature" | "expired_token" | "audience_mismatch" | "issuer_mismatch" | "subject_mismatch" | "kid_mismatch" | "unsupported_algorithm" | "jwks_fetch_failed" | "app_resolution_failed" | "configuration_error";
|
|
125
|
+
declare class MoonXError extends Error {
|
|
126
|
+
readonly code: MoonXErrorCode;
|
|
127
|
+
constructor(code: MoonXErrorCode, message: string);
|
|
128
|
+
}
|
|
129
|
+
declare class MalformedTokenError extends MoonXError {
|
|
130
|
+
constructor(message?: string);
|
|
131
|
+
}
|
|
132
|
+
declare class InvalidTokenError extends MoonXError {
|
|
133
|
+
constructor(message?: string);
|
|
134
|
+
}
|
|
135
|
+
declare class ExpiredTokenError extends MoonXError {
|
|
136
|
+
constructor(message?: string);
|
|
137
|
+
}
|
|
138
|
+
declare class AudienceMismatchError extends MoonXError {
|
|
139
|
+
constructor(expected: string, got: string | string[], message?: string);
|
|
140
|
+
}
|
|
141
|
+
declare class IssuerMismatchError extends MoonXError {
|
|
142
|
+
constructor(expected: string, got: string, message?: string);
|
|
143
|
+
}
|
|
144
|
+
declare class SubjectMismatchError extends MoonXError {
|
|
145
|
+
constructor(message?: string);
|
|
146
|
+
}
|
|
147
|
+
declare class KidMismatchError extends MoonXError {
|
|
148
|
+
constructor(message?: string);
|
|
149
|
+
}
|
|
150
|
+
declare class UnsupportedAlgorithmError extends MoonXError {
|
|
151
|
+
constructor(alg: string);
|
|
152
|
+
}
|
|
153
|
+
declare class JwksFetchError extends MoonXError {
|
|
154
|
+
constructor(message: string);
|
|
155
|
+
}
|
|
156
|
+
declare class AppResolutionError extends MoonXError {
|
|
157
|
+
constructor(message: string);
|
|
158
|
+
}
|
|
159
|
+
declare class ConfigurationError extends MoonXError {
|
|
160
|
+
constructor(message: string);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { AppResolutionError, AudienceMismatchError, ConfigurationError, ExpiredTokenError, InvalidTokenError, IssuerMismatchError, JwksFetchError, KidMismatchError, MalformedTokenError, MoonXClient, type MoonXClientConfig, MoonXError, type MoonXErrorCode, SubjectMismatchError, UnsupportedAlgorithmError };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { AccessTokenClaims, IdentityTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
2
|
+
export { AccessTokenClaims, BaseTokenClaims, IdentityTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
3
|
+
|
|
4
|
+
interface AuthOptions {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
publishableKey: string;
|
|
7
|
+
expectedIssuer: string;
|
|
8
|
+
jwksTtlMs?: number;
|
|
9
|
+
appResolveTtlMs?: number;
|
|
10
|
+
fetch?: typeof fetch;
|
|
11
|
+
}
|
|
12
|
+
declare class Auth {
|
|
13
|
+
private readonly resolver;
|
|
14
|
+
private readonly jwks;
|
|
15
|
+
private readonly expectedIssuer;
|
|
16
|
+
constructor(opts: AuthOptions);
|
|
17
|
+
/**
|
|
18
|
+
* Verify an access token. Returns the claims on success; throws a
|
|
19
|
+
* typed `MoonXError` subclass on any failure.
|
|
20
|
+
*/
|
|
21
|
+
verifyAccessToken(token: string): Promise<AccessTokenClaims>;
|
|
22
|
+
/**
|
|
23
|
+
* Verify an identity token. Returns the OIDC profile claims on
|
|
24
|
+
* success; throws a typed `MoonXError` subclass on any failure.
|
|
25
|
+
*/
|
|
26
|
+
verifyIdentityToken(token: string): Promise<IdentityTokenClaims>;
|
|
27
|
+
/**
|
|
28
|
+
* Verify both tokens (identity optional). Cross-checks that the
|
|
29
|
+
* identity token's subject matches the access token's subject so a
|
|
30
|
+
* caller can't swap in another user's (still-valid) identity token.
|
|
31
|
+
*
|
|
32
|
+
* Canonical entry point for "this request is authorized AND we know
|
|
33
|
+
* who the user is" — call this from your request handlers.
|
|
34
|
+
*/
|
|
35
|
+
verifySession(args: {
|
|
36
|
+
accessToken: string;
|
|
37
|
+
identityToken?: string | null;
|
|
38
|
+
}): Promise<VerifiedSession>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface MoonXClientConfig {
|
|
42
|
+
/**
|
|
43
|
+
* Required. The publishable key (`moon_pk_*`) for your MoonX app.
|
|
44
|
+
* Used to resolve the app id (which scopes audience pinning and
|
|
45
|
+
* JWKS lookups). Safe to also expose to the browser — that's what
|
|
46
|
+
* publishable keys are for — but in node-sdk it typically reads
|
|
47
|
+
* from a server env var.
|
|
48
|
+
*/
|
|
49
|
+
publishableKey: string;
|
|
50
|
+
/**
|
|
51
|
+
* Optional. The secret key (`moon_sk_*`) for your MoonX app. Required
|
|
52
|
+
* for privileged endpoints (datalayer, swaps) — not used by v0.1
|
|
53
|
+
* (auth-only). Reserved for the v0.2 surface expansion.
|
|
54
|
+
*
|
|
55
|
+
* NEVER hardcode. NEVER expose to the browser. Always read from a
|
|
56
|
+
* server-only env var.
|
|
57
|
+
*/
|
|
58
|
+
secretKey?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Optional. The MoonX deployment that issued your tokens. Defaults
|
|
61
|
+
* to `https://api.moonx-dev.com`. Override when running against a
|
|
62
|
+
* different environment.
|
|
63
|
+
*
|
|
64
|
+
* If unset and the default doesn't match your deployment, every
|
|
65
|
+
* token will fail the issuer check with a clean `IssuerMismatchError`
|
|
66
|
+
* — easier to debug than a silent 401.
|
|
67
|
+
*/
|
|
68
|
+
issuer?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Optional. Base URL for MoonX API calls. Defaults to the same value
|
|
71
|
+
* as `issuer` when unset.
|
|
72
|
+
*/
|
|
73
|
+
baseUrl?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Optional. JWKS cache TTL in milliseconds. Default 5 minutes. Lower
|
|
76
|
+
* if you're concerned about key rotation responsiveness; higher if
|
|
77
|
+
* you want fewer round-trips.
|
|
78
|
+
*/
|
|
79
|
+
jwksTtlMs?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Optional. Cache TTL in milliseconds for the publishable-key → app-id
|
|
82
|
+
* lookup. Default 1 hour. The mapping is effectively immutable, so a
|
|
83
|
+
* long TTL is safe.
|
|
84
|
+
*/
|
|
85
|
+
appResolveTtlMs?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Optional. Override `fetch`. Useful in tests. Defaults to
|
|
88
|
+
* `globalThis.fetch`.
|
|
89
|
+
*/
|
|
90
|
+
fetch?: typeof fetch;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* MoonXClient is the entry point for the node SDK. Construct once per
|
|
95
|
+
* process and reuse across requests — the client holds in-memory caches
|
|
96
|
+
* for the publishable-key → app-id mapping and the per-app JWKS.
|
|
97
|
+
*
|
|
98
|
+
* import { MoonXClient } from "@moon-x/node-sdk";
|
|
99
|
+
*
|
|
100
|
+
* const moonx = new MoonXClient({
|
|
101
|
+
* publishableKey: process.env.MOONX_PUBLISHABLE_KEY!,
|
|
102
|
+
* issuer: process.env.MOONX_AUTH_ISSUER,
|
|
103
|
+
* });
|
|
104
|
+
*
|
|
105
|
+
* // In a Next.js route handler / Express handler / etc.
|
|
106
|
+
* const session = await moonx.auth.verifySession({
|
|
107
|
+
* accessToken: req.headers["x-moonx-access-token"]!,
|
|
108
|
+
* identityToken: req.headers["x-moonx-identity-token"],
|
|
109
|
+
* });
|
|
110
|
+
* // session.access.sub — user id
|
|
111
|
+
* // session.access.sid — session id
|
|
112
|
+
* // session.identity?.email — OIDC profile claim (when identity token sent)
|
|
113
|
+
* // session.identity?.name — etc.
|
|
114
|
+
*
|
|
115
|
+
* v0.1 ships the `auth` namespace only. The `tokens`, `wallets`, and
|
|
116
|
+
* `swaps` namespaces will land in v0.2 once the secret-key middleware
|
|
117
|
+
* (MX-124) ships on the backend.
|
|
118
|
+
*/
|
|
119
|
+
declare class MoonXClient {
|
|
120
|
+
readonly auth: Auth;
|
|
121
|
+
constructor(input: MoonXClientConfig);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type MoonXErrorCode = "malformed_token" | "invalid_signature" | "expired_token" | "audience_mismatch" | "issuer_mismatch" | "subject_mismatch" | "kid_mismatch" | "unsupported_algorithm" | "jwks_fetch_failed" | "app_resolution_failed" | "configuration_error";
|
|
125
|
+
declare class MoonXError extends Error {
|
|
126
|
+
readonly code: MoonXErrorCode;
|
|
127
|
+
constructor(code: MoonXErrorCode, message: string);
|
|
128
|
+
}
|
|
129
|
+
declare class MalformedTokenError extends MoonXError {
|
|
130
|
+
constructor(message?: string);
|
|
131
|
+
}
|
|
132
|
+
declare class InvalidTokenError extends MoonXError {
|
|
133
|
+
constructor(message?: string);
|
|
134
|
+
}
|
|
135
|
+
declare class ExpiredTokenError extends MoonXError {
|
|
136
|
+
constructor(message?: string);
|
|
137
|
+
}
|
|
138
|
+
declare class AudienceMismatchError extends MoonXError {
|
|
139
|
+
constructor(expected: string, got: string | string[], message?: string);
|
|
140
|
+
}
|
|
141
|
+
declare class IssuerMismatchError extends MoonXError {
|
|
142
|
+
constructor(expected: string, got: string, message?: string);
|
|
143
|
+
}
|
|
144
|
+
declare class SubjectMismatchError extends MoonXError {
|
|
145
|
+
constructor(message?: string);
|
|
146
|
+
}
|
|
147
|
+
declare class KidMismatchError extends MoonXError {
|
|
148
|
+
constructor(message?: string);
|
|
149
|
+
}
|
|
150
|
+
declare class UnsupportedAlgorithmError extends MoonXError {
|
|
151
|
+
constructor(alg: string);
|
|
152
|
+
}
|
|
153
|
+
declare class JwksFetchError extends MoonXError {
|
|
154
|
+
constructor(message: string);
|
|
155
|
+
}
|
|
156
|
+
declare class AppResolutionError extends MoonXError {
|
|
157
|
+
constructor(message: string);
|
|
158
|
+
}
|
|
159
|
+
declare class ConfigurationError extends MoonXError {
|
|
160
|
+
constructor(message: string);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { AppResolutionError, AudienceMismatchError, ConfigurationError, ExpiredTokenError, InvalidTokenError, IssuerMismatchError, JwksFetchError, KidMismatchError, MalformedTokenError, MoonXClient, type MoonXClientConfig, MoonXError, type MoonXErrorCode, SubjectMismatchError, UnsupportedAlgorithmError };
|