@incorta/auth 1.0.0 → 1.1.1
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 +10 -3
- package/dist/cli.js +189 -47
- package/dist/index.cjs +87 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +84 -13
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ guide; this is the API surface.
|
|
|
8
8
|
|
|
9
9
|
| Import | What's in it |
|
|
10
10
|
| ----------------------- | ------------------------------------------------------------------- |
|
|
11
|
-
| `@incorta/auth` | `createIncortaAuth`, `registerClient`, types (`IncortaUser`, `AuthSession`, …) |
|
|
11
|
+
| `@incorta/auth` | `createIncortaAuth`, `registerClient`, `getClient`, `updateClientRedirectUris`, types (`IncortaUser`, `AuthSession`, …) |
|
|
12
12
|
| `@incorta/auth/react` | `IncortaAuthProvider`, `useAuth`, `useUser`, `SignedIn`, `SignedOut`, `Protect`, `RedirectToLogin` |
|
|
13
13
|
| `@incorta/auth/express` | `incortaAuth(auth)` middleware, `requireAuth(auth, options?)` |
|
|
14
14
|
| `@incorta/auth/node` | `toNodeHandler(auth)`, `toWebRequest`, `sendWebResponse`, `getNodeSession` |
|
|
@@ -49,10 +49,17 @@ tokens. Nothing is stored server-side.
|
|
|
49
49
|
```bash
|
|
50
50
|
incorta-auth register --url http://localhost:8080/incorta --tenant demo \
|
|
51
51
|
--name "My App" --redirect https://myapp.example.com/auth/callback [--json]
|
|
52
|
+
|
|
53
|
+
incorta-auth show --url ... --tenant ... --client <id> --rat <token> [--json]
|
|
54
|
+
|
|
55
|
+
incorta-auth update-redirects --url ... --tenant ... --client <id> --rat <token> \
|
|
56
|
+
--redirect <url> [--redirect ...] [--replace] [--json]
|
|
52
57
|
```
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
`.env` entries.
|
|
59
|
+
`register` creates the OAuth client via RFC 7591 dynamic registration and
|
|
60
|
+
prints the `.env` entries (keep the registration access token). `show` and
|
|
61
|
+
`update-redirects` manage the registered client's allowed callback URLs —
|
|
62
|
+
adding by default, replacing the whole set with `--replace`.
|
|
56
63
|
|
|
57
64
|
## Testing
|
|
58
65
|
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
import { randomBytes } from "crypto";
|
|
5
5
|
|
|
6
6
|
// src/core/register.ts
|
|
7
|
+
function registrationEndpoint(incortaUrl, tenant, clientId) {
|
|
8
|
+
const base = `${incortaUrl.replace(/\/+$/, "")}/oauth/${tenant}/register`;
|
|
9
|
+
return clientId ? `${base}/${clientId}` : base;
|
|
10
|
+
}
|
|
11
|
+
async function readJson(response, what) {
|
|
12
|
+
let body;
|
|
13
|
+
try {
|
|
14
|
+
body = await response.json();
|
|
15
|
+
} catch {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`[incorta-auth] ${what} returned a non-JSON response (HTTP ${response.status}). Is the OAuth authorization server enabled on this cluster?`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`[incorta-auth] ${what} failed (HTTP ${response.status}): ${body.error ?? "unknown_error"} \u2014 ${body.error_description ?? "no description"}`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return body;
|
|
26
|
+
}
|
|
7
27
|
async function registerClient(options) {
|
|
8
28
|
const {
|
|
9
29
|
incortaUrl,
|
|
@@ -17,8 +37,7 @@ async function registerClient(options) {
|
|
|
17
37
|
if (!redirectUris.length) {
|
|
18
38
|
throw new Error("[incorta-auth] registerClient requires at least one redirect URI.");
|
|
19
39
|
}
|
|
20
|
-
const
|
|
21
|
-
const response = await fetchImpl(endpoint, {
|
|
40
|
+
const response = await fetchImpl(registrationEndpoint(incortaUrl, tenant), {
|
|
22
41
|
method: "POST",
|
|
23
42
|
headers: { "content-type": "application/json", accept: "application/json" },
|
|
24
43
|
body: JSON.stringify({
|
|
@@ -29,17 +48,10 @@ async function registerClient(options) {
|
|
|
29
48
|
token_endpoint_auth_method: "client_secret_basic"
|
|
30
49
|
})
|
|
31
50
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
body = await response.json();
|
|
35
|
-
} catch {
|
|
51
|
+
const body = await readJson(response, "Client registration");
|
|
52
|
+
if (!body.client_id || !body.client_secret) {
|
|
36
53
|
throw new Error(
|
|
37
|
-
`[incorta-auth] Client registration
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
if (!response.ok || !body.client_id || !body.client_secret) {
|
|
41
|
-
throw new Error(
|
|
42
|
-
`[incorta-auth] Client registration failed (HTTP ${response.status}): ${body.error ?? "unknown_error"} \u2014 ${body.error_description ?? "no description"}`
|
|
54
|
+
`[incorta-auth] Client registration failed: response is missing client_id/client_secret.`
|
|
43
55
|
);
|
|
44
56
|
}
|
|
45
57
|
return {
|
|
@@ -49,6 +61,63 @@ async function registerClient(options) {
|
|
|
49
61
|
registrationClientUri: body.registration_client_uri
|
|
50
62
|
};
|
|
51
63
|
}
|
|
64
|
+
function toClientInfo(body, fallbackClientId) {
|
|
65
|
+
return {
|
|
66
|
+
clientId: body.client_id ?? fallbackClientId,
|
|
67
|
+
name: body.client_name,
|
|
68
|
+
redirectUris: body.redirect_uris ?? [],
|
|
69
|
+
grantTypes: body.grant_types ?? [],
|
|
70
|
+
scope: body.scope
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function getClient(options) {
|
|
74
|
+
const { incortaUrl, tenant, clientId, registrationAccessToken, fetchImpl = fetch } = options;
|
|
75
|
+
const response = await fetchImpl(registrationEndpoint(incortaUrl, tenant, clientId), {
|
|
76
|
+
headers: {
|
|
77
|
+
accept: "application/json",
|
|
78
|
+
authorization: `Bearer ${registrationAccessToken}`
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const body = await readJson(response, "Reading the client");
|
|
82
|
+
return toClientInfo(body, clientId);
|
|
83
|
+
}
|
|
84
|
+
async function updateClientRedirectUris(options) {
|
|
85
|
+
const {
|
|
86
|
+
incortaUrl,
|
|
87
|
+
tenant,
|
|
88
|
+
clientId,
|
|
89
|
+
registrationAccessToken,
|
|
90
|
+
redirectUris,
|
|
91
|
+
mode = "add",
|
|
92
|
+
fetchImpl = fetch
|
|
93
|
+
} = options;
|
|
94
|
+
if (!redirectUris.length) {
|
|
95
|
+
throw new Error("[incorta-auth] updateClientRedirectUris requires at least one redirect URI.");
|
|
96
|
+
}
|
|
97
|
+
const current = await getClient(options);
|
|
98
|
+
const nextUris = mode === "add" ? [.../* @__PURE__ */ new Set([...current.redirectUris, ...redirectUris])] : redirectUris;
|
|
99
|
+
const response = await fetchImpl(registrationEndpoint(incortaUrl, tenant, clientId), {
|
|
100
|
+
method: "PUT",
|
|
101
|
+
headers: {
|
|
102
|
+
"content-type": "application/json",
|
|
103
|
+
accept: "application/json",
|
|
104
|
+
authorization: `Bearer ${registrationAccessToken}`
|
|
105
|
+
},
|
|
106
|
+
// RFC 7592 update: client_id + full metadata. Incorta applies
|
|
107
|
+
// redirect_uris only, but nimbus-side parsing wants the full shape.
|
|
108
|
+
body: JSON.stringify({
|
|
109
|
+
client_id: clientId,
|
|
110
|
+
redirect_uris: nextUris,
|
|
111
|
+
grant_types: current.grantTypes,
|
|
112
|
+
scope: current.scope,
|
|
113
|
+
client_name: current.name
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
await readJson(response, "Updating the client");
|
|
118
|
+
}
|
|
119
|
+
return getClient(options);
|
|
120
|
+
}
|
|
52
121
|
|
|
53
122
|
// src/cli.ts
|
|
54
123
|
var HELP = `incorta-auth \u2014 IncortaAuth SDK helper
|
|
@@ -58,8 +127,22 @@ Usage:
|
|
|
58
127
|
--redirect <callbackUrl> [--redirect <callbackUrl> ...] \\
|
|
59
128
|
[--scope "openid profile email"] [--json]
|
|
60
129
|
|
|
61
|
-
|
|
62
|
-
|
|
130
|
+
incorta-auth show --url <incortaUrl> --tenant <tenant> \\
|
|
131
|
+
--client <clientId> --rat <registrationAccessToken> [--json]
|
|
132
|
+
|
|
133
|
+
incorta-auth update-redirects --url <incortaUrl> --tenant <tenant> \\
|
|
134
|
+
--client <clientId> --rat <registrationAccessToken> \\
|
|
135
|
+
--redirect <callbackUrl> [--redirect ...] \\
|
|
136
|
+
[--replace] [--json]
|
|
137
|
+
|
|
138
|
+
register Registers an OAuth client in Incorta (RFC 7591 dynamic
|
|
139
|
+
registration) and prints the .env entries your app needs.
|
|
140
|
+
Keep the printed registration access token \u2014 it is the key
|
|
141
|
+
for show/update-redirects later.
|
|
142
|
+
show Prints a registered client's current metadata.
|
|
143
|
+
update-redirects Adds the given callback URLs to the client's allowed set
|
|
144
|
+
(or replaces the whole set with --replace, which is also how
|
|
145
|
+
URLs are removed).
|
|
63
146
|
|
|
64
147
|
Example:
|
|
65
148
|
incorta-auth register \\
|
|
@@ -69,7 +152,7 @@ Example:
|
|
|
69
152
|
--redirect http://localhost:4000/auth/callback
|
|
70
153
|
`;
|
|
71
154
|
function parseArgs(argv) {
|
|
72
|
-
const args = { redirects: [], json: false };
|
|
155
|
+
const args = { redirects: [], replace: false, json: false };
|
|
73
156
|
for (let i = 0; i < argv.length; i++) {
|
|
74
157
|
const flag = argv[i];
|
|
75
158
|
const next = () => {
|
|
@@ -90,9 +173,18 @@ function parseArgs(argv) {
|
|
|
90
173
|
case "--scope":
|
|
91
174
|
args.scope = next();
|
|
92
175
|
break;
|
|
176
|
+
case "--client":
|
|
177
|
+
args.client = next();
|
|
178
|
+
break;
|
|
179
|
+
case "--rat":
|
|
180
|
+
args.rat = next();
|
|
181
|
+
break;
|
|
93
182
|
case "--redirect":
|
|
94
183
|
args.redirects.push(next());
|
|
95
184
|
break;
|
|
185
|
+
case "--replace":
|
|
186
|
+
args.replace = true;
|
|
187
|
+
break;
|
|
96
188
|
case "--json":
|
|
97
189
|
args.json = true;
|
|
98
190
|
break;
|
|
@@ -102,36 +194,12 @@ function parseArgs(argv) {
|
|
|
102
194
|
}
|
|
103
195
|
return args;
|
|
104
196
|
}
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (command !== "register") {
|
|
112
|
-
console.error(`Unknown command: ${command}
|
|
113
|
-
`);
|
|
114
|
-
console.log(HELP);
|
|
115
|
-
return 1;
|
|
116
|
-
}
|
|
117
|
-
let args;
|
|
118
|
-
try {
|
|
119
|
-
args = parseArgs(rest);
|
|
120
|
-
} catch (error) {
|
|
121
|
-
console.error(`${error.message}
|
|
122
|
-
`);
|
|
123
|
-
console.log(HELP);
|
|
124
|
-
return 1;
|
|
125
|
-
}
|
|
126
|
-
const missing = ["url", "tenant", "name"].filter((key) => !args[key]);
|
|
127
|
-
if (missing.length || !args.redirects.length) {
|
|
128
|
-
console.error(
|
|
129
|
-
`Missing required flag(s): ${[...missing.map((m) => `--${m}`), ...args.redirects.length ? [] : ["--redirect"]].join(", ")}
|
|
130
|
-
`
|
|
131
|
-
);
|
|
132
|
-
console.log(HELP);
|
|
133
|
-
return 1;
|
|
134
|
-
}
|
|
197
|
+
function requireFlags(args, flags, needsRedirect) {
|
|
198
|
+
const missing = flags.filter((key) => !args[key]).map((key) => `--${key}`);
|
|
199
|
+
if (needsRedirect && !args.redirects.length) missing.push("--redirect");
|
|
200
|
+
return missing;
|
|
201
|
+
}
|
|
202
|
+
async function runRegister(args) {
|
|
135
203
|
const client = await registerClient({
|
|
136
204
|
incortaUrl: args.url,
|
|
137
205
|
tenant: args.tenant,
|
|
@@ -141,7 +209,7 @@ async function main() {
|
|
|
141
209
|
});
|
|
142
210
|
if (args.json) {
|
|
143
211
|
console.log(JSON.stringify(client, null, 2));
|
|
144
|
-
return
|
|
212
|
+
return;
|
|
145
213
|
}
|
|
146
214
|
const authSecret = randomBytes(32).toString("base64url");
|
|
147
215
|
console.log(`Client registered successfully.
|
|
@@ -156,10 +224,84 @@ async function main() {
|
|
|
156
224
|
if (client.registrationAccessToken) {
|
|
157
225
|
console.log(
|
|
158
226
|
`
|
|
159
|
-
# Keep
|
|
227
|
+
# Keep this token \u2014 it manages the registration later (incorta-auth show / update-redirects):`
|
|
160
228
|
);
|
|
161
229
|
console.log(`# registration_access_token: ${client.registrationAccessToken}`);
|
|
162
230
|
}
|
|
231
|
+
}
|
|
232
|
+
async function runShow(args) {
|
|
233
|
+
const info = await getClient({
|
|
234
|
+
incortaUrl: args.url,
|
|
235
|
+
tenant: args.tenant,
|
|
236
|
+
clientId: args.client,
|
|
237
|
+
registrationAccessToken: args.rat
|
|
238
|
+
});
|
|
239
|
+
if (args.json) {
|
|
240
|
+
console.log(JSON.stringify(info, null, 2));
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
console.log(`Client: ${info.clientId}`);
|
|
244
|
+
if (info.name) console.log(`Name: ${info.name}`);
|
|
245
|
+
if (info.scope) console.log(`Scope: ${info.scope}`);
|
|
246
|
+
console.log(`Grant types: ${info.grantTypes.join(", ")}`);
|
|
247
|
+
console.log(`Redirect URIs:`);
|
|
248
|
+
for (const uri of info.redirectUris) console.log(` - ${uri}`);
|
|
249
|
+
}
|
|
250
|
+
async function runUpdateRedirects(args) {
|
|
251
|
+
const info = await updateClientRedirectUris({
|
|
252
|
+
incortaUrl: args.url,
|
|
253
|
+
tenant: args.tenant,
|
|
254
|
+
clientId: args.client,
|
|
255
|
+
registrationAccessToken: args.rat,
|
|
256
|
+
redirectUris: args.redirects,
|
|
257
|
+
mode: args.replace ? "replace" : "add"
|
|
258
|
+
});
|
|
259
|
+
if (args.json) {
|
|
260
|
+
console.log(JSON.stringify(info, null, 2));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
console.log(`Redirect URIs ${args.replace ? "replaced" : "updated"}. Current set:`);
|
|
264
|
+
for (const uri of info.redirectUris) console.log(` - ${uri}`);
|
|
265
|
+
}
|
|
266
|
+
var COMMANDS = {
|
|
267
|
+
register: { required: ["url", "tenant", "name"], needsRedirect: true, run: runRegister },
|
|
268
|
+
show: { required: ["url", "tenant", "client", "rat"], needsRedirect: false, run: runShow },
|
|
269
|
+
"update-redirects": {
|
|
270
|
+
required: ["url", "tenant", "client", "rat"],
|
|
271
|
+
needsRedirect: true,
|
|
272
|
+
run: runUpdateRedirects
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
async function main() {
|
|
276
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
277
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
278
|
+
console.log(HELP);
|
|
279
|
+
return command ? 0 : 1;
|
|
280
|
+
}
|
|
281
|
+
const spec = COMMANDS[command];
|
|
282
|
+
if (!spec) {
|
|
283
|
+
console.error(`Unknown command: ${command}
|
|
284
|
+
`);
|
|
285
|
+
console.log(HELP);
|
|
286
|
+
return 1;
|
|
287
|
+
}
|
|
288
|
+
let args;
|
|
289
|
+
try {
|
|
290
|
+
args = parseArgs(rest);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error(`${error.message}
|
|
293
|
+
`);
|
|
294
|
+
console.log(HELP);
|
|
295
|
+
return 1;
|
|
296
|
+
}
|
|
297
|
+
const missing = requireFlags(args, spec.required, spec.needsRedirect);
|
|
298
|
+
if (missing.length) {
|
|
299
|
+
console.error(`Missing required flag(s): ${missing.join(", ")}
|
|
300
|
+
`);
|
|
301
|
+
console.log(HELP);
|
|
302
|
+
return 1;
|
|
303
|
+
}
|
|
304
|
+
await spec.run(args);
|
|
163
305
|
return 0;
|
|
164
306
|
}
|
|
165
307
|
main().then((code) => {
|
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,9 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
IncortaAuthError: () => IncortaAuthError,
|
|
24
24
|
createIncortaAuth: () => createIncortaAuth,
|
|
25
|
-
|
|
25
|
+
getClient: () => getClient,
|
|
26
|
+
registerClient: () => registerClient,
|
|
27
|
+
updateClientRedirectUris: () => updateClientRedirectUris
|
|
26
28
|
});
|
|
27
29
|
module.exports = __toCommonJS(src_exports);
|
|
28
30
|
|
|
@@ -581,6 +583,26 @@ function createHandler(config) {
|
|
|
581
583
|
}
|
|
582
584
|
|
|
583
585
|
// src/core/register.ts
|
|
586
|
+
function registrationEndpoint(incortaUrl, tenant, clientId) {
|
|
587
|
+
const base = `${incortaUrl.replace(/\/+$/, "")}/oauth/${tenant}/register`;
|
|
588
|
+
return clientId ? `${base}/${clientId}` : base;
|
|
589
|
+
}
|
|
590
|
+
async function readJson(response, what) {
|
|
591
|
+
let body;
|
|
592
|
+
try {
|
|
593
|
+
body = await response.json();
|
|
594
|
+
} catch {
|
|
595
|
+
throw new Error(
|
|
596
|
+
`[incorta-auth] ${what} returned a non-JSON response (HTTP ${response.status}). Is the OAuth authorization server enabled on this cluster?`
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
if (!response.ok) {
|
|
600
|
+
throw new Error(
|
|
601
|
+
`[incorta-auth] ${what} failed (HTTP ${response.status}): ${body.error ?? "unknown_error"} \u2014 ${body.error_description ?? "no description"}`
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
return body;
|
|
605
|
+
}
|
|
584
606
|
async function registerClient(options) {
|
|
585
607
|
const {
|
|
586
608
|
incortaUrl,
|
|
@@ -594,8 +616,7 @@ async function registerClient(options) {
|
|
|
594
616
|
if (!redirectUris.length) {
|
|
595
617
|
throw new Error("[incorta-auth] registerClient requires at least one redirect URI.");
|
|
596
618
|
}
|
|
597
|
-
const
|
|
598
|
-
const response = await fetchImpl(endpoint, {
|
|
619
|
+
const response = await fetchImpl(registrationEndpoint(incortaUrl, tenant), {
|
|
599
620
|
method: "POST",
|
|
600
621
|
headers: { "content-type": "application/json", accept: "application/json" },
|
|
601
622
|
body: JSON.stringify({
|
|
@@ -606,17 +627,10 @@ async function registerClient(options) {
|
|
|
606
627
|
token_endpoint_auth_method: "client_secret_basic"
|
|
607
628
|
})
|
|
608
629
|
});
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
body = await response.json();
|
|
612
|
-
} catch {
|
|
630
|
+
const body = await readJson(response, "Client registration");
|
|
631
|
+
if (!body.client_id || !body.client_secret) {
|
|
613
632
|
throw new Error(
|
|
614
|
-
`[incorta-auth] Client registration
|
|
615
|
-
);
|
|
616
|
-
}
|
|
617
|
-
if (!response.ok || !body.client_id || !body.client_secret) {
|
|
618
|
-
throw new Error(
|
|
619
|
-
`[incorta-auth] Client registration failed (HTTP ${response.status}): ${body.error ?? "unknown_error"} \u2014 ${body.error_description ?? "no description"}`
|
|
633
|
+
`[incorta-auth] Client registration failed: response is missing client_id/client_secret.`
|
|
620
634
|
);
|
|
621
635
|
}
|
|
622
636
|
return {
|
|
@@ -626,6 +640,63 @@ async function registerClient(options) {
|
|
|
626
640
|
registrationClientUri: body.registration_client_uri
|
|
627
641
|
};
|
|
628
642
|
}
|
|
643
|
+
function toClientInfo(body, fallbackClientId) {
|
|
644
|
+
return {
|
|
645
|
+
clientId: body.client_id ?? fallbackClientId,
|
|
646
|
+
name: body.client_name,
|
|
647
|
+
redirectUris: body.redirect_uris ?? [],
|
|
648
|
+
grantTypes: body.grant_types ?? [],
|
|
649
|
+
scope: body.scope
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
async function getClient(options) {
|
|
653
|
+
const { incortaUrl, tenant, clientId, registrationAccessToken, fetchImpl = fetch } = options;
|
|
654
|
+
const response = await fetchImpl(registrationEndpoint(incortaUrl, tenant, clientId), {
|
|
655
|
+
headers: {
|
|
656
|
+
accept: "application/json",
|
|
657
|
+
authorization: `Bearer ${registrationAccessToken}`
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
const body = await readJson(response, "Reading the client");
|
|
661
|
+
return toClientInfo(body, clientId);
|
|
662
|
+
}
|
|
663
|
+
async function updateClientRedirectUris(options) {
|
|
664
|
+
const {
|
|
665
|
+
incortaUrl,
|
|
666
|
+
tenant,
|
|
667
|
+
clientId,
|
|
668
|
+
registrationAccessToken,
|
|
669
|
+
redirectUris,
|
|
670
|
+
mode = "add",
|
|
671
|
+
fetchImpl = fetch
|
|
672
|
+
} = options;
|
|
673
|
+
if (!redirectUris.length) {
|
|
674
|
+
throw new Error("[incorta-auth] updateClientRedirectUris requires at least one redirect URI.");
|
|
675
|
+
}
|
|
676
|
+
const current = await getClient(options);
|
|
677
|
+
const nextUris = mode === "add" ? [.../* @__PURE__ */ new Set([...current.redirectUris, ...redirectUris])] : redirectUris;
|
|
678
|
+
const response = await fetchImpl(registrationEndpoint(incortaUrl, tenant, clientId), {
|
|
679
|
+
method: "PUT",
|
|
680
|
+
headers: {
|
|
681
|
+
"content-type": "application/json",
|
|
682
|
+
accept: "application/json",
|
|
683
|
+
authorization: `Bearer ${registrationAccessToken}`
|
|
684
|
+
},
|
|
685
|
+
// RFC 7592 update: client_id + full metadata. Incorta applies
|
|
686
|
+
// redirect_uris only, but nimbus-side parsing wants the full shape.
|
|
687
|
+
body: JSON.stringify({
|
|
688
|
+
client_id: clientId,
|
|
689
|
+
redirect_uris: nextUris,
|
|
690
|
+
grant_types: current.grantTypes,
|
|
691
|
+
scope: current.scope,
|
|
692
|
+
client_name: current.name
|
|
693
|
+
})
|
|
694
|
+
});
|
|
695
|
+
if (!response.ok) {
|
|
696
|
+
await readJson(response, "Updating the client");
|
|
697
|
+
}
|
|
698
|
+
return getClient(options);
|
|
699
|
+
}
|
|
629
700
|
|
|
630
701
|
// src/index.ts
|
|
631
702
|
function createIncortaAuth(config = {}) {
|
|
@@ -637,6 +708,8 @@ function createIncortaAuth(config = {}) {
|
|
|
637
708
|
0 && (module.exports = {
|
|
638
709
|
IncortaAuthError,
|
|
639
710
|
createIncortaAuth,
|
|
640
|
-
|
|
711
|
+
getClient,
|
|
712
|
+
registerClient,
|
|
713
|
+
updateClientRedirectUris
|
|
641
714
|
});
|
|
642
715
|
//# sourceMappingURL=index.cjs.map
|