@ory/argus 0.13.6 → 0.13.7
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/dist/agent-auth.d.ts +8 -0
- package/dist/agent-auth.js +33 -5
- package/dist/build-info.json +4 -4
- package/dist/interactive-setup.js +47 -4
- package/package.json +1 -1
package/dist/agent-auth.d.ts
CHANGED
|
@@ -48,6 +48,14 @@ export interface AgentCredentials {
|
|
|
48
48
|
* via deprecated alias). Never blocks resolution.
|
|
49
49
|
*/
|
|
50
50
|
warnings: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Set on a `kind: "none"` result when the token endpoint rejected the
|
|
53
|
+
* credentials for an auth reason (401/403) — i.e. the client is genuinely
|
|
54
|
+
* dead (revoked/invalid). A transient failure (network, rate-limit, 5xx)
|
|
55
|
+
* leaves this false so callers don't discard otherwise-good persisted
|
|
56
|
+
* credentials. See the persisted-DCR branch in {@link resolveAgentCredentials}.
|
|
57
|
+
*/
|
|
58
|
+
authRejected?: boolean;
|
|
51
59
|
}
|
|
52
60
|
export interface ResolveAgentCredentialsOptions {
|
|
53
61
|
/** Ory project URL — required for client_credentials grant + DCR. */
|
package/dist/agent-auth.js
CHANGED
|
@@ -275,10 +275,20 @@ async function resolveAgentCredentials(options = {}) {
|
|
|
275
275
|
});
|
|
276
276
|
if (result.kind !== "none")
|
|
277
277
|
return result;
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
278
|
+
// Only a genuine auth rejection (401/403 — client revoked/invalid) means
|
|
279
|
+
// the persisted creds are dead. Clear them and fall through to a fresh
|
|
280
|
+
// registration. A transient failure (network, rate-limit, 5xx) must NOT
|
|
281
|
+
// discard good creds: doing so would orphan the server-side client
|
|
282
|
+
// (clearDynamicFn never revokes it) and register a brand-new one on every
|
|
283
|
+
// blip. Keep the persisted creds and report the transient failure instead.
|
|
284
|
+
if (result.authRejected) {
|
|
285
|
+
warnings.push(`Persisted dynamic agent credentials rejected (${result.reason}); re-registering.`);
|
|
286
|
+
clearDynamicFn();
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
warnings.push(`Persisted dynamic agent credentials temporarily unavailable (${result.reason}); keeping them for the next session.`);
|
|
290
|
+
return { ...result, warnings };
|
|
291
|
+
}
|
|
282
292
|
}
|
|
283
293
|
}
|
|
284
294
|
// 4. Fresh dynamic registration — bootstrap using the user's bearer
|
|
@@ -377,11 +387,27 @@ async function resolveClientCredentials(args) {
|
|
|
377
387
|
catch (err) {
|
|
378
388
|
return {
|
|
379
389
|
kind: "none",
|
|
390
|
+
authRejected: isAuthRejectionError(err),
|
|
380
391
|
reason: `${reasonNoun} client_credentials grant failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
381
392
|
warnings: args.warnings,
|
|
382
393
|
};
|
|
383
394
|
}
|
|
384
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Whether a token-grant error is an auth rejection (401/403) — meaning the
|
|
398
|
+
* credentials themselves are dead — as opposed to a transient failure
|
|
399
|
+
* (network, rate-limit, 5xx). Reads a `status` property when the thrower
|
|
400
|
+
* attaches one ({@link fetchClientCredentialsToken} does), and falls back to
|
|
401
|
+
* matching `HTTP 401`/`HTTP 403` in the message so injected/stubbed grant
|
|
402
|
+
* functions that throw a plain `Error` are classified correctly too.
|
|
403
|
+
*/
|
|
404
|
+
function isAuthRejectionError(err) {
|
|
405
|
+
const status = err?.status;
|
|
406
|
+
if (status === 401 || status === 403)
|
|
407
|
+
return true;
|
|
408
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
409
|
+
return /\bHTTP 40[13]\b/.test(msg);
|
|
410
|
+
}
|
|
385
411
|
// Kept as raw fetch (rather than @ory/client's OAuth2Api.oauth2TokenExchange)
|
|
386
412
|
// because the SDK method's signature does not expose client_secret, audience,
|
|
387
413
|
// or scope — all of which this grant needs. Ory's own SDK docstring on that
|
|
@@ -404,7 +430,9 @@ async function fetchClientCredentialsToken(args) {
|
|
|
404
430
|
body: body.toString(),
|
|
405
431
|
});
|
|
406
432
|
if (!res.ok) {
|
|
407
|
-
|
|
433
|
+
const err = new Error(`HTTP ${res.status}`);
|
|
434
|
+
err.status = res.status;
|
|
435
|
+
throw err;
|
|
408
436
|
}
|
|
409
437
|
const json = (await res.json());
|
|
410
438
|
const accessToken = typeof json.access_token === "string" ? json.access_token : "";
|
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"repo": "ory-agent-plugins",
|
|
3
|
-
"commit": "
|
|
4
|
-
"commitShort": "
|
|
3
|
+
"commit": "badfe6ff1166227b0eefaeb54018482631e0ce7b",
|
|
4
|
+
"commitShort": "badfe6f",
|
|
5
5
|
"branch": "main",
|
|
6
|
-
"commitDate": "2026-07-
|
|
6
|
+
"commitDate": "2026-07-15T11:49:39-07:00",
|
|
7
7
|
"dirty": false,
|
|
8
|
-
"builtAt": "2026-07-
|
|
8
|
+
"builtAt": "2026-07-15T18:53:45.680Z"
|
|
9
9
|
}
|
|
@@ -568,10 +568,20 @@ async function configureNetwork(binName, harness, ctx) {
|
|
|
568
568
|
// self-register at runtime. Ory Network projects ship with DCR disabled,
|
|
569
569
|
// so without this the default agent-identity path would never resolve.
|
|
570
570
|
await maybeEnableDcr(runner, prompt, project.id);
|
|
571
|
-
// 6.
|
|
571
|
+
// 6. Provision the public OAuth2 client for the PKCE user login. Reuse an
|
|
572
|
+
// existing one on this project first — a re-run (`install --reconfigure`)
|
|
573
|
+
// against the same project must not mint a duplicate public client and
|
|
574
|
+
// orphan the old one (the CLI-created client is never cleaned up by
|
|
575
|
+
// uninstall). Only create when no prior client is found.
|
|
572
576
|
ui.heading("OAuth2 client");
|
|
573
|
-
|
|
574
|
-
|
|
577
|
+
let clientId = findExistingOAuth2Client(runner, project.id);
|
|
578
|
+
if (clientId) {
|
|
579
|
+
ui.step(`Reusing the existing OAuth2 client for user login (${clientId}).`);
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
ui.step("Creating the OAuth2 client for user login...");
|
|
583
|
+
clientId = createOAuth2Client(runner, project.id);
|
|
584
|
+
}
|
|
575
585
|
if (!clientId) {
|
|
576
586
|
ui.warning("Could not create the OAuth2 client automatically.");
|
|
577
587
|
ui.warnDetail(`Project URL resolved: ${projectUrl}`);
|
|
@@ -604,6 +614,14 @@ async function configureNetwork(binName, harness, ctx) {
|
|
|
604
614
|
// runtime agent/user tokens can't write relation tuples on a hosted
|
|
605
615
|
// project (that's a project-admin operation), but the `ory` session can.
|
|
606
616
|
if (subject) {
|
|
617
|
+
// Persist the subject *shape* this grant used. If the install resolved a
|
|
618
|
+
// SubjectSet (ORY_USER_SUBJECT_NAMESPACE was set), a later runtime session
|
|
619
|
+
// that lacks the env var would otherwise resolve a direct subject_id and
|
|
620
|
+
// check/write a divergent tuple for the same user. Persisting the namespace
|
|
621
|
+
// keeps install-time and runtime writes on one canonical subject shape.
|
|
622
|
+
if ("subjectSet" in subject) {
|
|
623
|
+
(0, config_js_1.saveConfig)({ userSubjectNamespace: subject.subjectSet.namespace });
|
|
624
|
+
}
|
|
607
625
|
await bootstrapPermissionsViaOry(runner, project.id, harness, subject, prompt);
|
|
608
626
|
}
|
|
609
627
|
// 10. Provision the project API key runtime permission *checks* need. Same
|
|
@@ -1166,6 +1184,31 @@ async function maybeEnableDcr(runner, prompt, projectId) {
|
|
|
1166
1184
|
ui.warnDetail(`Enable it later with: ${manual}`);
|
|
1167
1185
|
}
|
|
1168
1186
|
}
|
|
1187
|
+
/** The `client_name` every plugin-provisioned public PKCE client carries. */
|
|
1188
|
+
const OAUTH2_CLIENT_NAME = "ory-agent-plugin";
|
|
1189
|
+
/**
|
|
1190
|
+
* Look for an already-provisioned public PKCE client on the project so a
|
|
1191
|
+
* re-run reuses it instead of minting a duplicate. Matches by the fixed
|
|
1192
|
+
* `client_name` {@link createOAuth2Client} assigns. Best-effort: any CLI or
|
|
1193
|
+
* parse failure returns null and the caller falls back to creating one.
|
|
1194
|
+
*/
|
|
1195
|
+
function findExistingOAuth2Client(runner, projectId) {
|
|
1196
|
+
const r = runner.exec([
|
|
1197
|
+
"list",
|
|
1198
|
+
"oauth2-clients",
|
|
1199
|
+
"--project",
|
|
1200
|
+
projectId,
|
|
1201
|
+
"--format",
|
|
1202
|
+
"json",
|
|
1203
|
+
]);
|
|
1204
|
+
if (r.status !== 0)
|
|
1205
|
+
return null;
|
|
1206
|
+
const clients = parseList(r.stdout, "items");
|
|
1207
|
+
if (!clients)
|
|
1208
|
+
return null;
|
|
1209
|
+
const match = clients.find((c) => c.client_name === OAUTH2_CLIENT_NAME && c.client_id);
|
|
1210
|
+
return match?.client_id ?? null;
|
|
1211
|
+
}
|
|
1169
1212
|
function createOAuth2Client(runner, projectId) {
|
|
1170
1213
|
const args = [
|
|
1171
1214
|
"create",
|
|
@@ -1173,7 +1216,7 @@ function createOAuth2Client(runner, projectId) {
|
|
|
1173
1216
|
"--project",
|
|
1174
1217
|
projectId,
|
|
1175
1218
|
"--name",
|
|
1176
|
-
|
|
1219
|
+
OAUTH2_CLIENT_NAME,
|
|
1177
1220
|
"--grant-type",
|
|
1178
1221
|
"authorization_code,refresh_token",
|
|
1179
1222
|
"--response-type",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/argus",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.7",
|
|
4
4
|
"description": "Ory Argus: the core API for building authentication, authorization, and audit into AI agent harness plugins, extensions, and custom integrations",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://ory.com",
|