@tdacorp/identity-client 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -6
- package/dist/{chunk-VJSMXIZB.js → chunk-6WGVTO7C.js} +37 -16
- package/dist/index.cjs +37 -16
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/next.cjs +17 -8
- package/dist/next.d.cts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +1 -1
- package/dist/{verify-BiGhwaIz.d.cts → verify-DTUDjR4v.d.cts} +35 -1
- package/dist/{verify-BiGhwaIz.d.ts → verify-DTUDjR4v.d.ts} +35 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -160,6 +160,23 @@ const tokens = await exchangeAuthorizationCode({
|
|
|
160
160
|
})
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
If your relying party is registered on the identity platform for
|
|
164
|
+
`client_secret_post` rather than the default `client_secret_basic`, pass
|
|
165
|
+
`clientAuthMethod` so credentials are sent the way the token endpoint
|
|
166
|
+
actually expects them:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
const tokens = await exchangeAuthorizationCode({
|
|
170
|
+
issuer: 'https://identity.tdacorp.in',
|
|
171
|
+
clientId: process.env.IDENTITY_CLIENT_ID!,
|
|
172
|
+
clientSecret: process.env.IDENTITY_CLIENT_SECRET!,
|
|
173
|
+
clientAuthMethod: 'client_secret_post',
|
|
174
|
+
code,
|
|
175
|
+
redirectUri,
|
|
176
|
+
codeVerifier,
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
163
180
|
Refresh (RFC 6749 §6), returning a classified outcome instead of throwing —
|
|
164
181
|
so a transient infrastructure failure is never mistaken for a rejected
|
|
165
182
|
refresh token:
|
|
@@ -269,12 +286,6 @@ instead.
|
|
|
269
286
|
|
|
270
287
|
## Limitations in v0.1
|
|
271
288
|
|
|
272
|
-
- **Only `client_secret_basic` client authentication is supported** for the
|
|
273
|
-
authorization-code exchange (`exchangeAuthorizationCode` sends an HTTP
|
|
274
|
-
Basic `Authorization` header when a `clientSecret` is given). A relying
|
|
275
|
-
party configured on TDACorp Identity for `client_secret_post` cannot use
|
|
276
|
-
`exchangeAuthorizationCode` as-is today — the token endpoint will reject
|
|
277
|
-
the request.
|
|
278
289
|
- **No built-in fallback for an `indeterminate` `permits()` result.** That is
|
|
279
290
|
`@tdacorp/identity-authz`'s concern, not this package's, but worth knowing
|
|
280
291
|
up front since most integrations hit both together — see that package's
|
|
@@ -135,13 +135,16 @@ function toTokenSet(body) {
|
|
|
135
135
|
scope: body.scope
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
|
-
async function postTokenRequest(tokenEndpoint, clientId, clientSecret, params) {
|
|
138
|
+
async function postTokenRequest(tokenEndpoint, clientId, clientSecret, clientAuthMethod, params) {
|
|
139
139
|
const body = new URLSearchParams(params);
|
|
140
140
|
const headers = {
|
|
141
141
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
142
142
|
Accept: "application/json"
|
|
143
143
|
};
|
|
144
|
-
if (clientSecret) {
|
|
144
|
+
if (clientSecret && clientAuthMethod === "client_secret_post") {
|
|
145
|
+
body.set("client_id", clientId);
|
|
146
|
+
body.set("client_secret", clientSecret);
|
|
147
|
+
} else if (clientSecret) {
|
|
145
148
|
headers.Authorization = `Basic ${btoa(`${clientId}:${clientSecret}`)}`;
|
|
146
149
|
} else {
|
|
147
150
|
body.set("client_id", clientId);
|
|
@@ -153,12 +156,18 @@ async function readTokenResponseBody(response) {
|
|
|
153
156
|
}
|
|
154
157
|
async function exchangeAuthorizationCode(options) {
|
|
155
158
|
const discovery = await fetchDiscovery(options.issuer);
|
|
156
|
-
const response = await postTokenRequest(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
const response = await postTokenRequest(
|
|
160
|
+
discovery.token_endpoint,
|
|
161
|
+
options.clientId,
|
|
162
|
+
options.clientSecret,
|
|
163
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
164
|
+
{
|
|
165
|
+
grant_type: "authorization_code",
|
|
166
|
+
code: options.code,
|
|
167
|
+
redirect_uri: options.redirectUri,
|
|
168
|
+
code_verifier: options.codeVerifier
|
|
169
|
+
}
|
|
170
|
+
);
|
|
162
171
|
const body = await readTokenResponseBody(response);
|
|
163
172
|
if (!response.ok || !body || body.error || typeof body.access_token !== "string") {
|
|
164
173
|
throw new TokenRequestError({ status: response.status, error: body?.error, errorDescription: body?.error_description });
|
|
@@ -167,10 +176,16 @@ async function exchangeAuthorizationCode(options) {
|
|
|
167
176
|
}
|
|
168
177
|
async function clientCredentialsGrant(options) {
|
|
169
178
|
const discovery = await fetchDiscovery(options.issuer);
|
|
170
|
-
const response = await postTokenRequest(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
const response = await postTokenRequest(
|
|
180
|
+
discovery.token_endpoint,
|
|
181
|
+
options.clientId,
|
|
182
|
+
options.clientSecret,
|
|
183
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
184
|
+
{
|
|
185
|
+
grant_type: "client_credentials",
|
|
186
|
+
...options.scope ? { scope: options.scope } : {}
|
|
187
|
+
}
|
|
188
|
+
);
|
|
174
189
|
const body = await readTokenResponseBody(response);
|
|
175
190
|
if (!response.ok || !body || body.error || typeof body.access_token !== "string") {
|
|
176
191
|
throw new TokenRequestError({ status: response.status, error: body?.error, errorDescription: body?.error_description });
|
|
@@ -185,10 +200,16 @@ async function refreshTokens(options) {
|
|
|
185
200
|
let response;
|
|
186
201
|
try {
|
|
187
202
|
const discovery = await fetchDiscovery(options.issuer);
|
|
188
|
-
response = await postTokenRequest(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
response = await postTokenRequest(
|
|
204
|
+
discovery.token_endpoint,
|
|
205
|
+
options.clientId,
|
|
206
|
+
options.clientSecret,
|
|
207
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
208
|
+
{
|
|
209
|
+
grant_type: "refresh_token",
|
|
210
|
+
refresh_token: options.refreshToken
|
|
211
|
+
}
|
|
212
|
+
);
|
|
192
213
|
} catch (error) {
|
|
193
214
|
return { outcome: "transient", error };
|
|
194
215
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -172,13 +172,16 @@ function toTokenSet(body) {
|
|
|
172
172
|
scope: body.scope
|
|
173
173
|
};
|
|
174
174
|
}
|
|
175
|
-
async function postTokenRequest(tokenEndpoint, clientId, clientSecret, params) {
|
|
175
|
+
async function postTokenRequest(tokenEndpoint, clientId, clientSecret, clientAuthMethod, params) {
|
|
176
176
|
const body = new URLSearchParams(params);
|
|
177
177
|
const headers = {
|
|
178
178
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
179
179
|
Accept: "application/json"
|
|
180
180
|
};
|
|
181
|
-
if (clientSecret) {
|
|
181
|
+
if (clientSecret && clientAuthMethod === "client_secret_post") {
|
|
182
|
+
body.set("client_id", clientId);
|
|
183
|
+
body.set("client_secret", clientSecret);
|
|
184
|
+
} else if (clientSecret) {
|
|
182
185
|
headers.Authorization = `Basic ${btoa(`${clientId}:${clientSecret}`)}`;
|
|
183
186
|
} else {
|
|
184
187
|
body.set("client_id", clientId);
|
|
@@ -190,12 +193,18 @@ async function readTokenResponseBody(response) {
|
|
|
190
193
|
}
|
|
191
194
|
async function exchangeAuthorizationCode(options) {
|
|
192
195
|
const discovery = await fetchDiscovery(options.issuer);
|
|
193
|
-
const response = await postTokenRequest(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
const response = await postTokenRequest(
|
|
197
|
+
discovery.token_endpoint,
|
|
198
|
+
options.clientId,
|
|
199
|
+
options.clientSecret,
|
|
200
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
201
|
+
{
|
|
202
|
+
grant_type: "authorization_code",
|
|
203
|
+
code: options.code,
|
|
204
|
+
redirect_uri: options.redirectUri,
|
|
205
|
+
code_verifier: options.codeVerifier
|
|
206
|
+
}
|
|
207
|
+
);
|
|
199
208
|
const body = await readTokenResponseBody(response);
|
|
200
209
|
if (!response.ok || !body || body.error || typeof body.access_token !== "string") {
|
|
201
210
|
throw new TokenRequestError({ status: response.status, error: body?.error, errorDescription: body?.error_description });
|
|
@@ -204,10 +213,16 @@ async function exchangeAuthorizationCode(options) {
|
|
|
204
213
|
}
|
|
205
214
|
async function clientCredentialsGrant(options) {
|
|
206
215
|
const discovery = await fetchDiscovery(options.issuer);
|
|
207
|
-
const response = await postTokenRequest(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
const response = await postTokenRequest(
|
|
217
|
+
discovery.token_endpoint,
|
|
218
|
+
options.clientId,
|
|
219
|
+
options.clientSecret,
|
|
220
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
221
|
+
{
|
|
222
|
+
grant_type: "client_credentials",
|
|
223
|
+
...options.scope ? { scope: options.scope } : {}
|
|
224
|
+
}
|
|
225
|
+
);
|
|
211
226
|
const body = await readTokenResponseBody(response);
|
|
212
227
|
if (!response.ok || !body || body.error || typeof body.access_token !== "string") {
|
|
213
228
|
throw new TokenRequestError({ status: response.status, error: body?.error, errorDescription: body?.error_description });
|
|
@@ -222,10 +237,16 @@ async function refreshTokens(options) {
|
|
|
222
237
|
let response;
|
|
223
238
|
try {
|
|
224
239
|
const discovery = await fetchDiscovery(options.issuer);
|
|
225
|
-
response = await postTokenRequest(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
240
|
+
response = await postTokenRequest(
|
|
241
|
+
discovery.token_endpoint,
|
|
242
|
+
options.clientId,
|
|
243
|
+
options.clientSecret,
|
|
244
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
245
|
+
{
|
|
246
|
+
grant_type: "refresh_token",
|
|
247
|
+
refresh_token: options.refreshToken
|
|
248
|
+
}
|
|
249
|
+
);
|
|
229
250
|
} catch (error) {
|
|
230
251
|
return { outcome: "transient", error };
|
|
231
252
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRemoteJWKSet } from 'jose';
|
|
2
|
-
export { A as AuthorizationCodeExchangeOptions, C as CLOCK_SKEW_TOLERANCE_SECONDS, a as ClientCredentialsGrantOptions, I as IdTokenClaims, R as RefreshTokensOptions, T as
|
|
2
|
+
export { A as AuthorizationCodeExchangeOptions, C as CLOCK_SKEW_TOLERANCE_SECONDS, a as ClientCredentialsGrantOptions, I as IdTokenClaims, R as RefreshTokensOptions, T as TokenEndpointAuthMethod, b as TokenRefreshOutcome, c as TokenRequestError, d as TokenSet, e as TokenVerificationError, f as TokenVerificationErrorCode, V as VerificationResult, g as VerifiedAccessToken, h as VerifyTokenOptions, i as clientCredentialsGrant, j as exchangeAuthorizationCode, r as refreshTokens, v as verifyAccessToken, k as verifyIdToken } from './verify-DTUDjR4v.cjs';
|
|
3
3
|
import '@tdacorp/identity-authz';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRemoteJWKSet } from 'jose';
|
|
2
|
-
export { A as AuthorizationCodeExchangeOptions, C as CLOCK_SKEW_TOLERANCE_SECONDS, a as ClientCredentialsGrantOptions, I as IdTokenClaims, R as RefreshTokensOptions, T as
|
|
2
|
+
export { A as AuthorizationCodeExchangeOptions, C as CLOCK_SKEW_TOLERANCE_SECONDS, a as ClientCredentialsGrantOptions, I as IdTokenClaims, R as RefreshTokensOptions, T as TokenEndpointAuthMethod, b as TokenRefreshOutcome, c as TokenRequestError, d as TokenSet, e as TokenVerificationError, f as TokenVerificationErrorCode, V as VerificationResult, g as VerifiedAccessToken, h as VerifyTokenOptions, i as clientCredentialsGrant, j as exchangeAuthorizationCode, r as refreshTokens, v as verifyAccessToken, k as verifyIdToken } from './verify-DTUDjR4v.js';
|
|
3
3
|
import '@tdacorp/identity-authz';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.js
CHANGED
package/dist/next.cjs
CHANGED
|
@@ -163,13 +163,16 @@ function toTokenSet(body) {
|
|
|
163
163
|
scope: body.scope
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
-
async function postTokenRequest(tokenEndpoint, clientId, clientSecret, params) {
|
|
166
|
+
async function postTokenRequest(tokenEndpoint, clientId, clientSecret, clientAuthMethod, params) {
|
|
167
167
|
const body = new URLSearchParams(params);
|
|
168
168
|
const headers = {
|
|
169
169
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
170
170
|
Accept: "application/json"
|
|
171
171
|
};
|
|
172
|
-
if (clientSecret) {
|
|
172
|
+
if (clientSecret && clientAuthMethod === "client_secret_post") {
|
|
173
|
+
body.set("client_id", clientId);
|
|
174
|
+
body.set("client_secret", clientSecret);
|
|
175
|
+
} else if (clientSecret) {
|
|
173
176
|
headers.Authorization = `Basic ${btoa(`${clientId}:${clientSecret}`)}`;
|
|
174
177
|
} else {
|
|
175
178
|
body.set("client_id", clientId);
|
|
@@ -181,12 +184,18 @@ async function readTokenResponseBody(response) {
|
|
|
181
184
|
}
|
|
182
185
|
async function exchangeAuthorizationCode(options) {
|
|
183
186
|
const discovery = await fetchDiscovery(options.issuer);
|
|
184
|
-
const response = await postTokenRequest(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
const response = await postTokenRequest(
|
|
188
|
+
discovery.token_endpoint,
|
|
189
|
+
options.clientId,
|
|
190
|
+
options.clientSecret,
|
|
191
|
+
options.clientAuthMethod ?? "client_secret_basic",
|
|
192
|
+
{
|
|
193
|
+
grant_type: "authorization_code",
|
|
194
|
+
code: options.code,
|
|
195
|
+
redirect_uri: options.redirectUri,
|
|
196
|
+
code_verifier: options.codeVerifier
|
|
197
|
+
}
|
|
198
|
+
);
|
|
190
199
|
const body = await readTokenResponseBody(response);
|
|
191
200
|
if (!response.ok || !body || body.error || typeof body.access_token !== "string") {
|
|
192
201
|
throw new TokenRequestError({ status: response.status, error: body?.error, errorDescription: body?.error_description });
|
package/dist/next.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse, NextRequest } from 'next/server';
|
|
2
|
-
import {
|
|
2
|
+
import { d as TokenSet, I as IdTokenClaims } from './verify-DTUDjR4v.cjs';
|
|
3
3
|
import { SealSecret } from './sealed.cjs';
|
|
4
4
|
import '@tdacorp/identity-authz';
|
|
5
5
|
import 'jose';
|
package/dist/next.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse, NextRequest } from 'next/server';
|
|
2
|
-
import {
|
|
2
|
+
import { d as TokenSet, I as IdTokenClaims } from './verify-DTUDjR4v.js';
|
|
3
3
|
import { SealSecret } from './sealed.js';
|
|
4
4
|
import '@tdacorp/identity-authz';
|
|
5
5
|
import 'jose';
|
package/dist/next.js
CHANGED
|
@@ -31,6 +31,10 @@ declare class TokenRequestError extends Error {
|
|
|
31
31
|
errorDescription?: string;
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
/** The token endpoint client-authentication methods this package supports --
|
|
35
|
+
* see RFC 6749 §2.3.1 and OIDC Discovery 1.0's
|
|
36
|
+
* `token_endpoint_auth_methods_supported`. */
|
|
37
|
+
type TokenEndpointAuthMethod = 'client_secret_basic' | 'client_secret_post';
|
|
34
38
|
/** Options for `exchangeAuthorizationCode`. */
|
|
35
39
|
interface AuthorizationCodeExchangeOptions {
|
|
36
40
|
/** The identity server's issuer URL, used to look up `token_endpoint`. */
|
|
@@ -46,6 +50,16 @@ interface AuthorizationCodeExchangeOptions {
|
|
|
46
50
|
/** The PKCE verifier generated (and kept) alongside the code challenge
|
|
47
51
|
* sent on the authorization request; see `generateCodeVerifier`. */
|
|
48
52
|
codeVerifier: string;
|
|
53
|
+
/** How to send `clientSecret` to the token endpoint. Defaults to
|
|
54
|
+
* `'client_secret_basic'`, which is this package's original and only
|
|
55
|
+
* behavior -- omitting this field changes nothing for an existing caller.
|
|
56
|
+
* Set it to `'client_secret_post'` if the relying party is registered on
|
|
57
|
+
* the identity platform for that method instead: sending Basic auth to a
|
|
58
|
+
* `client_secret_post`-only client gets `invalid_client` back, since the
|
|
59
|
+
* token endpoint never receives credentials in the form it expects. An
|
|
60
|
+
* issuer's OIDC discovery document's `token_endpoint_auth_methods_supported`
|
|
61
|
+
* says which methods it actually accepts. */
|
|
62
|
+
clientAuthMethod?: TokenEndpointAuthMethod;
|
|
49
63
|
}
|
|
50
64
|
/** RFC 6749 §4.1.3 / RFC 7636 §4.5: exchanges an authorization code for a
|
|
51
65
|
* token set. Throws `TokenRequestError` on any non-success response. */
|
|
@@ -60,6 +74,16 @@ interface ClientCredentialsGrantOptions {
|
|
|
60
74
|
clientSecret: string;
|
|
61
75
|
/** Space-separated scopes to request for the resulting token. */
|
|
62
76
|
scope?: string;
|
|
77
|
+
/** How to send `clientSecret` to the token endpoint. Defaults to
|
|
78
|
+
* `'client_secret_basic'`, which is this package's original and only
|
|
79
|
+
* behavior -- omitting this field changes nothing for an existing caller.
|
|
80
|
+
* Set it to `'client_secret_post'` if the relying party is registered on
|
|
81
|
+
* the identity platform for that method instead: sending Basic auth to a
|
|
82
|
+
* `client_secret_post`-only client gets `invalid_client` back, since the
|
|
83
|
+
* token endpoint never receives credentials in the form it expects. An
|
|
84
|
+
* issuer's OIDC discovery document's `token_endpoint_auth_methods_supported`
|
|
85
|
+
* says which methods it actually accepts. */
|
|
86
|
+
clientAuthMethod?: TokenEndpointAuthMethod;
|
|
63
87
|
}
|
|
64
88
|
/** RFC 6749 §4.4: mints a token with no end user, for service-to-service
|
|
65
89
|
* calls. Always confidential -- `clientSecret` is required, not optional,
|
|
@@ -75,6 +99,16 @@ interface RefreshTokensOptions {
|
|
|
75
99
|
clientSecret?: string;
|
|
76
100
|
/** The refresh token to redeem. */
|
|
77
101
|
refreshToken: string;
|
|
102
|
+
/** How to send `clientSecret` to the token endpoint. Defaults to
|
|
103
|
+
* `'client_secret_basic'`, which is this package's original and only
|
|
104
|
+
* behavior -- omitting this field changes nothing for an existing caller.
|
|
105
|
+
* Set it to `'client_secret_post'` if the relying party is registered on
|
|
106
|
+
* the identity platform for that method instead: sending Basic auth to a
|
|
107
|
+
* `client_secret_post`-only client gets `invalid_client` back, since the
|
|
108
|
+
* token endpoint never receives credentials in the form it expects. An
|
|
109
|
+
* issuer's OIDC discovery document's `token_endpoint_auth_methods_supported`
|
|
110
|
+
* says which methods it actually accepts. */
|
|
111
|
+
clientAuthMethod?: TokenEndpointAuthMethod;
|
|
78
112
|
}
|
|
79
113
|
type TokenRefreshOutcome = {
|
|
80
114
|
outcome: 'success';
|
|
@@ -303,4 +337,4 @@ declare function verifyIdToken(idToken: string, options: VerifyTokenOptions): Pr
|
|
|
303
337
|
* contract as `verifyIdToken`. */
|
|
304
338
|
declare function verifyAccessToken(accessToken: string, options: VerifyTokenOptions): Promise<VerificationResult<VerifiedAccessToken>>;
|
|
305
339
|
|
|
306
|
-
export { type AuthorizationCodeExchangeOptions as A, CLOCK_SKEW_TOLERANCE_SECONDS as C, type IdTokenClaims as I, type RefreshTokensOptions as R, type
|
|
340
|
+
export { type AuthorizationCodeExchangeOptions as A, CLOCK_SKEW_TOLERANCE_SECONDS as C, type IdTokenClaims as I, type RefreshTokensOptions as R, type TokenEndpointAuthMethod as T, type VerificationResult as V, type ClientCredentialsGrantOptions as a, type TokenRefreshOutcome as b, TokenRequestError as c, type TokenSet as d, type TokenVerificationError as e, type TokenVerificationErrorCode as f, type VerifiedAccessToken as g, type VerifyTokenOptions as h, clientCredentialsGrant as i, exchangeAuthorizationCode as j, verifyIdToken as k, refreshTokens as r, verifyAccessToken as v };
|
|
@@ -31,6 +31,10 @@ declare class TokenRequestError extends Error {
|
|
|
31
31
|
errorDescription?: string;
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
/** The token endpoint client-authentication methods this package supports --
|
|
35
|
+
* see RFC 6749 §2.3.1 and OIDC Discovery 1.0's
|
|
36
|
+
* `token_endpoint_auth_methods_supported`. */
|
|
37
|
+
type TokenEndpointAuthMethod = 'client_secret_basic' | 'client_secret_post';
|
|
34
38
|
/** Options for `exchangeAuthorizationCode`. */
|
|
35
39
|
interface AuthorizationCodeExchangeOptions {
|
|
36
40
|
/** The identity server's issuer URL, used to look up `token_endpoint`. */
|
|
@@ -46,6 +50,16 @@ interface AuthorizationCodeExchangeOptions {
|
|
|
46
50
|
/** The PKCE verifier generated (and kept) alongside the code challenge
|
|
47
51
|
* sent on the authorization request; see `generateCodeVerifier`. */
|
|
48
52
|
codeVerifier: string;
|
|
53
|
+
/** How to send `clientSecret` to the token endpoint. Defaults to
|
|
54
|
+
* `'client_secret_basic'`, which is this package's original and only
|
|
55
|
+
* behavior -- omitting this field changes nothing for an existing caller.
|
|
56
|
+
* Set it to `'client_secret_post'` if the relying party is registered on
|
|
57
|
+
* the identity platform for that method instead: sending Basic auth to a
|
|
58
|
+
* `client_secret_post`-only client gets `invalid_client` back, since the
|
|
59
|
+
* token endpoint never receives credentials in the form it expects. An
|
|
60
|
+
* issuer's OIDC discovery document's `token_endpoint_auth_methods_supported`
|
|
61
|
+
* says which methods it actually accepts. */
|
|
62
|
+
clientAuthMethod?: TokenEndpointAuthMethod;
|
|
49
63
|
}
|
|
50
64
|
/** RFC 6749 §4.1.3 / RFC 7636 §4.5: exchanges an authorization code for a
|
|
51
65
|
* token set. Throws `TokenRequestError` on any non-success response. */
|
|
@@ -60,6 +74,16 @@ interface ClientCredentialsGrantOptions {
|
|
|
60
74
|
clientSecret: string;
|
|
61
75
|
/** Space-separated scopes to request for the resulting token. */
|
|
62
76
|
scope?: string;
|
|
77
|
+
/** How to send `clientSecret` to the token endpoint. Defaults to
|
|
78
|
+
* `'client_secret_basic'`, which is this package's original and only
|
|
79
|
+
* behavior -- omitting this field changes nothing for an existing caller.
|
|
80
|
+
* Set it to `'client_secret_post'` if the relying party is registered on
|
|
81
|
+
* the identity platform for that method instead: sending Basic auth to a
|
|
82
|
+
* `client_secret_post`-only client gets `invalid_client` back, since the
|
|
83
|
+
* token endpoint never receives credentials in the form it expects. An
|
|
84
|
+
* issuer's OIDC discovery document's `token_endpoint_auth_methods_supported`
|
|
85
|
+
* says which methods it actually accepts. */
|
|
86
|
+
clientAuthMethod?: TokenEndpointAuthMethod;
|
|
63
87
|
}
|
|
64
88
|
/** RFC 6749 §4.4: mints a token with no end user, for service-to-service
|
|
65
89
|
* calls. Always confidential -- `clientSecret` is required, not optional,
|
|
@@ -75,6 +99,16 @@ interface RefreshTokensOptions {
|
|
|
75
99
|
clientSecret?: string;
|
|
76
100
|
/** The refresh token to redeem. */
|
|
77
101
|
refreshToken: string;
|
|
102
|
+
/** How to send `clientSecret` to the token endpoint. Defaults to
|
|
103
|
+
* `'client_secret_basic'`, which is this package's original and only
|
|
104
|
+
* behavior -- omitting this field changes nothing for an existing caller.
|
|
105
|
+
* Set it to `'client_secret_post'` if the relying party is registered on
|
|
106
|
+
* the identity platform for that method instead: sending Basic auth to a
|
|
107
|
+
* `client_secret_post`-only client gets `invalid_client` back, since the
|
|
108
|
+
* token endpoint never receives credentials in the form it expects. An
|
|
109
|
+
* issuer's OIDC discovery document's `token_endpoint_auth_methods_supported`
|
|
110
|
+
* says which methods it actually accepts. */
|
|
111
|
+
clientAuthMethod?: TokenEndpointAuthMethod;
|
|
78
112
|
}
|
|
79
113
|
type TokenRefreshOutcome = {
|
|
80
114
|
outcome: 'success';
|
|
@@ -303,4 +337,4 @@ declare function verifyIdToken(idToken: string, options: VerifyTokenOptions): Pr
|
|
|
303
337
|
* contract as `verifyIdToken`. */
|
|
304
338
|
declare function verifyAccessToken(accessToken: string, options: VerifyTokenOptions): Promise<VerificationResult<VerifiedAccessToken>>;
|
|
305
339
|
|
|
306
|
-
export { type AuthorizationCodeExchangeOptions as A, CLOCK_SKEW_TOLERANCE_SECONDS as C, type IdTokenClaims as I, type RefreshTokensOptions as R, type
|
|
340
|
+
export { type AuthorizationCodeExchangeOptions as A, CLOCK_SKEW_TOLERANCE_SECONDS as C, type IdTokenClaims as I, type RefreshTokensOptions as R, type TokenEndpointAuthMethod as T, type VerificationResult as V, type ClientCredentialsGrantOptions as a, type TokenRefreshOutcome as b, TokenRequestError as c, type TokenSet as d, type TokenVerificationError as e, type TokenVerificationErrorCode as f, type VerifiedAccessToken as g, type VerifyTokenOptions as h, clientCredentialsGrant as i, exchangeAuthorizationCode as j, verifyIdToken as k, refreshTokens as r, verifyAccessToken as v };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tdacorp/identity-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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": {
|
|
@@ -50,17 +50,12 @@
|
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build": "tsup",
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
56
|
-
"test": "vitest run"
|
|
57
|
-
},
|
|
58
53
|
"files": [
|
|
59
54
|
"dist"
|
|
60
55
|
],
|
|
61
56
|
"dependencies": {
|
|
62
|
-
"
|
|
63
|
-
"
|
|
57
|
+
"jose": "^6.2.9",
|
|
58
|
+
"@tdacorp/identity-authz": "^0.2.0"
|
|
64
59
|
},
|
|
65
60
|
"peerDependencies": {
|
|
66
61
|
"next": ">=14"
|
|
@@ -71,10 +66,15 @@
|
|
|
71
66
|
}
|
|
72
67
|
},
|
|
73
68
|
"devDependencies": {
|
|
74
|
-
"@tdacorp/typescript-config": "workspace:*",
|
|
75
69
|
"next": "^16.3.2",
|
|
76
70
|
"tsup": "^8.5.1",
|
|
77
71
|
"typescript": "^5.7.3",
|
|
78
|
-
"vitest": "^4.1.11"
|
|
72
|
+
"vitest": "^4.1.11",
|
|
73
|
+
"@tdacorp/typescript-config": "0.0.0"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"build": "tsup",
|
|
77
|
+
"typecheck": "tsc --noEmit",
|
|
78
|
+
"test": "vitest run"
|
|
79
79
|
}
|
|
80
|
-
}
|
|
80
|
+
}
|