@tdacorp/identity-client 0.2.2 → 0.2.4

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.
@@ -31,23 +31,36 @@ function assertHttps(url, label) {
31
31
  throw new Error(`Discovery: ${label} "${url}" must be https (loopback hosts are the only http exception)`);
32
32
  }
33
33
  }
34
+ var ENDPOINT_FIELDS = [
35
+ { field: "jwks_uri", required: true },
36
+ { field: "token_endpoint", required: true },
37
+ { field: "authorization_endpoint", required: true },
38
+ { field: "userinfo_endpoint", required: false },
39
+ { field: "end_session_endpoint", required: false },
40
+ { field: "revocation_endpoint", required: false },
41
+ { field: "introspection_endpoint", required: false },
42
+ { field: "registration_endpoint", required: false }
43
+ ];
44
+ function validateEndpointField(field, url, issuerOrigin) {
45
+ assertHttps(url, field);
46
+ if (new URL(url).origin !== issuerOrigin) {
47
+ throw new Error(`Discovery: ${field} "${url}" is not same-origin as issuer`);
48
+ }
49
+ }
34
50
  function validateDiscoveryDocument(document, issuerUrl) {
35
51
  assertHttps(issuerUrl, "issuer");
36
- assertHttps(document.jwks_uri, "jwks_uri");
37
- assertHttps(document.token_endpoint, "token_endpoint");
38
- assertHttps(document.authorization_endpoint, "authorization_endpoint");
39
52
  if (document.issuer !== issuerUrl) {
40
53
  throw new Error(`Discovery: document issuer "${document.issuer}" does not match the configured issuer "${issuerUrl}"`);
41
54
  }
42
55
  const issuerOrigin = new URL(issuerUrl).origin;
43
- if (new URL(document.jwks_uri).origin !== issuerOrigin) {
44
- throw new Error(`Discovery: jwks_uri "${document.jwks_uri}" is not same-origin as issuer "${issuerUrl}"`);
45
- }
46
- if (new URL(document.token_endpoint).origin !== issuerOrigin) {
47
- throw new Error(`Discovery: token_endpoint "${document.token_endpoint}" is not same-origin as issuer "${issuerUrl}"`);
48
- }
49
- if (new URL(document.authorization_endpoint).origin !== issuerOrigin) {
50
- throw new Error(`Discovery: authorization_endpoint "${document.authorization_endpoint}" is not same-origin as issuer "${issuerUrl}"`);
56
+ for (const { field, required } of ENDPOINT_FIELDS) {
57
+ const value = document[field];
58
+ if (value === void 0 && !required) continue;
59
+ if (typeof value !== "string") {
60
+ const requirement = required ? "is required and must be a string" : ", if present, must be a string";
61
+ throw new Error(`Discovery: ${field} ${requirement}`);
62
+ }
63
+ validateEndpointField(field, value, issuerOrigin);
51
64
  }
52
65
  }
53
66
  async function fetchDiscovery(issuerUrl) {
@@ -129,6 +142,16 @@ var TokenRequestError = class extends Error {
129
142
  this.errorDescription = details.errorDescription;
130
143
  }
131
144
  };
145
+ async function fetchDiscoveryForTokenRequest(issuer) {
146
+ try {
147
+ return await fetchDiscovery(issuer);
148
+ } catch (error) {
149
+ throw new TokenRequestError({
150
+ error: "discovery_failed",
151
+ errorDescription: error instanceof Error ? error.message : "Failed to fetch the issuer's discovery document"
152
+ });
153
+ }
154
+ }
132
155
  function toTokenSet(body) {
133
156
  return {
134
157
  accessToken: body.access_token,
@@ -159,7 +182,7 @@ async function readTokenResponseBody(response) {
159
182
  return await response.json().catch(() => null);
160
183
  }
161
184
  async function exchangeAuthorizationCode(options) {
162
- const discovery = await fetchDiscovery(options.issuer);
185
+ const discovery = await fetchDiscoveryForTokenRequest(options.issuer);
163
186
  const response = await postTokenRequest(
164
187
  discovery.token_endpoint,
165
188
  options.clientId,
@@ -179,7 +202,7 @@ async function exchangeAuthorizationCode(options) {
179
202
  return toTokenSet(body);
180
203
  }
181
204
  async function clientCredentialsGrant(options) {
182
- const discovery = await fetchDiscovery(options.issuer);
205
+ const discovery = await fetchDiscoveryForTokenRequest(options.issuer);
183
206
  const response = await postTokenRequest(
184
207
  discovery.token_endpoint,
185
208
  options.clientId,
package/dist/index.cjs CHANGED
@@ -68,23 +68,36 @@ function assertHttps(url, label) {
68
68
  throw new Error(`Discovery: ${label} "${url}" must be https (loopback hosts are the only http exception)`);
69
69
  }
70
70
  }
71
+ var ENDPOINT_FIELDS = [
72
+ { field: "jwks_uri", required: true },
73
+ { field: "token_endpoint", required: true },
74
+ { field: "authorization_endpoint", required: true },
75
+ { field: "userinfo_endpoint", required: false },
76
+ { field: "end_session_endpoint", required: false },
77
+ { field: "revocation_endpoint", required: false },
78
+ { field: "introspection_endpoint", required: false },
79
+ { field: "registration_endpoint", required: false }
80
+ ];
81
+ function validateEndpointField(field, url, issuerOrigin) {
82
+ assertHttps(url, field);
83
+ if (new URL(url).origin !== issuerOrigin) {
84
+ throw new Error(`Discovery: ${field} "${url}" is not same-origin as issuer`);
85
+ }
86
+ }
71
87
  function validateDiscoveryDocument(document, issuerUrl) {
72
88
  assertHttps(issuerUrl, "issuer");
73
- assertHttps(document.jwks_uri, "jwks_uri");
74
- assertHttps(document.token_endpoint, "token_endpoint");
75
- assertHttps(document.authorization_endpoint, "authorization_endpoint");
76
89
  if (document.issuer !== issuerUrl) {
77
90
  throw new Error(`Discovery: document issuer "${document.issuer}" does not match the configured issuer "${issuerUrl}"`);
78
91
  }
79
92
  const issuerOrigin = new URL(issuerUrl).origin;
80
- if (new URL(document.jwks_uri).origin !== issuerOrigin) {
81
- throw new Error(`Discovery: jwks_uri "${document.jwks_uri}" is not same-origin as issuer "${issuerUrl}"`);
82
- }
83
- if (new URL(document.token_endpoint).origin !== issuerOrigin) {
84
- throw new Error(`Discovery: token_endpoint "${document.token_endpoint}" is not same-origin as issuer "${issuerUrl}"`);
85
- }
86
- if (new URL(document.authorization_endpoint).origin !== issuerOrigin) {
87
- throw new Error(`Discovery: authorization_endpoint "${document.authorization_endpoint}" is not same-origin as issuer "${issuerUrl}"`);
93
+ for (const { field, required } of ENDPOINT_FIELDS) {
94
+ const value = document[field];
95
+ if (value === void 0 && !required) continue;
96
+ if (typeof value !== "string") {
97
+ const requirement = required ? "is required and must be a string" : ", if present, must be a string";
98
+ throw new Error(`Discovery: ${field} ${requirement}`);
99
+ }
100
+ validateEndpointField(field, value, issuerOrigin);
88
101
  }
89
102
  }
90
103
  async function fetchDiscovery(issuerUrl) {
@@ -166,6 +179,16 @@ var TokenRequestError = class extends Error {
166
179
  this.errorDescription = details.errorDescription;
167
180
  }
168
181
  };
182
+ async function fetchDiscoveryForTokenRequest(issuer) {
183
+ try {
184
+ return await fetchDiscovery(issuer);
185
+ } catch (error) {
186
+ throw new TokenRequestError({
187
+ error: "discovery_failed",
188
+ errorDescription: error instanceof Error ? error.message : "Failed to fetch the issuer's discovery document"
189
+ });
190
+ }
191
+ }
169
192
  function toTokenSet(body) {
170
193
  return {
171
194
  accessToken: body.access_token,
@@ -196,7 +219,7 @@ async function readTokenResponseBody(response) {
196
219
  return await response.json().catch(() => null);
197
220
  }
198
221
  async function exchangeAuthorizationCode(options) {
199
- const discovery = await fetchDiscovery(options.issuer);
222
+ const discovery = await fetchDiscoveryForTokenRequest(options.issuer);
200
223
  const response = await postTokenRequest(
201
224
  discovery.token_endpoint,
202
225
  options.clientId,
@@ -216,7 +239,7 @@ async function exchangeAuthorizationCode(options) {
216
239
  return toTokenSet(body);
217
240
  }
218
241
  async function clientCredentialsGrant(options) {
219
- const discovery = await fetchDiscovery(options.issuer);
242
+ const discovery = await fetchDiscoveryForTokenRequest(options.issuer);
220
243
  const response = await postTokenRequest(
221
244
  discovery.token_endpoint,
222
245
  options.clientId,
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  refreshTokens,
12
12
  verifyAccessToken,
13
13
  verifyIdToken
14
- } from "./chunk-TTFIPEZ3.js";
14
+ } from "./chunk-HO6U23GY.js";
15
15
  export {
16
16
  CLOCK_SKEW_TOLERANCE_SECONDS,
17
17
  TokenRequestError,
package/dist/next.cjs CHANGED
@@ -59,23 +59,36 @@ function assertHttps(url, label) {
59
59
  throw new Error(`Discovery: ${label} "${url}" must be https (loopback hosts are the only http exception)`);
60
60
  }
61
61
  }
62
+ var ENDPOINT_FIELDS = [
63
+ { field: "jwks_uri", required: true },
64
+ { field: "token_endpoint", required: true },
65
+ { field: "authorization_endpoint", required: true },
66
+ { field: "userinfo_endpoint", required: false },
67
+ { field: "end_session_endpoint", required: false },
68
+ { field: "revocation_endpoint", required: false },
69
+ { field: "introspection_endpoint", required: false },
70
+ { field: "registration_endpoint", required: false }
71
+ ];
72
+ function validateEndpointField(field, url, issuerOrigin) {
73
+ assertHttps(url, field);
74
+ if (new URL(url).origin !== issuerOrigin) {
75
+ throw new Error(`Discovery: ${field} "${url}" is not same-origin as issuer`);
76
+ }
77
+ }
62
78
  function validateDiscoveryDocument(document, issuerUrl) {
63
79
  assertHttps(issuerUrl, "issuer");
64
- assertHttps(document.jwks_uri, "jwks_uri");
65
- assertHttps(document.token_endpoint, "token_endpoint");
66
- assertHttps(document.authorization_endpoint, "authorization_endpoint");
67
80
  if (document.issuer !== issuerUrl) {
68
81
  throw new Error(`Discovery: document issuer "${document.issuer}" does not match the configured issuer "${issuerUrl}"`);
69
82
  }
70
83
  const issuerOrigin = new URL(issuerUrl).origin;
71
- if (new URL(document.jwks_uri).origin !== issuerOrigin) {
72
- throw new Error(`Discovery: jwks_uri "${document.jwks_uri}" is not same-origin as issuer "${issuerUrl}"`);
73
- }
74
- if (new URL(document.token_endpoint).origin !== issuerOrigin) {
75
- throw new Error(`Discovery: token_endpoint "${document.token_endpoint}" is not same-origin as issuer "${issuerUrl}"`);
76
- }
77
- if (new URL(document.authorization_endpoint).origin !== issuerOrigin) {
78
- throw new Error(`Discovery: authorization_endpoint "${document.authorization_endpoint}" is not same-origin as issuer "${issuerUrl}"`);
84
+ for (const { field, required } of ENDPOINT_FIELDS) {
85
+ const value = document[field];
86
+ if (value === void 0 && !required) continue;
87
+ if (typeof value !== "string") {
88
+ const requirement = required ? "is required and must be a string" : ", if present, must be a string";
89
+ throw new Error(`Discovery: ${field} ${requirement}`);
90
+ }
91
+ validateEndpointField(field, value, issuerOrigin);
79
92
  }
80
93
  }
81
94
  async function fetchDiscovery(issuerUrl) {
@@ -157,6 +170,16 @@ var TokenRequestError = class extends Error {
157
170
  this.errorDescription = details.errorDescription;
158
171
  }
159
172
  };
173
+ async function fetchDiscoveryForTokenRequest(issuer) {
174
+ try {
175
+ return await fetchDiscovery(issuer);
176
+ } catch (error) {
177
+ throw new TokenRequestError({
178
+ error: "discovery_failed",
179
+ errorDescription: error instanceof Error ? error.message : "Failed to fetch the issuer's discovery document"
180
+ });
181
+ }
182
+ }
160
183
  function toTokenSet(body) {
161
184
  return {
162
185
  accessToken: body.access_token,
@@ -187,7 +210,7 @@ async function readTokenResponseBody(response) {
187
210
  return await response.json().catch(() => null);
188
211
  }
189
212
  async function exchangeAuthorizationCode(options) {
190
- const discovery = await fetchDiscovery(options.issuer);
213
+ const discovery = await fetchDiscoveryForTokenRequest(options.issuer);
191
214
  const response = await postTokenRequest(
192
215
  discovery.token_endpoint,
193
216
  options.clientId,
package/dist/next.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  generateCodeVerifier,
6
6
  generateState,
7
7
  verifyIdToken
8
- } from "./chunk-TTFIPEZ3.js";
8
+ } from "./chunk-HO6U23GY.js";
9
9
  import {
10
10
  seal,
11
11
  unseal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tdacorp/identity-client",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "OIDC relying-party client for TDACorp Identity: discovery, PKCE, token exchange, token verification and Next.js route helpers.",
5
5
  "license": "MIT",
6
6
  "bugs": {
@@ -55,7 +55,7 @@
55
55
  ],
56
56
  "dependencies": {
57
57
  "jose": "^6.2.9",
58
- "@tdacorp/identity-authz": "^0.2.0"
58
+ "@tdacorp/identity-authz": "^0.2.1"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "next": ">=14"