@nya-account/node-sdk 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,173 +1,187 @@
1
- # @nya-account/node-sdk
2
-
3
- Official Node.js SDK for [Nya Account](https://account.lolinya.net) SSO system.
4
-
5
- Provides a complete OAuth 2.1 / OIDC client with PKCE, JWT verification, and Express middleware.
6
-
7
- ## Installation
8
-
9
- ```bash
10
- npm install @nya-account/node-sdk
11
- # or
12
- pnpm add @nya-account/node-sdk
13
- # or
14
- yarn add @nya-account/node-sdk
15
- ```
16
-
17
- ## Quick Start
18
-
19
- ```typescript
20
- import { NyaAccountClient } from '@nya-account/node-sdk'
21
-
22
- const client = new NyaAccountClient({
23
- // See https://account.lolinya.net/docs/developer/service-endpoints#integration-endpoints
24
- issuer: 'https://account-api.edge.lolinya.net',
25
- clientId: 'my-app',
26
- clientSecret: 'my-secret',
27
- })
28
-
29
- // Create authorization URL (with PKCE)
30
- const { url, codeVerifier, state } = await client.createAuthorizationUrl({
31
- redirectUri: 'https://myapp.com/callback',
32
- scope: 'openid profile email',
33
- })
34
-
35
- // Exchange code for tokens
36
- const tokens = await client.exchangeCode({
37
- code: callbackCode,
38
- redirectUri: 'https://myapp.com/callback',
39
- codeVerifier,
40
- })
41
-
42
- // Get user info
43
- const userInfo = await client.getUserInfo(tokens.accessToken)
44
- ```
45
-
46
- ## Express Middleware
47
-
48
- ```typescript
49
- import express from 'express'
50
- import { NyaAccountClient } from '@nya-account/node-sdk'
51
- import { getAuth } from '@nya-account/node-sdk/express'
52
-
53
- const app = express()
54
- const client = new NyaAccountClient({
55
- issuer: 'https://account-api.edge.lolinya.net',
56
- clientId: 'my-app',
57
- clientSecret: 'my-secret',
58
- })
59
-
60
- // Protect all /api routes
61
- app.use('/api', client.authenticate())
62
-
63
- app.get('/api/me', (req, res) => {
64
- const auth = getAuth(req)
65
- res.json({ userId: auth?.sub, scopes: auth?.scope })
66
- })
67
-
68
- // Require specific scopes
69
- app.get('/api/profile',
70
- client.authenticate(),
71
- client.requireScopes('profile'),
72
- (req, res) => {
73
- const auth = getAuth(req)
74
- res.json({ name: auth?.sub })
75
- }
76
- )
77
-
78
- // Use introspection for sensitive operations
79
- app.post('/api/sensitive',
80
- client.authenticate({ strategy: 'introspection' }),
81
- handler
82
- )
83
- ```
84
-
85
- ## Configuration
86
-
87
- | Option | Type | Default | Description |
88
- |---|---|---|---|
89
- | `issuer` | `string` | `'https://account-api.edge.lolinya.net'` | SSO service URL (Issuer URL). See [Service Endpoints](https://account.lolinya.net/docs/developer/service-endpoints#integration-endpoints) for available endpoints. |
90
- | `clientId` | `string` | *required* | OAuth client ID |
91
- | `clientSecret` | `string` | *required* | OAuth client secret |
92
- | `timeout` | `number` | `10000` | HTTP request timeout in milliseconds |
93
- | `discoveryCacheTtl` | `number` | `3600000` | Discovery document cache TTL in milliseconds (default: 1 hour) |
94
- | `endpoints` | `EndpointConfig` | — | Explicitly specify endpoint URLs (auto-discovered via OIDC Discovery if omitted) |
95
-
96
- ## API Reference
97
-
98
- ### `NyaAccountClient`
99
-
100
- #### Authorization
101
-
102
- - **`createAuthorizationUrl(options)`**Create an OAuth authorization URL with PKCE
103
-
104
- #### Token Operations
105
-
106
- - **`exchangeCode(options)`** — Exchange an authorization code for tokens
107
- - **`refreshToken(refreshToken)`** — Refresh an Access Token
108
- - **`revokeToken(token)`** — Revoke a token (RFC 7009)
109
- - **`introspectToken(token)`** — Token introspection (RFC 7662)
110
-
111
- #### User Info
112
-
113
- - **`getUserInfo(accessToken)`** — Get user info via OIDC UserInfo endpoint
114
-
115
- #### JWT Verification
116
-
117
- - **`verifyAccessToken(token, options?)`** — Locally verify a JWT Access Token (RFC 9068)
118
- - **`verifyIdToken(token, options?)`** — Locally verify an OIDC ID Token
119
-
120
- #### Express Middleware
121
-
122
- - **`authenticate(options?)`** — Middleware to verify Bearer Token (`local` or `introspection` strategy)
123
- - **`requireScopes(...scopes)`** — Middleware to validate token scopes
124
-
125
- #### Cache
126
-
127
- - **`discover()`** — Fetch OIDC Discovery document (cached with TTL)
128
- - **`clearCache()`** — Clear Discovery and JWT verifier cache
129
-
130
- ### Express Helpers
131
-
132
- Available from `@nya-account/node-sdk/express`:
133
-
134
- - **`getAuth(req)`** — Retrieve the verified Access Token payload from a request
135
- - **`extractBearerToken(req)`** — Extract Bearer token from the Authorization header
136
- - **`sendOAuthError(res, statusCode, error, errorDescription)`** — Send an OAuth-standard error response
137
-
138
- ### PKCE Utilities
139
-
140
- - **`generatePkce()`** — Generate a code_verifier and code_challenge pair
141
- - **`generateCodeVerifier()`** — Generate a PKCE code_verifier
142
- - **`generateCodeChallenge(codeVerifier)`** — Generate an S256 code_challenge
143
-
144
- ## Error Handling
145
-
146
- The SDK provides typed error classes:
147
-
148
- ```typescript
149
- import {
150
- NyaAccountError, // Base error class
151
- OAuthError, // OAuth protocol errors from the server
152
- TokenVerificationError, // JWT verification failures
153
- DiscoveryError, // OIDC Discovery failures
154
- } from '@nya-account/node-sdk'
155
-
156
- try {
157
- await client.verifyAccessToken(token)
158
- } catch (error) {
159
- if (error instanceof TokenVerificationError) {
160
- console.log(error.code) // 'token_verification_failed'
161
- console.log(error.description) // Human-readable description
162
- }
163
- }
164
- ```
165
-
166
- ## Requirements
167
-
168
- - Node.js >= 20.0.0
169
- - Express 4.x or 5.x (optional, for middleware features)
170
-
171
- ## License
172
-
173
- [MIT](./LICENSE)
1
+ # @nya-account/node-sdk
2
+
3
+ Official Node.js SDK for [Nya Account](https://account.lolinya.net) SSO system.
4
+
5
+ Provides a complete OAuth 2.1 / OIDC client with PKCE, JWT verification, and Express middleware.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @nya-account/node-sdk
11
+ # or
12
+ pnpm add @nya-account/node-sdk
13
+ # or
14
+ yarn add @nya-account/node-sdk
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ import { NyaAccountClient } from '@nya-account/node-sdk'
21
+
22
+ const client = new NyaAccountClient({
23
+ // See https://account.lolinya.net/docs/developer/service-endpoints#integration-endpoints
24
+ issuer: 'https://account-api.edge.lolinya.net',
25
+ clientId: 'my-app',
26
+ clientSecret: 'my-secret'
27
+ })
28
+
29
+ // Create authorization URL (with PKCE)
30
+ const { url, codeVerifier, state } = await client.createAuthorizationUrl({
31
+ redirectUri: 'https://myapp.com/callback',
32
+ scope: 'openid profile email'
33
+ })
34
+
35
+ // Exchange code for tokens
36
+ const tokens = await client.exchangeCode({
37
+ code: callbackCode,
38
+ redirectUri: 'https://myapp.com/callback',
39
+ codeVerifier
40
+ })
41
+
42
+ // Get user info
43
+ const userInfo = await client.getUserInfo(tokens.accessToken)
44
+
45
+ // Revoke refresh token on logout
46
+ await client.revokeToken(tokens.refreshToken, { tokenTypeHint: 'refresh_token' })
47
+
48
+ // Build RP-initiated logout URL
49
+ const logoutUrl = await client.createEndSessionUrl({
50
+ idTokenHint: tokens.idToken,
51
+ postLogoutRedirectUri: 'https://myapp.com/logout/callback',
52
+ state: 'logout-csrf-state'
53
+ })
54
+ ```
55
+
56
+ ## Express Middleware
57
+
58
+ ```typescript
59
+ import express from 'express'
60
+ import { NyaAccountClient } from '@nya-account/node-sdk'
61
+ import { getAuth } from '@nya-account/node-sdk/express'
62
+
63
+ const app = express()
64
+ const client = new NyaAccountClient({
65
+ issuer: 'https://account-api.edge.lolinya.net',
66
+ clientId: 'my-app',
67
+ clientSecret: 'my-secret'
68
+ })
69
+
70
+ // Protect all /api routes
71
+ app.use('/api', client.authenticate())
72
+
73
+ app.get('/api/me', (req, res) => {
74
+ const auth = getAuth(req)
75
+ res.json({ userId: auth?.sub, scopes: auth?.scope })
76
+ })
77
+
78
+ // Require specific scopes
79
+ app.get(
80
+ '/api/profile',
81
+ client.authenticate(),
82
+ client.requireScopes('profile'),
83
+ (req, res) => {
84
+ const auth = getAuth(req)
85
+ res.json({ name: auth?.sub })
86
+ }
87
+ )
88
+
89
+ // Use introspection for sensitive operations
90
+ app.post('/api/sensitive', client.authenticate({ strategy: 'introspection' }), handler)
91
+ ```
92
+
93
+ ## Configuration
94
+
95
+ | Option | Type | Default | Description |
96
+ | ------------------- | ---------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
97
+ | `issuer` | `string` | `'https://account-api.edge.lolinya.net'` | SSO service URL (Issuer URL). See [Service Endpoints](https://account.lolinya.net/docs/developer/service-endpoints#integration-endpoints) for available endpoints. |
98
+ | `clientId` | `string` | _required_ | OAuth client ID |
99
+ | `clientSecret` | `string` | _required_ | OAuth client secret |
100
+ | `timeout` | `number` | `10000` | HTTP request timeout in milliseconds |
101
+ | `discoveryCacheTtl` | `number` | `3600000` | Discovery document cache TTL in milliseconds (default: 1 hour) |
102
+ | `endpoints` | `EndpointConfig` | | Explicitly specify endpoint URLs (auto-discovered via OIDC Discovery if omitted) |
103
+
104
+ ## API Reference
105
+
106
+ ### `NyaAccountClient`
107
+
108
+ #### Authorization
109
+
110
+ - **`createAuthorizationUrl(options)`** — Create an OAuth authorization URL with PKCE
111
+ - **`pushAuthorizationRequest(options)`** — Push authorization request to PAR endpoint (RFC 9126)
112
+ - **`createAuthorizationUrlWithPar(options)`** — Create authorization URL using PAR `request_uri`
113
+
114
+ #### Token Operations
115
+
116
+ - **`exchangeCode(options)`** — Exchange an authorization code for tokens
117
+ - **`refreshToken(refreshToken)`** — Refresh an Access Token
118
+ - **`revokeToken(token, options?)`** — Revoke a token (RFC 7009)
119
+ - **`introspectToken(token, options?)`** — Token introspection (RFC 7662)
120
+
121
+ #### User Info
122
+
123
+ - **`getUserInfo(accessToken)`** — Get user info via OIDC UserInfo endpoint
124
+
125
+ #### JWT Verification
126
+
127
+ - **`verifyAccessToken(token, options?)`** — Locally verify a JWT Access Token (RFC 9068)
128
+ - **`verifyIdToken(token, options?)`** — Locally verify an OIDC ID Token
129
+
130
+ #### Express Middleware
131
+
132
+ - **`authenticate(options?)`** — Middleware to verify Bearer Token (`local` or `introspection` strategy)
133
+ - **`requireScopes(...scopes)`** — Middleware to validate token scopes
134
+
135
+ #### Cache
136
+
137
+ - **`discover()`** — Fetch OIDC Discovery document (cached with TTL)
138
+ - **`clearCache()`** — Clear Discovery and JWT verifier cache
139
+
140
+ #### OIDC Logout
141
+
142
+ - **`createEndSessionUrl(options?)`** — Create OIDC RP-initiated logout URL (`end_session_endpoint`)
143
+
144
+ ### Express Helpers
145
+
146
+ Available from `@nya-account/node-sdk/express`:
147
+
148
+ - **`getAuth(req)`** — Retrieve the verified Access Token payload from a request
149
+ - **`extractBearerToken(req)`** — Extract Bearer token from the Authorization header
150
+ - **`sendOAuthError(res, statusCode, error, errorDescription)`** — Send an OAuth-standard error response
151
+
152
+ ### PKCE Utilities
153
+
154
+ - **`generatePkce()`** — Generate a code_verifier and code_challenge pair
155
+ - **`generateCodeVerifier()`** — Generate a PKCE code_verifier
156
+ - **`generateCodeChallenge(codeVerifier)`** — Generate an S256 code_challenge
157
+
158
+ ## Error Handling
159
+
160
+ The SDK provides typed error classes:
161
+
162
+ ```typescript
163
+ import {
164
+ NyaAccountError, // Base error class
165
+ OAuthError, // OAuth protocol errors from the server
166
+ TokenVerificationError, // JWT verification failures
167
+ DiscoveryError // OIDC Discovery failures
168
+ } from '@nya-account/node-sdk'
169
+
170
+ try {
171
+ await client.verifyAccessToken(token)
172
+ } catch (error) {
173
+ if (error instanceof TokenVerificationError) {
174
+ console.log(error.code) // 'token_verification_failed'
175
+ console.log(error.description) // Human-readable description
176
+ }
177
+ }
178
+ ```
179
+
180
+ ## Requirements
181
+
182
+ - Node.js >= 20.0.0
183
+ - Express 4.x or 5.x (optional, for middleware features)
184
+
185
+ ## License
186
+
187
+ [MIT](./LICENSE)
@@ -9,6 +9,8 @@ declare const AccessTokenPayloadSchema: z.ZodObject<{
9
9
  aud: z.ZodString;
10
10
  scope: z.ZodString;
11
11
  ver: z.ZodString;
12
+ sid: z.ZodString;
13
+ sv: z.ZodNumber;
12
14
  iat: z.ZodNumber;
13
15
  exp: z.ZodNumber;
14
16
  jti: z.ZodString;
@@ -27,6 +29,8 @@ declare const AccessTokenPayloadSchema: z.ZodObject<{
27
29
  aud: string;
28
30
  iss: string;
29
31
  jti: string;
32
+ sid: string;
33
+ sv: number;
30
34
  ver: string;
31
35
  cnf?: {
32
36
  jkt: string;
@@ -39,6 +43,8 @@ declare const AccessTokenPayloadSchema: z.ZodObject<{
39
43
  aud: string;
40
44
  iss: string;
41
45
  jti: string;
46
+ sid: string;
47
+ sv: number;
42
48
  ver: string;
43
49
  cnf?: {
44
50
  jkt: string;
@@ -49,11 +55,11 @@ declare const IdTokenPayloadSchema: z.ZodObject<{
49
55
  iss: z.ZodString;
50
56
  sub: z.ZodString;
51
57
  aud: z.ZodString;
58
+ sid: z.ZodOptional<z.ZodString>;
52
59
  iat: z.ZodNumber;
53
60
  exp: z.ZodNumber;
54
61
  nonce: z.ZodOptional<z.ZodString>;
55
62
  name: z.ZodOptional<z.ZodString>;
56
- preferred_username: z.ZodOptional<z.ZodString>;
57
63
  email: z.ZodOptional<z.ZodString>;
58
64
  email_verified: z.ZodOptional<z.ZodBoolean>;
59
65
  updated_at: z.ZodOptional<z.ZodNumber>;
@@ -63,8 +69,8 @@ declare const IdTokenPayloadSchema: z.ZodObject<{
63
69
  sub: string;
64
70
  aud: string;
65
71
  iss: string;
72
+ sid?: string | undefined;
66
73
  name?: string | undefined;
67
- preferred_username?: string | undefined;
68
74
  email?: string | undefined;
69
75
  email_verified?: boolean | undefined;
70
76
  updated_at?: number | undefined;
@@ -75,8 +81,8 @@ declare const IdTokenPayloadSchema: z.ZodObject<{
75
81
  sub: string;
76
82
  aud: string;
77
83
  iss: string;
84
+ sid?: string | undefined;
78
85
  name?: string | undefined;
79
- preferred_username?: string | undefined;
80
86
  email?: string | undefined;
81
87
  email_verified?: boolean | undefined;
82
88
  updated_at?: number | undefined;
@@ -115,4 +121,4 @@ declare function sendOAuthError(res: Response, statusCode: number, error: string
115
121
 
116
122
  //#endregion
117
123
  export { AccessTokenPayload, IdTokenPayload, extractBearerToken as extractBearerToken$1, getAuth as getAuth$1, sendOAuthError as sendOAuthError$1 };
118
- //# sourceMappingURL=express-yO7hxKKd.d.ts.map
124
+ //# sourceMappingURL=express-Bn8IUnft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express-Bn8IUnft.d.ts","names":[],"sources":["../src/core/schemas.d.ts","../src/middleware/express.d.ts"],"sourcesContent":null,"mappings":";;;;AAcA,IAAW,2BAAM;CAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;AAAA;AACjB,IAAW,qBAAqB;CAAC;CAAA,MAAA;CAAA,MAAA,EAAA;AAAA;AACjC,IAAG,uBAAA;CAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;AAAA;AACH,IAAW,iBAAa;CAAA;CAAA,MAAA;CAAA,MAAA,EAAA;AAAA;;;;;;;;;;;;;;;;;;;ACAxB,IAAW,UAAU,CAAC,GAAG,MAAM,kBAAmB;;;;AAQlD,IAAW,qBAAqB,CAAC,GAAG,MAAM,OAAQ;;;;AAIlD,IAAW,iBAAiB,CAAC,GAAG,MAAM,QAAS"}
package/dist/express.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { extractBearerToken$1 as extractBearerToken, getAuth$1 as getAuth, sendOAuthError$1 as sendOAuthError } from "./express-yO7hxKKd.js";
1
+ import { extractBearerToken$1 as extractBearerToken, getAuth$1 as getAuth, sendOAuthError$1 as sendOAuthError } from "./express-Bn8IUnft.js";
2
2
  export { extractBearerToken, getAuth, sendOAuthError };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AccessTokenPayload, IdTokenPayload, getAuth$1 as getAuth } from "./express-yO7hxKKd.js";
1
+ import { AccessTokenPayload, IdTokenPayload, getAuth$1 as getAuth } from "./express-Bn8IUnft.js";
2
2
  import { NextFunction, Request, Response } from "express";
3
3
 
4
4
  //#region src/core/types.d.ts
@@ -22,6 +22,7 @@ interface NyaAccountConfig {
22
22
  }
23
23
  interface EndpointConfig {
24
24
  authorization?: string;
25
+ pushedAuthorizationRequest?: string;
25
26
  token?: string;
26
27
  userinfo?: string;
27
28
  revocation?: string;
@@ -40,7 +41,6 @@ interface TokenResponse {
40
41
  interface UserInfo {
41
42
  sub: string;
42
43
  name?: string;
43
- preferredUsername?: string;
44
44
  picture?: string;
45
45
  email?: string;
46
46
  emailVerified?: boolean;
@@ -58,6 +58,8 @@ interface IntrospectionResponse {
58
58
  aud?: string;
59
59
  iss?: string;
60
60
  jti?: string;
61
+ sid?: string;
62
+ sv?: number;
61
63
  }
62
64
  interface DiscoveryDocument {
63
65
  issuer: string;
@@ -88,6 +90,20 @@ interface CreateAuthorizationUrlOptions {
88
90
  /** ID Token replay protection parameter */
89
91
  nonce?: string;
90
92
  }
93
+ interface PushAuthorizationRequestOptions extends CreateAuthorizationUrlOptions {
94
+ /** Optional JAR request object */
95
+ request?: string;
96
+ }
97
+ interface PushAuthorizationRequestResult {
98
+ /** PAR request URI */
99
+ requestUri: string;
100
+ /** PAR request URI lifetime in seconds */
101
+ expiresIn: number;
102
+ /** PKCE code_verifier, must be stored in session for later token exchange */
103
+ codeVerifier: string;
104
+ /** State parameter, must be stored in session for CSRF validation */
105
+ state: string;
106
+ }
91
107
  interface AuthorizationUrlResult {
92
108
  /** Full authorization URL to redirect the user to */
93
109
  url: string;
@@ -96,6 +112,16 @@ interface AuthorizationUrlResult {
96
112
  /** State parameter, must be stored in session for CSRF validation */
97
113
  state: string;
98
114
  }
115
+ interface CreateEndSessionUrlOptions {
116
+ /** Previously issued ID Token */
117
+ idTokenHint?: string;
118
+ /** Redirect URL after logout, must match registered post-logout URI */
119
+ postLogoutRedirectUri?: string;
120
+ /** Opaque state value returned to post_logout_redirect_uri */
121
+ state?: string;
122
+ /** Optional client ID override (defaults to configured clientId) */
123
+ clientId?: string;
124
+ }
99
125
  interface ExchangeCodeOptions {
100
126
  /** Authorization code received in the callback */
101
127
  code: string;
@@ -136,6 +162,23 @@ declare class NyaAccountClient {
136
162
  * for later use in token exchange and CSRF validation.
137
163
  */
138
164
  createAuthorizationUrl(options: CreateAuthorizationUrlOptions): Promise<AuthorizationUrlResult>;
165
+ /**
166
+ * Push authorization parameters to PAR endpoint (RFC 9126).
167
+ *
168
+ * Returns a `request_uri` that can be used in the authorization endpoint.
169
+ */
170
+ pushAuthorizationRequest(options: PushAuthorizationRequestOptions): Promise<PushAuthorizationRequestResult>;
171
+ /**
172
+ * Create an authorization URL using PAR `request_uri`.
173
+ */
174
+ createAuthorizationUrlWithPar(options: PushAuthorizationRequestOptions): Promise<AuthorizationUrlResult & {
175
+ requestUri: string;
176
+ expiresIn: number;
177
+ }>;
178
+ /**
179
+ * Create OIDC RP-Initiated Logout URL (`end_session_endpoint`).
180
+ */
181
+ createEndSessionUrl(options?: CreateEndSessionUrlOptions): Promise<string>;
139
182
  /**
140
183
  * Exchange an authorization code for tokens (Authorization Code Grant).
141
184
  */
@@ -150,18 +193,22 @@ declare class NyaAccountClient {
150
193
  * Supports revoking Access Tokens or Refresh Tokens.
151
194
  * Revoking a Refresh Token also revokes its entire token family.
152
195
  */
153
- revokeToken(token: string): Promise<void>;
196
+ revokeToken(token: string, options?: {
197
+ tokenTypeHint?: 'access_token' | 'refresh_token';
198
+ }): Promise<void>;
154
199
  /**
155
200
  * Token introspection (RFC 7662).
156
201
  *
157
202
  * Query the server for the current state of a token (active status, associated user info, etc.).
158
203
  */
159
- introspectToken(token: string): Promise<IntrospectionResponse>;
204
+ introspectToken(token: string, options?: {
205
+ tokenTypeHint?: 'access_token' | 'refresh_token';
206
+ }): Promise<IntrospectionResponse>;
160
207
  /**
161
208
  * Get user info using an Access Token (OIDC UserInfo Endpoint).
162
209
  *
163
210
  * The returned fields depend on the scopes included in the token:
164
- * - `profile`: name, preferredUsername, picture, updatedAt
211
+ * - `profile`: name, picture, updatedAt
165
212
  * - `email`: email, emailVerified
166
213
  */
167
214
  getUserInfo(accessToken: string): Promise<UserInfo>;
@@ -271,5 +318,5 @@ declare function generateCodeChallenge(codeVerifier: string): string;
271
318
  declare function generatePkce(): PkcePair;
272
319
 
273
320
  //#endregion
274
- export { AccessTokenPayload, AuthenticateOptions, AuthorizationUrlResult, CreateAuthorizationUrlOptions, DiscoveryDocument, DiscoveryError, EndpointConfig, ExchangeCodeOptions, IdTokenPayload, IntrospectionResponse, NyaAccountClient, NyaAccountConfig, NyaAccountError, OAuthError, PkcePair, TokenResponse, TokenVerificationError, UserInfo, generateCodeChallenge, generateCodeVerifier, generatePkce, getAuth };
321
+ export { AccessTokenPayload, AuthenticateOptions, AuthorizationUrlResult, CreateAuthorizationUrlOptions, CreateEndSessionUrlOptions, DiscoveryDocument, DiscoveryError, EndpointConfig, ExchangeCodeOptions, IdTokenPayload, IntrospectionResponse, NyaAccountClient, NyaAccountConfig, NyaAccountError, OAuthError, PkcePair, PushAuthorizationRequestOptions, PushAuthorizationRequestResult, TokenResponse, TokenVerificationError, UserInfo, generateCodeChallenge, generateCodeVerifier, generatePkce, getAuth };
275
322
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/core/types.d.ts","../src/client.d.ts","../src/core/errors.d.ts","../src/utils/pkce.d.ts"],"sourcesContent":null,"mappings":";;;;AAEA,IAAW,mBAAmB,CAAC,IAAG,MAAA,cAAA;AAClC,IAAM,iBAAA,CAAA,EAAA;AACN,IAAW,gBAAgB,CAAC,EAAG;AAC/B,IAAK,WAAA,CAAA,EAAA;AACL,IAAW,wBAAwB,CAAC,EAAG;AACvC,IAAM,oBAAA,CAAA,EAAA;AACN,IAAW,gCAAQ,CAAA,EAAA;AACnB,IAAW,yBAAc,CAAA,EAAA;AACzB,IAAW,sBAAS,CAAA,EAAA;AACpB,IAAW,sBAAkB,CAAA,EAAA;AAC7B,IAAW,WAAW,CAAC,EAAC;;;;ACTxB,IAAW,mBAAmB;CAAC;CAAG,MAAI;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;AAAA;;;;;;;ACAtC,IAAW,kBAAkB,CAAC,IAAI,MAAM,KAAM;;;;AAI9C,IAAA,aAAA,CAAA,IAAA,MAAA,eAAA;;;;AAIA,IAAW,yBAAyB,CAAC,IAAI,MAAM,eAAS;;;;AAIxD,IAAW,iBAAc,CAAA,IAAA,MAAA,eAAA;;;;;;;ACXzB,IAAW,uBAAuB,CAAC,EAAG;;;;AAItC,IAAW,wBAAwB,CAAC,EAAG;;;;AAIvC,IAAW,eAAe,CAAC,IAAI,MAAM,QAAS"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/core/types.d.ts","../src/client.d.ts","../src/core/errors.d.ts","../src/utils/pkce.d.ts"],"sourcesContent":null,"mappings":";;;;AAEA,IAAW,mBAAmB,CAAC,IAAG,MAAA,cAAA;AAClC,IAAM,iBAAA,CAAA,EAAA;AACN,IAAW,gBAAgB,CAAC,EAAG;AAC/B,IAAK,WAAA,CAAA,EAAA;AACL,IAAW,wBAAwB,CAAC,EAAG;AACvC,IAAM,oBAAA,CAAA,EAAA;AACN,IAAW,gCAAQ,CAAA,EAAA;AACnB,IAAW,kCAAc,CAAA,IAAA,MAAA,6BAAA;AACzB,IAAW,iCAAS,CAAA,EAAA;AACpB,IAAW,yBAAkB,CAAA,EAAA;AAC7B,IAAW,6BAAa,CAAA,EAAA;AACxB,IAAW,sBAAsB,CAAC,EAAG;AACrC,IAAW,sBAAS,CAAA,EAAA;AACpB,IAAW,WAAW,CAAC,EAAG;;;;ACZ1B,IAAW,mBAAmB;CAAC;CAAG,MAAI;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;CAAA,MAAA;AAAA;;;;;;;ACAtC,IAAW,kBAAkB,CAAC,IAAI,MAAM,KAAM;;;;AAI9C,IAAA,aAAA,CAAA,IAAA,MAAA,eAAA;;;;AAIA,IAAW,yBAAyB,CAAC,IAAI,MAAM,eAAS;;;;AAIxD,IAAW,iBAAc,CAAA,IAAA,MAAA,eAAA;;;;;;;ACXzB,IAAW,uBAAuB,CAAC,EAAG;;;;AAItC,IAAW,wBAAwB,CAAC,EAAG;;;;AAIvC,IAAW,eAAe,CAAC,IAAI,MAAM,QAAS"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { z } from "zod";
5
5
  import { createRemoteJWKSet, errors, jwtVerify } from "jose";
6
6
 
7
7
  //#region src/core/schemas.ts
8
+ const TokenTypeHintSchema = z.enum(["access_token", "refresh_token"]);
8
9
  const TokenResponseSchema = z.object({
9
10
  access_token: z.string(),
10
11
  token_type: z.string(),
@@ -28,12 +29,13 @@ const IntrospectionResponseSchema = z.object({
28
29
  sub: z.string().optional(),
29
30
  aud: z.string().optional(),
30
31
  iss: z.string().optional(),
31
- jti: z.string().optional()
32
+ jti: z.string().optional(),
33
+ sid: z.string().optional(),
34
+ sv: z.number().optional()
32
35
  });
33
36
  const UserInfoSchema = z.object({
34
37
  sub: z.string(),
35
38
  name: z.string().optional(),
36
- preferred_username: z.string().optional(),
37
39
  picture: z.string().optional(),
38
40
  email: z.string().optional(),
39
41
  email_verified: z.boolean().optional(),
@@ -61,12 +63,18 @@ const DiscoveryDocumentSchema = z.object({
61
63
  request_parameter_supported: z.boolean().optional(),
62
64
  request_uri_parameter_supported: z.boolean().optional()
63
65
  });
66
+ const PushedAuthorizationResponseSchema = z.object({
67
+ request_uri: z.string().min(1),
68
+ expires_in: z.number().int().positive()
69
+ });
64
70
  const AccessTokenPayloadSchema = z.object({
65
71
  iss: z.string(),
66
72
  sub: z.string(),
67
73
  aud: z.string(),
68
74
  scope: z.string(),
69
75
  ver: z.string(),
76
+ sid: z.string(),
77
+ sv: z.number().int().nonnegative(),
70
78
  iat: z.number(),
71
79
  exp: z.number(),
72
80
  jti: z.string(),
@@ -76,11 +84,11 @@ const IdTokenPayloadSchema = z.object({
76
84
  iss: z.string(),
77
85
  sub: z.string(),
78
86
  aud: z.string(),
87
+ sid: z.string().optional(),
79
88
  iat: z.number(),
80
89
  exp: z.number(),
81
90
  nonce: z.string().optional(),
82
91
  name: z.string().optional(),
83
- preferred_username: z.string().optional(),
84
92
  email: z.string().optional(),
85
93
  email_verified: z.boolean().optional(),
86
94
  updated_at: z.number().optional()
@@ -236,6 +244,7 @@ var JwtVerifier = class {
236
244
  //#region src/client.ts
237
245
  const DISCOVERY_ENDPOINT_MAP = {
238
246
  authorization: "authorizationEndpoint",
247
+ pushedAuthorizationRequest: "pushedAuthorizationRequestEndpoint",
239
248
  token: "tokenEndpoint",
240
249
  userinfo: "userinfoEndpoint",
241
250
  revocation: "revocationEndpoint",
@@ -263,9 +272,7 @@ var NyaAccountClient = class {
263
272
  this.httpClient = axios.create({ timeout: config.timeout ?? 1e4 });
264
273
  }
265
274
  /**
266
-
267
275
  * Fetch the OIDC Discovery document. Results are cached with a configurable TTL.
268
-
269
276
  */
270
277
  async discover() {
271
278
  if (this.discoveryCache && Date.now() - this.discoveryCacheTimestamp < this.discoveryCacheTtl) return this.discoveryCache;
@@ -301,9 +308,7 @@ var NyaAccountClient = class {
301
308
  }
302
309
  }
303
310
  /**
304
-
305
311
  * Clear the cached Discovery document and JWT verifier, forcing a re-fetch on next use.
306
-
307
312
  */
308
313
  clearCache() {
309
314
  this.discoveryCache = null;
@@ -311,15 +316,10 @@ var NyaAccountClient = class {
311
316
  this.jwtVerifier = null;
312
317
  }
313
318
  /**
314
-
315
319
  * Create an OAuth authorization URL (automatically includes PKCE).
316
-
317
320
  *
318
-
319
321
  * The returned `codeVerifier` and `state` must be saved to the session
320
-
321
322
  * for later use in token exchange and CSRF validation.
322
-
323
323
  */
324
324
  async createAuthorizationUrl(options) {
325
325
  const authorizationEndpoint = await this.resolveEndpoint("authorization");
@@ -343,9 +343,72 @@ var NyaAccountClient = class {
343
343
  };
344
344
  }
345
345
  /**
346
-
346
+ * Push authorization parameters to PAR endpoint (RFC 9126).
347
+ *
348
+ * Returns a `request_uri` that can be used in the authorization endpoint.
349
+ */
350
+ async pushAuthorizationRequest(options) {
351
+ const parEndpoint = await this.resolveEndpoint("pushedAuthorizationRequest");
352
+ const codeVerifier = generateCodeVerifier();
353
+ const codeChallenge = generateCodeChallenge(codeVerifier);
354
+ const state = options.state ?? randomBytes(16).toString("base64url");
355
+ const payload = {
356
+ client_id: this.config.clientId,
357
+ client_secret: this.config.clientSecret,
358
+ redirect_uri: options.redirectUri,
359
+ response_type: "code",
360
+ scope: options.scope ?? "openid",
361
+ state,
362
+ code_challenge: codeChallenge,
363
+ code_challenge_method: "S256"
364
+ };
365
+ if (options.nonce) payload.nonce = options.nonce;
366
+ if (options.request) payload.request = options.request;
367
+ try {
368
+ const response = await this.httpClient.post(parEndpoint, payload);
369
+ const raw = PushedAuthorizationResponseSchema.parse(response.data);
370
+ return {
371
+ requestUri: raw.request_uri,
372
+ expiresIn: raw.expires_in,
373
+ codeVerifier,
374
+ state
375
+ };
376
+ } catch (error) {
377
+ throw this.handleTokenError(error);
378
+ }
379
+ }
380
+ /**
381
+ * Create an authorization URL using PAR `request_uri`.
382
+ */
383
+ async createAuthorizationUrlWithPar(options) {
384
+ const authorizationEndpoint = await this.resolveEndpoint("authorization");
385
+ const pushed = await this.pushAuthorizationRequest(options);
386
+ const params = new URLSearchParams({
387
+ client_id: this.config.clientId,
388
+ request_uri: pushed.requestUri
389
+ });
390
+ return {
391
+ url: `${authorizationEndpoint}?${params.toString()}`,
392
+ codeVerifier: pushed.codeVerifier,
393
+ state: pushed.state,
394
+ requestUri: pushed.requestUri,
395
+ expiresIn: pushed.expiresIn
396
+ };
397
+ }
398
+ /**
399
+ * Create OIDC RP-Initiated Logout URL (`end_session_endpoint`).
400
+ */
401
+ async createEndSessionUrl(options) {
402
+ const endSessionEndpoint = await this.resolveEndpoint("endSession");
403
+ const params = new URLSearchParams();
404
+ if (options?.idTokenHint) params.set("id_token_hint", options.idTokenHint);
405
+ if (options?.postLogoutRedirectUri) params.set("post_logout_redirect_uri", options.postLogoutRedirectUri);
406
+ if (options?.state) params.set("state", options.state);
407
+ params.set("client_id", options?.clientId ?? this.config.clientId);
408
+ return `${endSessionEndpoint}?${params.toString()}`;
409
+ }
410
+ /**
347
411
  * Exchange an authorization code for tokens (Authorization Code Grant).
348
-
349
412
  */
350
413
  async exchangeCode(options) {
351
414
  const tokenEndpoint = await this.resolveEndpoint("token");
@@ -364,9 +427,7 @@ var NyaAccountClient = class {
364
427
  }
365
428
  }
366
429
  /**
367
-
368
430
  * Refresh an Access Token using a Refresh Token.
369
-
370
431
  */
371
432
  async refreshToken(refreshToken) {
372
433
  const tokenEndpoint = await this.resolveEndpoint("token");
@@ -383,40 +444,35 @@ var NyaAccountClient = class {
383
444
  }
384
445
  }
385
446
  /**
386
-
387
447
  * Revoke a token (RFC 7009).
388
-
389
448
  *
390
-
391
449
  * Supports revoking Access Tokens or Refresh Tokens.
392
-
393
450
  * Revoking a Refresh Token also revokes its entire token family.
394
-
395
451
  */
396
- async revokeToken(token) {
452
+ async revokeToken(token, options) {
397
453
  const revocationEndpoint = await this.resolveEndpoint("revocation");
398
454
  try {
455
+ const tokenTypeHint = options?.tokenTypeHint ? TokenTypeHintSchema.parse(options.tokenTypeHint) : void 0;
399
456
  await this.httpClient.post(revocationEndpoint, {
400
457
  token,
458
+ token_type_hint: tokenTypeHint,
401
459
  client_id: this.config.clientId,
402
460
  client_secret: this.config.clientSecret
403
461
  });
404
462
  } catch {}
405
463
  }
406
464
  /**
407
-
408
465
  * Token introspection (RFC 7662).
409
-
410
466
  *
411
-
412
467
  * Query the server for the current state of a token (active status, associated user info, etc.).
413
-
414
468
  */
415
- async introspectToken(token) {
469
+ async introspectToken(token, options) {
416
470
  const introspectionEndpoint = await this.resolveEndpoint("introspection");
417
471
  try {
472
+ const tokenTypeHint = options?.tokenTypeHint ? TokenTypeHintSchema.parse(options.tokenTypeHint) : void 0;
418
473
  const response = await this.httpClient.post(introspectionEndpoint, {
419
474
  token,
475
+ token_type_hint: tokenTypeHint,
420
476
  client_id: this.config.clientId,
421
477
  client_secret: this.config.clientSecret
422
478
  });
@@ -432,24 +488,20 @@ var NyaAccountClient = class {
432
488
  sub: raw.sub,
433
489
  aud: raw.aud,
434
490
  iss: raw.iss,
435
- jti: raw.jti
491
+ jti: raw.jti,
492
+ sid: raw.sid,
493
+ sv: raw.sv
436
494
  };
437
495
  } catch (error) {
438
496
  throw this.handleTokenError(error);
439
497
  }
440
498
  }
441
499
  /**
442
-
443
500
  * Get user info using an Access Token (OIDC UserInfo Endpoint).
444
-
445
501
  *
446
-
447
502
  * The returned fields depend on the scopes included in the token:
448
-
449
- * - `profile`: name, preferredUsername, picture, updatedAt
450
-
503
+ * - `profile`: name, picture, updatedAt
451
504
  * - `email`: email, emailVerified
452
-
453
505
  */
454
506
  async getUserInfo(accessToken) {
455
507
  const userinfoEndpoint = await this.resolveEndpoint("userinfo");
@@ -459,7 +511,6 @@ var NyaAccountClient = class {
459
511
  return {
460
512
  sub: raw.sub,
461
513
  name: raw.name,
462
- preferredUsername: raw.preferred_username,
463
514
  picture: raw.picture,
464
515
  email: raw.email,
465
516
  emailVerified: raw.email_verified,
@@ -470,77 +521,46 @@ var NyaAccountClient = class {
470
521
  }
471
522
  }
472
523
  /**
473
-
474
524
  * Locally verify a JWT Access Token (RFC 9068).
475
-
476
525
  *
477
-
478
526
  * Uses remote JWKS for signature verification, and validates issuer, audience, expiry, etc.
479
-
480
527
  *
481
-
482
528
  * @param token JWT Access Token string
483
-
484
529
  * @param options.audience Custom audience validation value (defaults to clientId)
485
-
486
530
  */
487
531
  async verifyAccessToken(token, options) {
488
532
  const verifier = await this.getJwtVerifier();
489
533
  return verifier.verifyAccessToken(token, options?.audience);
490
534
  }
491
535
  /**
492
-
493
536
  * Locally verify an OIDC ID Token.
494
-
495
537
  *
496
-
497
538
  * @param token JWT ID Token string
498
-
499
539
  * @param options.audience Custom audience validation value (defaults to clientId)
500
-
501
540
  * @param options.nonce Validate the nonce claim (required if nonce was sent during authorization)
502
-
503
541
  */
504
542
  async verifyIdToken(token, options) {
505
543
  const verifier = await this.getJwtVerifier();
506
544
  return verifier.verifyIdToken(token, options);
507
545
  }
508
546
  /**
509
-
510
547
  * Express middleware: verify the Bearer Token in the request.
511
-
512
548
  *
513
-
514
549
  * After successful verification, use `getAuth(req)` to retrieve the token payload.
515
-
516
550
  *
517
-
518
551
  * @param options.strategy Verification strategy: 'local' (default, JWT local verification) or 'introspection' (remote introspection)
519
-
520
552
  *
521
-
522
553
  * @example
523
-
524
554
  * ```typescript
525
-
526
555
  * import { getAuth } from '@nya-account/node-sdk/express'
527
-
528
556
  *
529
-
530
557
  * app.use('/api', client.authenticate())
531
-
532
558
  *
533
-
534
559
  * app.get('/api/me', (req, res) => {
535
-
536
560
  * const auth = getAuth(req)
537
-
538
561
  * res.json({ userId: auth?.sub })
539
-
540
562
  * })
541
-
542
563
  * ```
543
-
544
564
  */
545
565
  authenticate(options) {
546
566
  const strategy = options?.strategy ?? "local";
@@ -558,6 +578,11 @@ var NyaAccountClient = class {
558
578
  sendOAuthError(res, 401, "invalid_token", "Token is not active");
559
579
  return;
560
580
  }
581
+ const tokenType = introspection.tokenType?.toLowerCase();
582
+ if (tokenType && tokenType !== "bearer" && tokenType !== "access_token") {
583
+ sendOAuthError(res, 401, "invalid_token", "Token is not an access token");
584
+ return;
585
+ }
561
586
  payload = {
562
587
  iss: introspection.iss ?? "",
563
588
  sub: introspection.sub ?? "",
@@ -566,7 +591,9 @@ var NyaAccountClient = class {
566
591
  ver: "1",
567
592
  iat: introspection.iat ?? 0,
568
593
  exp: introspection.exp ?? 0,
569
- jti: introspection.jti ?? ""
594
+ jti: introspection.jti ?? "",
595
+ sid: introspection.sid ?? "",
596
+ sv: introspection.sv ?? 0
570
597
  };
571
598
  } else payload = await this.verifyAccessToken(token);
572
599
  setAuth(req, payload);
@@ -578,31 +605,18 @@ var NyaAccountClient = class {
578
605
  };
579
606
  }
580
607
  /**
581
-
582
608
  * Express middleware: validate that the token in the request contains the specified scopes.
583
-
584
609
  *
585
-
586
610
  * Must be used after the `authenticate()` middleware.
587
-
588
611
  *
589
-
590
612
  * @example
591
-
592
613
  * ```typescript
593
-
594
614
  * app.get('/api/profile',
595
-
596
615
  * client.authenticate(),
597
-
598
616
  * client.requireScopes('profile'),
599
-
600
617
  * (req, res) => { ... }
601
-
602
618
  * )
603
-
604
619
  * ```
605
-
606
620
  */
607
621
  requireScopes(...scopes) {
608
622
  return (req, res, next) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["code: string","description: string","error: string","errorDescription: string","codeVerifier: string","jwksUri: string","issuer: string","defaultAudience: string","token: string","audience?: string","options?: { audience?: string; nonce?: string }","error: unknown","tokenType: string","DISCOVERY_ENDPOINT_MAP: Record<EndpointName, keyof DiscoveryDocument>","config: NyaAccountConfig","options: CreateAuthorizationUrlOptions","options: ExchangeCodeOptions","refreshToken: string","token: string","accessToken: string","options?: { audience?: string }","options?: { audience?: string; nonce?: string }","options?: AuthenticateOptions","req: Request","res: Response","next: NextFunction","payload: AccessTokenPayload","name: EndpointName","data: unknown","error: unknown"],"sources":["../src/core/schemas.ts","../src/core/errors.ts","../src/utils/pkce.ts","../src/utils/jwt.ts","../src/client.ts"],"sourcesContent":["import { z } from 'zod'\r\n\r\n// ============================================================\r\n// OAuth Token Response\r\n// ============================================================\r\n\r\nexport const TokenResponseSchema = z.object({\r\n access_token: z.string(),\r\n token_type: z.string(),\r\n expires_in: z.number(),\r\n refresh_token: z.string(),\r\n scope: z.string(),\r\n id_token: z.string().optional(),\r\n})\r\n\r\nexport type TokenResponseRaw = z.infer<typeof TokenResponseSchema>\r\n\r\n// ============================================================\r\n// OAuth Error Response\r\n// ============================================================\r\n\r\nexport const OAuthErrorSchema = z.object({\r\n error: z.string(),\r\n error_description: z.string().optional(),\r\n})\r\n\r\nexport type OAuthErrorRaw = z.infer<typeof OAuthErrorSchema>\r\n\r\n// ============================================================\r\n// Token Introspection Response (RFC 7662)\r\n// ============================================================\r\n\r\nexport const IntrospectionResponseSchema = z.object({\r\n active: z.boolean(),\r\n scope: z.string().optional(),\r\n client_id: z.string().optional(),\r\n username: z.string().optional(),\r\n token_type: z.string().optional(),\r\n exp: z.number().optional(),\r\n iat: z.number().optional(),\r\n sub: z.string().optional(),\r\n aud: z.string().optional(),\r\n iss: z.string().optional(),\r\n jti: z.string().optional(),\r\n})\r\n\r\nexport type IntrospectionResponseRaw = z.infer<typeof IntrospectionResponseSchema>\r\n\r\n// ============================================================\r\n// OIDC UserInfo Response\r\n// ============================================================\r\n\r\nexport const UserInfoSchema = z.object({\r\n sub: z.string(),\r\n name: z.string().optional(),\r\n preferred_username: z.string().optional(),\r\n picture: z.string().optional(),\r\n email: z.string().optional(),\r\n email_verified: z.boolean().optional(),\r\n updated_at: z.number().optional(),\r\n})\r\n\r\nexport type UserInfoRaw = z.infer<typeof UserInfoSchema>\r\n\r\n// ============================================================\r\n// OIDC Discovery Document\r\n// ============================================================\r\n\r\nexport const DiscoveryDocumentSchema = z.object({\r\n issuer: z.string(),\r\n authorization_endpoint: z.string(),\r\n token_endpoint: z.string(),\r\n userinfo_endpoint: z.string().optional(),\r\n jwks_uri: z.string(),\r\n revocation_endpoint: z.string().optional(),\r\n introspection_endpoint: z.string().optional(),\r\n pushed_authorization_request_endpoint: z.string().optional(),\r\n end_session_endpoint: z.string().optional(),\r\n response_types_supported: z.array(z.string()),\r\n grant_types_supported: z.array(z.string()),\r\n id_token_signing_alg_values_supported: z.array(z.string()),\r\n scopes_supported: z.array(z.string()),\r\n subject_types_supported: z.array(z.string()),\r\n token_endpoint_auth_methods_supported: z.array(z.string()),\r\n code_challenge_methods_supported: z.array(z.string()).optional(),\r\n claims_supported: z.array(z.string()).optional(),\r\n dpop_signing_alg_values_supported: z.array(z.string()).optional(),\r\n request_parameter_supported: z.boolean().optional(),\r\n request_uri_parameter_supported: z.boolean().optional(),\r\n})\r\n\r\nexport type DiscoveryDocumentRaw = z.infer<typeof DiscoveryDocumentSchema>\r\n\r\n// ============================================================\r\n// JWT Access Token Payload (RFC 9068)\r\n// ============================================================\r\n\r\nexport const AccessTokenPayloadSchema = z.object({\r\n iss: z.string(),\r\n sub: z.string(),\r\n aud: z.string(),\r\n scope: z.string(),\r\n ver: z.string(),\r\n iat: z.number(),\r\n exp: z.number(),\r\n jti: z.string(),\r\n cnf: z.object({ jkt: z.string() }).optional(),\r\n})\r\n\r\nexport type AccessTokenPayload = z.infer<typeof AccessTokenPayloadSchema>\r\n\r\n// ============================================================\r\n// JWT ID Token Payload (OIDC Core)\r\n// ============================================================\r\n\r\nexport const IdTokenPayloadSchema = z.object({\r\n iss: z.string(),\r\n sub: z.string(),\r\n aud: z.string(),\r\n iat: z.number(),\r\n exp: z.number(),\r\n nonce: z.string().optional(),\r\n name: z.string().optional(),\r\n preferred_username: z.string().optional(),\r\n email: z.string().optional(),\r\n email_verified: z.boolean().optional(),\r\n updated_at: z.number().optional(),\r\n})\r\n\r\nexport type IdTokenPayload = z.infer<typeof IdTokenPayloadSchema>\r\n","/**\r\n * Base error class for the SDK.\r\n */\r\nexport class NyaAccountError extends Error {\r\n readonly code: string\r\n readonly description: string\r\n\r\n constructor(code: string, description: string) {\r\n super(`[${code}] ${description}`)\r\n this.name = 'NyaAccountError'\r\n this.code = code\r\n this.description = description\r\n }\r\n}\r\n\r\n/**\r\n * OAuth protocol error (from server error / error_description response).\r\n */\r\nexport class OAuthError extends NyaAccountError {\r\n constructor(error: string, errorDescription: string) {\r\n super(error, errorDescription)\r\n this.name = 'OAuthError'\r\n }\r\n}\r\n\r\n/**\r\n * JWT verification error.\r\n */\r\nexport class TokenVerificationError extends NyaAccountError {\r\n constructor(description: string) {\r\n super('token_verification_failed', description)\r\n this.name = 'TokenVerificationError'\r\n }\r\n}\r\n\r\n/**\r\n * OIDC Discovery error.\r\n */\r\nexport class DiscoveryError extends NyaAccountError {\r\n constructor(description: string) {\r\n super('discovery_error', description)\r\n this.name = 'DiscoveryError'\r\n }\r\n}\r\n","import { randomBytes, createHash } from 'node:crypto'\r\nimport type { PkcePair } from '@/core/types'\r\n\r\n/**\r\n * Generate a PKCE code_verifier (43-128 character random string).\r\n */\r\nexport function generateCodeVerifier(): string {\r\n return randomBytes(32).toString('base64url')\r\n}\r\n\r\n/**\r\n * Generate an S256 code_challenge from a code_verifier.\r\n */\r\nexport function generateCodeChallenge(codeVerifier: string): string {\r\n return createHash('sha256').update(codeVerifier).digest('base64url')\r\n}\r\n\r\n/**\r\n * Generate a PKCE code_verifier and code_challenge pair.\r\n */\r\nexport function generatePkce(): PkcePair {\r\n const codeVerifier = generateCodeVerifier()\r\n const codeChallenge = generateCodeChallenge(codeVerifier)\r\n return { codeVerifier, codeChallenge }\r\n}\r\n","import { createRemoteJWKSet, jwtVerify, errors as joseErrors } from 'jose'\r\nimport {\r\n AccessTokenPayloadSchema,\r\n IdTokenPayloadSchema,\r\n type AccessTokenPayload,\r\n type IdTokenPayload,\r\n} from '@/core/schemas'\r\nimport { TokenVerificationError } from '@/core/errors'\r\n\r\n/**\r\n * JWT verifier using remote JWKS for signature verification.\r\n */\r\nexport class JwtVerifier {\r\n private jwks: ReturnType<typeof createRemoteJWKSet>\r\n private issuer: string\r\n private defaultAudience: string\r\n\r\n constructor(jwksUri: string, issuer: string, defaultAudience: string) {\r\n this.jwks = createRemoteJWKSet(new URL(jwksUri))\r\n this.issuer = issuer\r\n this.defaultAudience = defaultAudience\r\n }\r\n\r\n /**\r\n * Verify an OAuth 2.0 Access Token (JWT, RFC 9068).\r\n */\r\n async verifyAccessToken(token: string, audience?: string): Promise<AccessTokenPayload> {\r\n try {\r\n const { payload } = await jwtVerify(token, this.jwks, {\r\n algorithms: ['RS256'],\r\n issuer: this.issuer,\r\n audience: audience ?? this.defaultAudience,\r\n })\r\n return AccessTokenPayloadSchema.parse(payload)\r\n } catch (error) {\r\n throw this.wrapError(error, 'Access Token')\r\n }\r\n }\r\n\r\n /**\r\n * Verify an OIDC ID Token.\r\n */\r\n async verifyIdToken(token: string, options?: { audience?: string; nonce?: string }): Promise<IdTokenPayload> {\r\n try {\r\n const { payload } = await jwtVerify(token, this.jwks, {\r\n algorithms: ['RS256'],\r\n issuer: this.issuer,\r\n audience: options?.audience ?? this.defaultAudience,\r\n })\r\n\r\n const parsed = IdTokenPayloadSchema.parse(payload)\r\n\r\n if (options?.nonce !== undefined && parsed.nonce !== options.nonce) {\r\n throw new TokenVerificationError('ID Token nonce mismatch')\r\n }\r\n\r\n return parsed\r\n } catch (error) {\r\n if (error instanceof TokenVerificationError) {\r\n throw error\r\n }\r\n throw this.wrapError(error, 'ID Token')\r\n }\r\n }\r\n\r\n private wrapError(error: unknown, tokenType: string): TokenVerificationError {\r\n if (error instanceof TokenVerificationError) {\r\n return error\r\n }\r\n if (error instanceof joseErrors.JWTExpired) {\r\n return new TokenVerificationError(`${tokenType} has expired`)\r\n }\r\n if (error instanceof joseErrors.JWTClaimValidationFailed) {\r\n return new TokenVerificationError(`${tokenType} claim validation failed: ${error.message}`)\r\n }\r\n if (error instanceof joseErrors.JWSSignatureVerificationFailed) {\r\n return new TokenVerificationError(`${tokenType} signature verification failed`)\r\n }\r\n const message = error instanceof Error ? error.message : 'Unknown error'\r\n return new TokenVerificationError(`${tokenType} verification failed: ${message}`)\r\n }\r\n}\r\n","import axios, { AxiosError, type AxiosInstance } from 'axios'\r\nimport type { Request, Response, NextFunction } from 'express'\r\nimport { randomBytes } from 'node:crypto'\r\nimport {\r\n TokenResponseSchema,\r\n OAuthErrorSchema,\r\n IntrospectionResponseSchema,\r\n UserInfoSchema,\r\n DiscoveryDocumentSchema,\r\n type AccessTokenPayload,\r\n type IdTokenPayload,\r\n} from '@/core/schemas'\r\nimport type {\r\n NyaAccountConfig,\r\n TokenResponse,\r\n UserInfo,\r\n IntrospectionResponse,\r\n DiscoveryDocument,\r\n AuthorizationUrlResult,\r\n CreateAuthorizationUrlOptions,\r\n ExchangeCodeOptions,\r\n AuthenticateOptions,\r\n EndpointConfig,\r\n} from '@/core/types'\r\nimport { OAuthError, DiscoveryError, NyaAccountError } from '@/core/errors'\r\nimport { generateCodeVerifier, generateCodeChallenge } from '@/utils/pkce'\r\nimport { JwtVerifier } from '@/utils/jwt'\r\nimport { setAuth, getAuth, extractBearerToken, sendOAuthError } from '@/middleware/express'\r\n\r\ntype EndpointName = keyof EndpointConfig\r\n\r\nconst DISCOVERY_ENDPOINT_MAP: Record<EndpointName, keyof DiscoveryDocument> = {\r\n authorization: 'authorizationEndpoint',\r\n token: 'tokenEndpoint',\r\n userinfo: 'userinfoEndpoint',\r\n revocation: 'revocationEndpoint',\r\n introspection: 'introspectionEndpoint',\r\n jwks: 'jwksUri',\r\n endSession: 'endSessionEndpoint',\r\n}\r\n\r\n/** Default issuer URL */\r\nconst DEFAULT_ISSUER = 'https://account-api.edge.lolinya.net'\r\n\r\n/** Default discovery cache TTL: 1 hour */\r\nconst DEFAULT_DISCOVERY_CACHE_TTL = 3600000\r\n\r\n/**\r\n * Nya Account Node.js SDK client.\r\n *\r\n * Provides full OAuth 2.1 / OIDC flow support:\r\n * - Authorization Code + PKCE\r\n * - Token exchange / refresh / revocation / introspection\r\n * - Local JWT verification (via JWKS)\r\n * - OIDC UserInfo\r\n * - OIDC Discovery auto-discovery\r\n * - Express middleware (Bearer Token auth + scope validation)\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new NyaAccountClient({\r\n * issuer: 'https://account.example.com',\r\n * clientId: 'my-app',\r\n * clientSecret: 'my-secret',\r\n * })\r\n *\r\n * // Create authorization URL (with PKCE)\r\n * const { url, codeVerifier, state } = await client.createAuthorizationUrl({\r\n * redirectUri: 'https://myapp.com/callback',\r\n * scope: 'openid profile email',\r\n * })\r\n *\r\n * // Exchange code for tokens\r\n * const tokens = await client.exchangeCode({\r\n * code: callbackCode,\r\n * redirectUri: 'https://myapp.com/callback',\r\n * codeVerifier,\r\n * })\r\n *\r\n * // Get user info\r\n * const userInfo = await client.getUserInfo(tokens.accessToken)\r\n * ```\r\n */\r\ntype ResolvedConfig = NyaAccountConfig & { issuer: string }\r\n\r\nexport class NyaAccountClient {\r\n private httpClient: AxiosInstance\r\n private config: ResolvedConfig\r\n private discoveryCache: DiscoveryDocument | null = null\r\n private discoveryCacheTimestamp = 0\r\n private readonly discoveryCacheTtl: number\r\n private jwtVerifier: JwtVerifier | null = null\r\n\r\n constructor(config: NyaAccountConfig) {\r\n this.config = {\r\n ...config,\r\n issuer: config.issuer ?? DEFAULT_ISSUER,\r\n }\r\n this.discoveryCacheTtl = config.discoveryCacheTtl ?? DEFAULT_DISCOVERY_CACHE_TTL\r\n this.httpClient = axios.create({\r\n timeout: config.timeout ?? 10000,\r\n })\r\n }\r\n\r\n // ============================================================\r\n // OIDC Discovery\r\n // ============================================================\r\n\r\n /**\r\n * Fetch the OIDC Discovery document. Results are cached with a configurable TTL.\r\n */\r\n async discover(): Promise<DiscoveryDocument> {\r\n if (this.discoveryCache && Date.now() - this.discoveryCacheTimestamp < this.discoveryCacheTtl) {\r\n return this.discoveryCache\r\n }\r\n\r\n try {\r\n const url = `${this.config.issuer}/.well-known/openid-configuration`\r\n const response = await this.httpClient.get(url)\r\n const raw = DiscoveryDocumentSchema.parse(response.data)\r\n\r\n this.discoveryCache = {\r\n issuer: raw.issuer,\r\n authorizationEndpoint: raw.authorization_endpoint,\r\n tokenEndpoint: raw.token_endpoint,\r\n userinfoEndpoint: raw.userinfo_endpoint,\r\n jwksUri: raw.jwks_uri,\r\n revocationEndpoint: raw.revocation_endpoint,\r\n introspectionEndpoint: raw.introspection_endpoint,\r\n pushedAuthorizationRequestEndpoint: raw.pushed_authorization_request_endpoint,\r\n endSessionEndpoint: raw.end_session_endpoint,\r\n responseTypesSupported: raw.response_types_supported,\r\n grantTypesSupported: raw.grant_types_supported,\r\n idTokenSigningAlgValuesSupported: raw.id_token_signing_alg_values_supported,\r\n scopesSupported: raw.scopes_supported,\r\n subjectTypesSupported: raw.subject_types_supported,\r\n tokenEndpointAuthMethodsSupported: raw.token_endpoint_auth_methods_supported,\r\n codeChallengeMethodsSupported: raw.code_challenge_methods_supported,\r\n claimsSupported: raw.claims_supported,\r\n }\r\n this.discoveryCacheTimestamp = Date.now()\r\n\r\n return this.discoveryCache\r\n } catch (error) {\r\n if (error instanceof DiscoveryError) throw error\r\n const message = error instanceof Error ? error.message : 'Unknown error'\r\n throw new DiscoveryError(`Failed to fetch OIDC Discovery document: ${message}`)\r\n }\r\n }\r\n\r\n /**\r\n * Clear the cached Discovery document and JWT verifier, forcing a re-fetch on next use.\r\n */\r\n clearCache(): void {\r\n this.discoveryCache = null\r\n this.discoveryCacheTimestamp = 0\r\n this.jwtVerifier = null\r\n }\r\n\r\n // ============================================================\r\n // Authorization URL\r\n // ============================================================\r\n\r\n /**\r\n * Create an OAuth authorization URL (automatically includes PKCE).\r\n *\r\n * The returned `codeVerifier` and `state` must be saved to the session\r\n * for later use in token exchange and CSRF validation.\r\n */\r\n async createAuthorizationUrl(options: CreateAuthorizationUrlOptions): Promise<AuthorizationUrlResult> {\r\n const authorizationEndpoint = await this.resolveEndpoint('authorization')\r\n\r\n const codeVerifier = generateCodeVerifier()\r\n const codeChallenge = generateCodeChallenge(codeVerifier)\r\n const state = options.state ?? randomBytes(16).toString('base64url')\r\n\r\n const params = new URLSearchParams({\r\n client_id: this.config.clientId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n scope: options.scope ?? 'openid',\r\n state,\r\n code_challenge: codeChallenge,\r\n code_challenge_method: 'S256',\r\n })\r\n\r\n if (options.nonce) {\r\n params.set('nonce', options.nonce)\r\n }\r\n\r\n return {\r\n url: `${authorizationEndpoint}?${params.toString()}`,\r\n codeVerifier,\r\n state,\r\n }\r\n }\r\n\r\n // ============================================================\r\n // Token Operations\r\n // ============================================================\r\n\r\n /**\r\n * Exchange an authorization code for tokens (Authorization Code Grant).\r\n */\r\n async exchangeCode(options: ExchangeCodeOptions): Promise<TokenResponse> {\r\n const tokenEndpoint = await this.resolveEndpoint('token')\r\n\r\n try {\r\n const response = await this.httpClient.post(tokenEndpoint, {\r\n grant_type: 'authorization_code',\r\n code: options.code,\r\n redirect_uri: options.redirectUri,\r\n client_id: this.config.clientId,\r\n client_secret: this.config.clientSecret,\r\n code_verifier: options.codeVerifier,\r\n })\r\n\r\n return this.mapTokenResponse(response.data)\r\n } catch (error) {\r\n throw this.handleTokenError(error)\r\n }\r\n }\r\n\r\n /**\r\n * Refresh an Access Token using a Refresh Token.\r\n */\r\n async refreshToken(refreshToken: string): Promise<TokenResponse> {\r\n const tokenEndpoint = await this.resolveEndpoint('token')\r\n\r\n try {\r\n const response = await this.httpClient.post(tokenEndpoint, {\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n client_id: this.config.clientId,\r\n client_secret: this.config.clientSecret,\r\n })\r\n\r\n return this.mapTokenResponse(response.data)\r\n } catch (error) {\r\n throw this.handleTokenError(error)\r\n }\r\n }\r\n\r\n /**\r\n * Revoke a token (RFC 7009).\r\n *\r\n * Supports revoking Access Tokens or Refresh Tokens.\r\n * Revoking a Refresh Token also revokes its entire token family.\r\n */\r\n async revokeToken(token: string): Promise<void> {\r\n const revocationEndpoint = await this.resolveEndpoint('revocation')\r\n\r\n try {\r\n await this.httpClient.post(revocationEndpoint, {\r\n token,\r\n client_id: this.config.clientId,\r\n client_secret: this.config.clientSecret,\r\n })\r\n } catch {\r\n // RFC 7009: revocation endpoint always returns 200, ignore errors\r\n }\r\n }\r\n\r\n /**\r\n * Token introspection (RFC 7662).\r\n *\r\n * Query the server for the current state of a token (active status, associated user info, etc.).\r\n */\r\n async introspectToken(token: string): Promise<IntrospectionResponse> {\r\n const introspectionEndpoint = await this.resolveEndpoint('introspection')\r\n\r\n try {\r\n const response = await this.httpClient.post(introspectionEndpoint, {\r\n token,\r\n client_id: this.config.clientId,\r\n client_secret: this.config.clientSecret,\r\n })\r\n\r\n const raw = IntrospectionResponseSchema.parse(response.data)\r\n return {\r\n active: raw.active,\r\n scope: raw.scope,\r\n clientId: raw.client_id,\r\n username: raw.username,\r\n tokenType: raw.token_type,\r\n exp: raw.exp,\r\n iat: raw.iat,\r\n sub: raw.sub,\r\n aud: raw.aud,\r\n iss: raw.iss,\r\n jti: raw.jti,\r\n }\r\n } catch (error) {\r\n throw this.handleTokenError(error)\r\n }\r\n }\r\n\r\n // ============================================================\r\n // OIDC UserInfo\r\n // ============================================================\r\n\r\n /**\r\n * Get user info using an Access Token (OIDC UserInfo Endpoint).\r\n *\r\n * The returned fields depend on the scopes included in the token:\r\n * - `profile`: name, preferredUsername, picture, updatedAt\r\n * - `email`: email, emailVerified\r\n */\r\n async getUserInfo(accessToken: string): Promise<UserInfo> {\r\n const userinfoEndpoint = await this.resolveEndpoint('userinfo')\r\n\r\n try {\r\n const response = await this.httpClient.get(userinfoEndpoint, {\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n\r\n const raw = UserInfoSchema.parse(response.data)\r\n return {\r\n sub: raw.sub,\r\n name: raw.name,\r\n preferredUsername: raw.preferred_username,\r\n picture: raw.picture,\r\n email: raw.email,\r\n emailVerified: raw.email_verified,\r\n updatedAt: raw.updated_at,\r\n }\r\n } catch (error) {\r\n throw this.handleTokenError(error)\r\n }\r\n }\r\n\r\n // ============================================================\r\n // Local JWT Verification\r\n // ============================================================\r\n\r\n /**\r\n * Locally verify a JWT Access Token (RFC 9068).\r\n *\r\n * Uses remote JWKS for signature verification, and validates issuer, audience, expiry, etc.\r\n *\r\n * @param token JWT Access Token string\r\n * @param options.audience Custom audience validation value (defaults to clientId)\r\n */\r\n async verifyAccessToken(token: string, options?: { audience?: string }): Promise<AccessTokenPayload> {\r\n const verifier = await this.getJwtVerifier()\r\n return verifier.verifyAccessToken(token, options?.audience)\r\n }\r\n\r\n /**\r\n * Locally verify an OIDC ID Token.\r\n *\r\n * @param token JWT ID Token string\r\n * @param options.audience Custom audience validation value (defaults to clientId)\r\n * @param options.nonce Validate the nonce claim (required if nonce was sent during authorization)\r\n */\r\n async verifyIdToken(token: string, options?: { audience?: string; nonce?: string }): Promise<IdTokenPayload> {\r\n const verifier = await this.getJwtVerifier()\r\n return verifier.verifyIdToken(token, options)\r\n }\r\n\r\n // ============================================================\r\n // Express Middleware\r\n // ============================================================\r\n\r\n /**\r\n * Express middleware: verify the Bearer Token in the request.\r\n *\r\n * After successful verification, use `getAuth(req)` to retrieve the token payload.\r\n *\r\n * @param options.strategy Verification strategy: 'local' (default, JWT local verification) or 'introspection' (remote introspection)\r\n *\r\n * @example\r\n * ```typescript\r\n * import { getAuth } from '@nya-account/node-sdk/express'\r\n *\r\n * app.use('/api', client.authenticate())\r\n *\r\n * app.get('/api/me', (req, res) => {\r\n * const auth = getAuth(req)\r\n * res.json({ userId: auth?.sub })\r\n * })\r\n * ```\r\n */\r\n authenticate(options?: AuthenticateOptions): (req: Request, res: Response, next: NextFunction) => void {\r\n const strategy = options?.strategy ?? 'local'\r\n\r\n return (req: Request, res: Response, next: NextFunction) => {\r\n const token = extractBearerToken(req)\r\n if (!token) {\r\n sendOAuthError(res, 401, 'invalid_token', 'Missing Bearer token in Authorization header')\r\n return\r\n }\r\n\r\n const handleVerification = async (): Promise<void> => {\r\n let payload: AccessTokenPayload\r\n\r\n if (strategy === 'introspection') {\r\n const introspection = await this.introspectToken(token)\r\n if (!introspection.active) {\r\n sendOAuthError(res, 401, 'invalid_token', 'Token is not active')\r\n return\r\n }\r\n payload = {\r\n iss: introspection.iss ?? '',\r\n sub: introspection.sub ?? '',\r\n aud: introspection.aud ?? '',\r\n scope: introspection.scope ?? '',\r\n ver: '1',\r\n iat: introspection.iat ?? 0,\r\n exp: introspection.exp ?? 0,\r\n jti: introspection.jti ?? '',\r\n }\r\n } else {\r\n payload = await this.verifyAccessToken(token)\r\n }\r\n\r\n setAuth(req, payload)\r\n next()\r\n }\r\n\r\n handleVerification().catch(() => {\r\n sendOAuthError(res, 401, 'invalid_token', 'Invalid or expired access token')\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * Express middleware: validate that the token in the request contains the specified scopes.\r\n *\r\n * Must be used after the `authenticate()` middleware.\r\n *\r\n * @example\r\n * ```typescript\r\n * app.get('/api/profile',\r\n * client.authenticate(),\r\n * client.requireScopes('profile'),\r\n * (req, res) => { ... }\r\n * )\r\n * ```\r\n */\r\n requireScopes(...scopes: string[]): (req: Request, res: Response, next: NextFunction) => void {\r\n return (req: Request, res: Response, next: NextFunction) => {\r\n const auth = getAuth(req)\r\n if (!auth) {\r\n sendOAuthError(res, 401, 'invalid_token', 'Request not authenticated')\r\n return\r\n }\r\n\r\n const tokenScopes = auth.scope.split(' ')\r\n const missingScopes = scopes.filter(s => !tokenScopes.includes(s))\r\n\r\n if (missingScopes.length > 0) {\r\n sendOAuthError(res, 403, 'insufficient_scope', `Missing required scopes: ${missingScopes.join(' ')}`)\r\n return\r\n }\r\n\r\n next()\r\n }\r\n }\r\n\r\n // ============================================================\r\n // Private Methods\r\n // ============================================================\r\n\r\n private async resolveEndpoint(name: EndpointName): Promise<string> {\r\n const explicit = this.config.endpoints?.[name]\r\n if (explicit) {\r\n return explicit\r\n }\r\n\r\n const discovery = await this.discover()\r\n const discoveryKey = DISCOVERY_ENDPOINT_MAP[name]\r\n const endpoint = discovery[discoveryKey]\r\n\r\n if (!endpoint || typeof endpoint !== 'string') {\r\n throw new NyaAccountError(\r\n 'endpoint_not_found',\r\n `Endpoint '${name}' not found in Discovery document`,\r\n )\r\n }\r\n\r\n return endpoint\r\n }\r\n\r\n private async getJwtVerifier(): Promise<JwtVerifier> {\r\n if (this.jwtVerifier) {\r\n return this.jwtVerifier\r\n }\r\n\r\n const jwksUri = await this.resolveEndpoint('jwks')\r\n const discovery = await this.discover()\r\n\r\n this.jwtVerifier = new JwtVerifier(jwksUri, discovery.issuer, this.config.clientId)\r\n return this.jwtVerifier\r\n }\r\n\r\n private mapTokenResponse(data: unknown): TokenResponse {\r\n const raw = TokenResponseSchema.parse(data)\r\n return {\r\n accessToken: raw.access_token,\r\n tokenType: raw.token_type,\r\n expiresIn: raw.expires_in,\r\n refreshToken: raw.refresh_token,\r\n scope: raw.scope,\r\n idToken: raw.id_token,\r\n }\r\n }\r\n\r\n private handleTokenError(error: unknown): NyaAccountError {\r\n if (error instanceof NyaAccountError) {\r\n return error\r\n }\r\n\r\n if (error instanceof AxiosError && error.response) {\r\n const parsed = OAuthErrorSchema.safeParse(error.response.data)\r\n if (parsed.success) {\r\n return new OAuthError(\r\n parsed.data.error,\r\n parsed.data.error_description ?? 'Unknown error',\r\n )\r\n }\r\n }\r\n\r\n const message = error instanceof Error ? error.message : 'Unknown error'\r\n return new NyaAccountError('request_failed', `Request failed: ${message}`)\r\n }\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["code: string","description: string","error: string","errorDescription: string","codeVerifier: string","jwksUri: string","issuer: string","defaultAudience: string","token: string","audience?: string","options?: { audience?: string; nonce?: string }","error: unknown","tokenType: string","DISCOVERY_ENDPOINT_MAP: Record<EndpointName, keyof DiscoveryDocument>","config: NyaAccountConfig","options: CreateAuthorizationUrlOptions","options: PushAuthorizationRequestOptions","payload: Record<string, string>","options?: CreateEndSessionUrlOptions","options: ExchangeCodeOptions","refreshToken: string","token: string","options?: { tokenTypeHint?: 'access_token' | 'refresh_token' }","accessToken: string","options?: { audience?: string }","options?: { audience?: string; nonce?: string }","options?: AuthenticateOptions","req: Request","res: Response","next: NextFunction","payload: AccessTokenPayload","name: EndpointName","data: unknown","error: unknown"],"sources":["../src/core/schemas.ts","../src/core/errors.ts","../src/utils/pkce.ts","../src/utils/jwt.ts","../src/client.ts"],"sourcesContent":["import { z } from 'zod'\n\nexport const TokenTypeHintSchema = z.enum(['access_token', 'refresh_token'])\n\n// ============================================================\n// OAuth Token Response\n// ============================================================\n\nexport const TokenResponseSchema = z.object({\n access_token: z.string(),\n token_type: z.string(),\n expires_in: z.number(),\n refresh_token: z.string(),\n scope: z.string(),\n id_token: z.string().optional()\n})\n\nexport type TokenResponseRaw = z.infer<typeof TokenResponseSchema>\n\n// ============================================================\n// OAuth Error Response\n// ============================================================\n\nexport const OAuthErrorSchema = z.object({\n error: z.string(),\n error_description: z.string().optional()\n})\n\nexport type OAuthErrorRaw = z.infer<typeof OAuthErrorSchema>\n\n// ============================================================\n// Token Introspection Response (RFC 7662)\n// ============================================================\n\nexport const IntrospectionResponseSchema = z.object({\n active: z.boolean(),\n scope: z.string().optional(),\n client_id: z.string().optional(),\n username: z.string().optional(),\n token_type: z.string().optional(),\n exp: z.number().optional(),\n iat: z.number().optional(),\n sub: z.string().optional(),\n aud: z.string().optional(),\n iss: z.string().optional(),\n jti: z.string().optional(),\n sid: z.string().optional(),\n sv: z.number().optional()\n})\n\nexport type IntrospectionResponseRaw = z.infer<typeof IntrospectionResponseSchema>\n\n// ============================================================\n// OIDC UserInfo Response\n// ============================================================\n\nexport const UserInfoSchema = z.object({\n sub: z.string(),\n name: z.string().optional(),\n picture: z.string().optional(),\n email: z.string().optional(),\n email_verified: z.boolean().optional(),\n updated_at: z.number().optional()\n})\n\nexport type UserInfoRaw = z.infer<typeof UserInfoSchema>\n\n// ============================================================\n// OIDC Discovery Document\n// ============================================================\n\nexport const DiscoveryDocumentSchema = z.object({\n issuer: z.string(),\n authorization_endpoint: z.string(),\n token_endpoint: z.string(),\n userinfo_endpoint: z.string().optional(),\n jwks_uri: z.string(),\n revocation_endpoint: z.string().optional(),\n introspection_endpoint: z.string().optional(),\n pushed_authorization_request_endpoint: z.string().optional(),\n end_session_endpoint: z.string().optional(),\n response_types_supported: z.array(z.string()),\n grant_types_supported: z.array(z.string()),\n id_token_signing_alg_values_supported: z.array(z.string()),\n scopes_supported: z.array(z.string()),\n subject_types_supported: z.array(z.string()),\n token_endpoint_auth_methods_supported: z.array(z.string()),\n code_challenge_methods_supported: z.array(z.string()).optional(),\n claims_supported: z.array(z.string()).optional(),\n dpop_signing_alg_values_supported: z.array(z.string()).optional(),\n request_parameter_supported: z.boolean().optional(),\n request_uri_parameter_supported: z.boolean().optional()\n})\n\nexport type DiscoveryDocumentRaw = z.infer<typeof DiscoveryDocumentSchema>\n\nexport const PushedAuthorizationResponseSchema = z.object({\n request_uri: z.string().min(1),\n expires_in: z.number().int().positive()\n})\n\nexport type PushedAuthorizationResponseRaw = z.infer<\n typeof PushedAuthorizationResponseSchema\n>\n\n// ============================================================\n// JWT Access Token Payload (RFC 9068)\n// ============================================================\n\nexport const AccessTokenPayloadSchema = z.object({\n iss: z.string(),\n sub: z.string(),\n aud: z.string(),\n scope: z.string(),\n ver: z.string(),\n sid: z.string(),\n sv: z.number().int().nonnegative(),\n iat: z.number(),\n exp: z.number(),\n jti: z.string(),\n cnf: z.object({ jkt: z.string() }).optional()\n})\n\nexport type AccessTokenPayload = z.infer<typeof AccessTokenPayloadSchema>\n\n// ============================================================\n// JWT ID Token Payload (OIDC Core)\n// ============================================================\n\nexport const IdTokenPayloadSchema = z.object({\n iss: z.string(),\n sub: z.string(),\n aud: z.string(),\n sid: z.string().optional(),\n iat: z.number(),\n exp: z.number(),\n nonce: z.string().optional(),\n name: z.string().optional(),\n email: z.string().optional(),\n email_verified: z.boolean().optional(),\n updated_at: z.number().optional()\n})\n\nexport type IdTokenPayload = z.infer<typeof IdTokenPayloadSchema>\n","/**\r\n * Base error class for the SDK.\r\n */\r\nexport class NyaAccountError extends Error {\r\n readonly code: string\r\n readonly description: string\r\n\r\n constructor(code: string, description: string) {\r\n super(`[${code}] ${description}`)\r\n this.name = 'NyaAccountError'\r\n this.code = code\r\n this.description = description\r\n }\r\n}\r\n\r\n/**\r\n * OAuth protocol error (from server error / error_description response).\r\n */\r\nexport class OAuthError extends NyaAccountError {\r\n constructor(error: string, errorDescription: string) {\r\n super(error, errorDescription)\r\n this.name = 'OAuthError'\r\n }\r\n}\r\n\r\n/**\r\n * JWT verification error.\r\n */\r\nexport class TokenVerificationError extends NyaAccountError {\r\n constructor(description: string) {\r\n super('token_verification_failed', description)\r\n this.name = 'TokenVerificationError'\r\n }\r\n}\r\n\r\n/**\r\n * OIDC Discovery error.\r\n */\r\nexport class DiscoveryError extends NyaAccountError {\r\n constructor(description: string) {\r\n super('discovery_error', description)\r\n this.name = 'DiscoveryError'\r\n }\r\n}\r\n","import { randomBytes, createHash } from 'node:crypto'\r\nimport type { PkcePair } from '@/core/types'\r\n\r\n/**\r\n * Generate a PKCE code_verifier (43-128 character random string).\r\n */\r\nexport function generateCodeVerifier(): string {\r\n return randomBytes(32).toString('base64url')\r\n}\r\n\r\n/**\r\n * Generate an S256 code_challenge from a code_verifier.\r\n */\r\nexport function generateCodeChallenge(codeVerifier: string): string {\r\n return createHash('sha256').update(codeVerifier).digest('base64url')\r\n}\r\n\r\n/**\r\n * Generate a PKCE code_verifier and code_challenge pair.\r\n */\r\nexport function generatePkce(): PkcePair {\r\n const codeVerifier = generateCodeVerifier()\r\n const codeChallenge = generateCodeChallenge(codeVerifier)\r\n return { codeVerifier, codeChallenge }\r\n}\r\n","import { createRemoteJWKSet, jwtVerify, errors as joseErrors } from 'jose'\r\nimport {\r\n AccessTokenPayloadSchema,\r\n IdTokenPayloadSchema,\r\n type AccessTokenPayload,\r\n type IdTokenPayload,\r\n} from '@/core/schemas'\r\nimport { TokenVerificationError } from '@/core/errors'\r\n\r\n/**\r\n * JWT verifier using remote JWKS for signature verification.\r\n */\r\nexport class JwtVerifier {\r\n private jwks: ReturnType<typeof createRemoteJWKSet>\r\n private issuer: string\r\n private defaultAudience: string\r\n\r\n constructor(jwksUri: string, issuer: string, defaultAudience: string) {\r\n this.jwks = createRemoteJWKSet(new URL(jwksUri))\r\n this.issuer = issuer\r\n this.defaultAudience = defaultAudience\r\n }\r\n\r\n /**\r\n * Verify an OAuth 2.0 Access Token (JWT, RFC 9068).\r\n */\r\n async verifyAccessToken(token: string, audience?: string): Promise<AccessTokenPayload> {\r\n try {\r\n const { payload } = await jwtVerify(token, this.jwks, {\r\n algorithms: ['RS256'],\r\n issuer: this.issuer,\r\n audience: audience ?? this.defaultAudience,\r\n })\r\n return AccessTokenPayloadSchema.parse(payload)\r\n } catch (error) {\r\n throw this.wrapError(error, 'Access Token')\r\n }\r\n }\r\n\r\n /**\r\n * Verify an OIDC ID Token.\r\n */\r\n async verifyIdToken(token: string, options?: { audience?: string; nonce?: string }): Promise<IdTokenPayload> {\r\n try {\r\n const { payload } = await jwtVerify(token, this.jwks, {\r\n algorithms: ['RS256'],\r\n issuer: this.issuer,\r\n audience: options?.audience ?? this.defaultAudience,\r\n })\r\n\r\n const parsed = IdTokenPayloadSchema.parse(payload)\r\n\r\n if (options?.nonce !== undefined && parsed.nonce !== options.nonce) {\r\n throw new TokenVerificationError('ID Token nonce mismatch')\r\n }\r\n\r\n return parsed\r\n } catch (error) {\r\n if (error instanceof TokenVerificationError) {\r\n throw error\r\n }\r\n throw this.wrapError(error, 'ID Token')\r\n }\r\n }\r\n\r\n private wrapError(error: unknown, tokenType: string): TokenVerificationError {\r\n if (error instanceof TokenVerificationError) {\r\n return error\r\n }\r\n if (error instanceof joseErrors.JWTExpired) {\r\n return new TokenVerificationError(`${tokenType} has expired`)\r\n }\r\n if (error instanceof joseErrors.JWTClaimValidationFailed) {\r\n return new TokenVerificationError(`${tokenType} claim validation failed: ${error.message}`)\r\n }\r\n if (error instanceof joseErrors.JWSSignatureVerificationFailed) {\r\n return new TokenVerificationError(`${tokenType} signature verification failed`)\r\n }\r\n const message = error instanceof Error ? error.message : 'Unknown error'\r\n return new TokenVerificationError(`${tokenType} verification failed: ${message}`)\r\n }\r\n}\r\n","import axios, { AxiosError, type AxiosInstance } from 'axios'\nimport type { Request, Response, NextFunction } from 'express'\nimport { randomBytes } from 'node:crypto'\nimport {\n TokenResponseSchema,\n OAuthErrorSchema,\n IntrospectionResponseSchema,\n UserInfoSchema,\n DiscoveryDocumentSchema,\n PushedAuthorizationResponseSchema,\n TokenTypeHintSchema,\n type AccessTokenPayload,\n type IdTokenPayload\n} from '@/core/schemas'\nimport type {\n NyaAccountConfig,\n TokenResponse,\n UserInfo,\n IntrospectionResponse,\n DiscoveryDocument,\n AuthorizationUrlResult,\n CreateAuthorizationUrlOptions,\n PushAuthorizationRequestOptions,\n PushAuthorizationRequestResult,\n CreateEndSessionUrlOptions,\n ExchangeCodeOptions,\n AuthenticateOptions,\n EndpointConfig\n} from '@/core/types'\nimport { OAuthError, DiscoveryError, NyaAccountError } from '@/core/errors'\nimport { generateCodeVerifier, generateCodeChallenge } from '@/utils/pkce'\nimport { JwtVerifier } from '@/utils/jwt'\nimport {\n setAuth,\n getAuth,\n extractBearerToken,\n sendOAuthError\n} from '@/middleware/express'\n\ntype EndpointName = keyof EndpointConfig\n\nconst DISCOVERY_ENDPOINT_MAP: Record<EndpointName, keyof DiscoveryDocument> = {\n authorization: 'authorizationEndpoint',\n pushedAuthorizationRequest: 'pushedAuthorizationRequestEndpoint',\n token: 'tokenEndpoint',\n userinfo: 'userinfoEndpoint',\n revocation: 'revocationEndpoint',\n introspection: 'introspectionEndpoint',\n jwks: 'jwksUri',\n endSession: 'endSessionEndpoint'\n}\n\n/** Default issuer URL */\nconst DEFAULT_ISSUER = 'https://account-api.edge.lolinya.net'\n\n/** Default discovery cache TTL: 1 hour */\nconst DEFAULT_DISCOVERY_CACHE_TTL = 3600000\n\n/**\n * Nya Account Node.js SDK client.\n *\n * Provides full OAuth 2.1 / OIDC flow support:\n * - Authorization Code + PKCE\n * - Token exchange / refresh / revocation / introspection\n * - Local JWT verification (via JWKS)\n * - OIDC UserInfo\n * - OIDC Discovery auto-discovery\n * - Express middleware (Bearer Token auth + scope validation)\n *\n * @example\n * ```typescript\n * const client = new NyaAccountClient({\n * issuer: 'https://account.example.com',\n * clientId: 'my-app',\n * clientSecret: 'my-secret',\n * })\n *\n * // Create authorization URL (with PKCE)\n * const { url, codeVerifier, state } = await client.createAuthorizationUrl({\n * redirectUri: 'https://myapp.com/callback',\n * scope: 'openid profile email',\n * })\n *\n * // Exchange code for tokens\n * const tokens = await client.exchangeCode({\n * code: callbackCode,\n * redirectUri: 'https://myapp.com/callback',\n * codeVerifier,\n * })\n *\n * // Get user info\n * const userInfo = await client.getUserInfo(tokens.accessToken)\n * ```\n */\ntype ResolvedConfig = NyaAccountConfig & { issuer: string }\n\nexport class NyaAccountClient {\n private httpClient: AxiosInstance\n private config: ResolvedConfig\n private discoveryCache: DiscoveryDocument | null = null\n private discoveryCacheTimestamp = 0\n private readonly discoveryCacheTtl: number\n private jwtVerifier: JwtVerifier | null = null\n\n constructor(config: NyaAccountConfig) {\n this.config = {\n ...config,\n issuer: config.issuer ?? DEFAULT_ISSUER\n }\n this.discoveryCacheTtl = config.discoveryCacheTtl ?? DEFAULT_DISCOVERY_CACHE_TTL\n this.httpClient = axios.create({\n timeout: config.timeout ?? 10000\n })\n }\n\n // ============================================================\n // OIDC Discovery\n // ============================================================\n\n /**\n * Fetch the OIDC Discovery document. Results are cached with a configurable TTL.\n */\n async discover(): Promise<DiscoveryDocument> {\n if (\n this.discoveryCache &&\n Date.now() - this.discoveryCacheTimestamp < this.discoveryCacheTtl\n ) {\n return this.discoveryCache\n }\n\n try {\n const url = `${this.config.issuer}/.well-known/openid-configuration`\n const response = await this.httpClient.get(url)\n const raw = DiscoveryDocumentSchema.parse(response.data)\n\n this.discoveryCache = {\n issuer: raw.issuer,\n authorizationEndpoint: raw.authorization_endpoint,\n tokenEndpoint: raw.token_endpoint,\n userinfoEndpoint: raw.userinfo_endpoint,\n jwksUri: raw.jwks_uri,\n revocationEndpoint: raw.revocation_endpoint,\n introspectionEndpoint: raw.introspection_endpoint,\n pushedAuthorizationRequestEndpoint:\n raw.pushed_authorization_request_endpoint,\n endSessionEndpoint: raw.end_session_endpoint,\n responseTypesSupported: raw.response_types_supported,\n grantTypesSupported: raw.grant_types_supported,\n idTokenSigningAlgValuesSupported:\n raw.id_token_signing_alg_values_supported,\n scopesSupported: raw.scopes_supported,\n subjectTypesSupported: raw.subject_types_supported,\n tokenEndpointAuthMethodsSupported:\n raw.token_endpoint_auth_methods_supported,\n codeChallengeMethodsSupported: raw.code_challenge_methods_supported,\n claimsSupported: raw.claims_supported\n }\n this.discoveryCacheTimestamp = Date.now()\n\n return this.discoveryCache\n } catch (error) {\n if (error instanceof DiscoveryError) throw error\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new DiscoveryError(\n `Failed to fetch OIDC Discovery document: ${message}`\n )\n }\n }\n\n /**\n * Clear the cached Discovery document and JWT verifier, forcing a re-fetch on next use.\n */\n clearCache(): void {\n this.discoveryCache = null\n this.discoveryCacheTimestamp = 0\n this.jwtVerifier = null\n }\n\n // ============================================================\n // Authorization URL\n // ============================================================\n\n /**\n * Create an OAuth authorization URL (automatically includes PKCE).\n *\n * The returned `codeVerifier` and `state` must be saved to the session\n * for later use in token exchange and CSRF validation.\n */\n async createAuthorizationUrl(\n options: CreateAuthorizationUrlOptions\n ): Promise<AuthorizationUrlResult> {\n const authorizationEndpoint = await this.resolveEndpoint('authorization')\n\n const codeVerifier = generateCodeVerifier()\n const codeChallenge = generateCodeChallenge(codeVerifier)\n const state = options.state ?? randomBytes(16).toString('base64url')\n\n const params = new URLSearchParams({\n client_id: this.config.clientId,\n redirect_uri: options.redirectUri,\n response_type: 'code',\n scope: options.scope ?? 'openid',\n state,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256'\n })\n\n if (options.nonce) {\n params.set('nonce', options.nonce)\n }\n\n return {\n url: `${authorizationEndpoint}?${params.toString()}`,\n codeVerifier,\n state\n }\n }\n\n /**\n * Push authorization parameters to PAR endpoint (RFC 9126).\n *\n * Returns a `request_uri` that can be used in the authorization endpoint.\n */\n async pushAuthorizationRequest(\n options: PushAuthorizationRequestOptions\n ): Promise<PushAuthorizationRequestResult> {\n const parEndpoint = await this.resolveEndpoint('pushedAuthorizationRequest')\n\n const codeVerifier = generateCodeVerifier()\n const codeChallenge = generateCodeChallenge(codeVerifier)\n const state = options.state ?? randomBytes(16).toString('base64url')\n\n const payload: Record<string, string> = {\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret,\n redirect_uri: options.redirectUri,\n response_type: 'code',\n scope: options.scope ?? 'openid',\n state,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256'\n }\n\n if (options.nonce) {\n payload.nonce = options.nonce\n }\n if (options.request) {\n payload.request = options.request\n }\n\n try {\n const response = await this.httpClient.post(parEndpoint, payload)\n const raw = PushedAuthorizationResponseSchema.parse(response.data)\n\n return {\n requestUri: raw.request_uri,\n expiresIn: raw.expires_in,\n codeVerifier,\n state\n }\n } catch (error) {\n throw this.handleTokenError(error)\n }\n }\n\n /**\n * Create an authorization URL using PAR `request_uri`.\n */\n async createAuthorizationUrlWithPar(\n options: PushAuthorizationRequestOptions\n ): Promise<AuthorizationUrlResult & { requestUri: string; expiresIn: number }> {\n const authorizationEndpoint = await this.resolveEndpoint('authorization')\n const pushed = await this.pushAuthorizationRequest(options)\n\n const params = new URLSearchParams({\n client_id: this.config.clientId,\n request_uri: pushed.requestUri\n })\n\n return {\n url: `${authorizationEndpoint}?${params.toString()}`,\n codeVerifier: pushed.codeVerifier,\n state: pushed.state,\n requestUri: pushed.requestUri,\n expiresIn: pushed.expiresIn\n }\n }\n\n /**\n * Create OIDC RP-Initiated Logout URL (`end_session_endpoint`).\n */\n async createEndSessionUrl(options?: CreateEndSessionUrlOptions): Promise<string> {\n const endSessionEndpoint = await this.resolveEndpoint('endSession')\n const params = new URLSearchParams()\n\n if (options?.idTokenHint) {\n params.set('id_token_hint', options.idTokenHint)\n }\n if (options?.postLogoutRedirectUri) {\n params.set('post_logout_redirect_uri', options.postLogoutRedirectUri)\n }\n if (options?.state) {\n params.set('state', options.state)\n }\n\n // 帮助服务端在未提供 id_token_hint 时识别客户端\n params.set('client_id', options?.clientId ?? this.config.clientId)\n\n return `${endSessionEndpoint}?${params.toString()}`\n }\n\n // ============================================================\n // Token Operations\n // ============================================================\n\n /**\n * Exchange an authorization code for tokens (Authorization Code Grant).\n */\n async exchangeCode(options: ExchangeCodeOptions): Promise<TokenResponse> {\n const tokenEndpoint = await this.resolveEndpoint('token')\n\n try {\n const response = await this.httpClient.post(tokenEndpoint, {\n grant_type: 'authorization_code',\n code: options.code,\n redirect_uri: options.redirectUri,\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret,\n code_verifier: options.codeVerifier\n })\n\n return this.mapTokenResponse(response.data)\n } catch (error) {\n throw this.handleTokenError(error)\n }\n }\n\n /**\n * Refresh an Access Token using a Refresh Token.\n */\n async refreshToken(refreshToken: string): Promise<TokenResponse> {\n const tokenEndpoint = await this.resolveEndpoint('token')\n\n try {\n const response = await this.httpClient.post(tokenEndpoint, {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret\n })\n\n return this.mapTokenResponse(response.data)\n } catch (error) {\n throw this.handleTokenError(error)\n }\n }\n\n /**\n * Revoke a token (RFC 7009).\n *\n * Supports revoking Access Tokens or Refresh Tokens.\n * Revoking a Refresh Token also revokes its entire token family.\n */\n async revokeToken(\n token: string,\n options?: { tokenTypeHint?: 'access_token' | 'refresh_token' }\n ): Promise<void> {\n const revocationEndpoint = await this.resolveEndpoint('revocation')\n\n try {\n const tokenTypeHint = options?.tokenTypeHint\n ? TokenTypeHintSchema.parse(options.tokenTypeHint)\n : undefined\n await this.httpClient.post(revocationEndpoint, {\n token,\n token_type_hint: tokenTypeHint,\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret\n })\n } catch {\n // RFC 7009: revocation endpoint always returns 200, ignore errors\n }\n }\n\n /**\n * Token introspection (RFC 7662).\n *\n * Query the server for the current state of a token (active status, associated user info, etc.).\n */\n async introspectToken(\n token: string,\n options?: { tokenTypeHint?: 'access_token' | 'refresh_token' }\n ): Promise<IntrospectionResponse> {\n const introspectionEndpoint = await this.resolveEndpoint('introspection')\n\n try {\n const tokenTypeHint = options?.tokenTypeHint\n ? TokenTypeHintSchema.parse(options.tokenTypeHint)\n : undefined\n const response = await this.httpClient.post(introspectionEndpoint, {\n token,\n token_type_hint: tokenTypeHint,\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret\n })\n\n const raw = IntrospectionResponseSchema.parse(response.data)\n return {\n active: raw.active,\n scope: raw.scope,\n clientId: raw.client_id,\n username: raw.username,\n tokenType: raw.token_type,\n exp: raw.exp,\n iat: raw.iat,\n sub: raw.sub,\n aud: raw.aud,\n iss: raw.iss,\n jti: raw.jti,\n sid: raw.sid,\n sv: raw.sv\n }\n } catch (error) {\n throw this.handleTokenError(error)\n }\n }\n\n // ============================================================\n // OIDC UserInfo\n // ============================================================\n\n /**\n * Get user info using an Access Token (OIDC UserInfo Endpoint).\n *\n * The returned fields depend on the scopes included in the token:\n * - `profile`: name, picture, updatedAt\n * - `email`: email, emailVerified\n */\n async getUserInfo(accessToken: string): Promise<UserInfo> {\n const userinfoEndpoint = await this.resolveEndpoint('userinfo')\n\n try {\n const response = await this.httpClient.get(userinfoEndpoint, {\n headers: { Authorization: `Bearer ${accessToken}` }\n })\n\n const raw = UserInfoSchema.parse(response.data)\n return {\n sub: raw.sub,\n name: raw.name,\n picture: raw.picture,\n email: raw.email,\n emailVerified: raw.email_verified,\n updatedAt: raw.updated_at\n }\n } catch (error) {\n throw this.handleTokenError(error)\n }\n }\n\n // ============================================================\n // Local JWT Verification\n // ============================================================\n\n /**\n * Locally verify a JWT Access Token (RFC 9068).\n *\n * Uses remote JWKS for signature verification, and validates issuer, audience, expiry, etc.\n *\n * @param token JWT Access Token string\n * @param options.audience Custom audience validation value (defaults to clientId)\n */\n async verifyAccessToken(\n token: string,\n options?: { audience?: string }\n ): Promise<AccessTokenPayload> {\n const verifier = await this.getJwtVerifier()\n return verifier.verifyAccessToken(token, options?.audience)\n }\n\n /**\n * Locally verify an OIDC ID Token.\n *\n * @param token JWT ID Token string\n * @param options.audience Custom audience validation value (defaults to clientId)\n * @param options.nonce Validate the nonce claim (required if nonce was sent during authorization)\n */\n async verifyIdToken(\n token: string,\n options?: { audience?: string; nonce?: string }\n ): Promise<IdTokenPayload> {\n const verifier = await this.getJwtVerifier()\n return verifier.verifyIdToken(token, options)\n }\n\n // ============================================================\n // Express Middleware\n // ============================================================\n\n /**\n * Express middleware: verify the Bearer Token in the request.\n *\n * After successful verification, use `getAuth(req)` to retrieve the token payload.\n *\n * @param options.strategy Verification strategy: 'local' (default, JWT local verification) or 'introspection' (remote introspection)\n *\n * @example\n * ```typescript\n * import { getAuth } from '@nya-account/node-sdk/express'\n *\n * app.use('/api', client.authenticate())\n *\n * app.get('/api/me', (req, res) => {\n * const auth = getAuth(req)\n * res.json({ userId: auth?.sub })\n * })\n * ```\n */\n authenticate(\n options?: AuthenticateOptions\n ): (req: Request, res: Response, next: NextFunction) => void {\n const strategy = options?.strategy ?? 'local'\n\n return (req: Request, res: Response, next: NextFunction) => {\n const token = extractBearerToken(req)\n if (!token) {\n sendOAuthError(\n res,\n 401,\n 'invalid_token',\n 'Missing Bearer token in Authorization header'\n )\n return\n }\n\n const handleVerification = async (): Promise<void> => {\n let payload: AccessTokenPayload\n\n if (strategy === 'introspection') {\n const introspection = await this.introspectToken(token)\n if (!introspection.active) {\n sendOAuthError(res, 401, 'invalid_token', 'Token is not active')\n return\n }\n const tokenType = introspection.tokenType?.toLowerCase()\n if (\n tokenType &&\n tokenType !== 'bearer' &&\n tokenType !== 'access_token'\n ) {\n sendOAuthError(\n res,\n 401,\n 'invalid_token',\n 'Token is not an access token'\n )\n return\n }\n payload = {\n iss: introspection.iss ?? '',\n sub: introspection.sub ?? '',\n aud: introspection.aud ?? '',\n scope: introspection.scope ?? '',\n ver: '1',\n iat: introspection.iat ?? 0,\n exp: introspection.exp ?? 0,\n jti: introspection.jti ?? '',\n sid: introspection.sid ?? '',\n sv: introspection.sv ?? 0\n }\n } else {\n payload = await this.verifyAccessToken(token)\n }\n\n setAuth(req, payload)\n next()\n }\n\n handleVerification().catch(() => {\n sendOAuthError(\n res,\n 401,\n 'invalid_token',\n 'Invalid or expired access token'\n )\n })\n }\n }\n\n /**\n * Express middleware: validate that the token in the request contains the specified scopes.\n *\n * Must be used after the `authenticate()` middleware.\n *\n * @example\n * ```typescript\n * app.get('/api/profile',\n * client.authenticate(),\n * client.requireScopes('profile'),\n * (req, res) => { ... }\n * )\n * ```\n */\n requireScopes(\n ...scopes: string[]\n ): (req: Request, res: Response, next: NextFunction) => void {\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req)\n if (!auth) {\n sendOAuthError(res, 401, 'invalid_token', 'Request not authenticated')\n return\n }\n\n const tokenScopes = auth.scope.split(' ')\n const missingScopes = scopes.filter((s) => !tokenScopes.includes(s))\n\n if (missingScopes.length > 0) {\n sendOAuthError(\n res,\n 403,\n 'insufficient_scope',\n `Missing required scopes: ${missingScopes.join(' ')}`\n )\n return\n }\n\n next()\n }\n }\n\n // ============================================================\n // Private Methods\n // ============================================================\n\n private async resolveEndpoint(name: EndpointName): Promise<string> {\n const explicit = this.config.endpoints?.[name]\n if (explicit) {\n return explicit\n }\n\n const discovery = await this.discover()\n const discoveryKey = DISCOVERY_ENDPOINT_MAP[name]\n const endpoint = discovery[discoveryKey]\n\n if (!endpoint || typeof endpoint !== 'string') {\n throw new NyaAccountError(\n 'endpoint_not_found',\n `Endpoint '${name}' not found in Discovery document`\n )\n }\n\n return endpoint\n }\n\n private async getJwtVerifier(): Promise<JwtVerifier> {\n if (this.jwtVerifier) {\n return this.jwtVerifier\n }\n\n const jwksUri = await this.resolveEndpoint('jwks')\n const discovery = await this.discover()\n\n this.jwtVerifier = new JwtVerifier(\n jwksUri,\n discovery.issuer,\n this.config.clientId\n )\n return this.jwtVerifier\n }\n\n private mapTokenResponse(data: unknown): TokenResponse {\n const raw = TokenResponseSchema.parse(data)\n return {\n accessToken: raw.access_token,\n tokenType: raw.token_type,\n expiresIn: raw.expires_in,\n refreshToken: raw.refresh_token,\n scope: raw.scope,\n idToken: raw.id_token\n }\n }\n\n private handleTokenError(error: unknown): NyaAccountError {\n if (error instanceof NyaAccountError) {\n return error\n }\n\n if (error instanceof AxiosError && error.response) {\n const parsed = OAuthErrorSchema.safeParse(error.response.data)\n if (parsed.success) {\n return new OAuthError(\n parsed.data.error,\n parsed.data.error_description ?? 'Unknown error'\n )\n }\n }\n\n const message = error instanceof Error ? error.message : 'Unknown error'\n return new NyaAccountError('request_failed', `Request failed: ${message}`)\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nya-account/node-sdk",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Official Node.js SDK for Nya Account SSO — OAuth 2.1 / OIDC client with PKCE, JWT verification, and Express middleware",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"express-yO7hxKKd.d.ts","names":[],"sources":["../src/core/schemas.d.ts","../src/middleware/express.d.ts"],"sourcesContent":null,"mappings":";;;;AAWA,IAAW,2BAAW;CAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;AAAA;AACtB,IAAW,qBAAc;CAAA;CAAA,MAAA;CAAA,MAAA,EAAA;AAAA;AACzB,IAAW,uBAAM;CAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;CAAA,MAAA,EAAA;AAAA;AACjB,IAAW,iBAAiB;CAAC;CAAI,MAAA;CAAA,MAAA,EAAA;AAAA;;;;;;;;;;;;;;;;;;;ACGjC,IAAW,UAAU,CAAC,GAAG,MAAM,kBAAmB;;;;AAQlD,IAAW,qBAAqB,CAAC,GAAG,MAAM,OAAQ;;;;AAIlD,IAAW,iBAAiB,CAAC,GAAG,MAAM,QAAS"}