@canopy-io/node 0.5.0 → 0.7.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/CHANGELOG.md +35 -0
- package/README.md +13 -4
- package/dist/index.cjs +47 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1116 -363
- package/dist/index.d.ts +1116 -363
- package/dist/index.js +47 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -82,6 +82,15 @@ function isCanopyTokenError(error) {
|
|
|
82
82
|
return error instanceof Error && error.name === "CanopyTokenError";
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
// src/strings.ts
|
|
86
|
+
function withoutTrailingSlashes(value) {
|
|
87
|
+
let end = value.length;
|
|
88
|
+
while (end > 0 && value[end - 1] === "/") {
|
|
89
|
+
end -= 1;
|
|
90
|
+
}
|
|
91
|
+
return value.slice(0, end);
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
// src/client.ts
|
|
86
95
|
function isCursorPagination(pagination) {
|
|
87
96
|
return "next_cursor" in pagination;
|
|
@@ -106,7 +115,7 @@ var CanopyClient = class {
|
|
|
106
115
|
"CanopyClient requires either `apiKey` (server-to-server) or `accessToken` (a user or identity JWT)."
|
|
107
116
|
);
|
|
108
117
|
}
|
|
109
|
-
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL)
|
|
118
|
+
this.baseUrl = withoutTrailingSlashes(options.baseUrl ?? DEFAULT_BASE_URL);
|
|
110
119
|
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
111
120
|
this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
112
121
|
this.maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
|
|
@@ -550,29 +559,19 @@ var Identities = class {
|
|
|
550
559
|
{ body: input }
|
|
551
560
|
);
|
|
552
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Takes the identity out of this key's Environment: its membership here is
|
|
564
|
+
* deactivated and its role assignments here are dropped. The identity and
|
|
565
|
+
* its access to other Environments are untouched. Deactivating an identity
|
|
566
|
+
* everywhere is an Account-level action, not available to an
|
|
567
|
+
* Environment-scoped key.
|
|
568
|
+
*/
|
|
553
569
|
delete(id) {
|
|
554
570
|
return this.client.request(
|
|
555
571
|
"DELETE",
|
|
556
572
|
`/api/v1/identities/${encodeURIComponent(id)}`
|
|
557
573
|
);
|
|
558
574
|
}
|
|
559
|
-
/**
|
|
560
|
-
* Deactivation is the reversible counterpart to `delete` — sessions are
|
|
561
|
-
* revoked and sign-in refused, but the identity and its assignments survive.
|
|
562
|
-
* Prefer it for offboarding you may need to undo.
|
|
563
|
-
*/
|
|
564
|
-
deactivate(id) {
|
|
565
|
-
return this.client.request(
|
|
566
|
-
"POST",
|
|
567
|
-
`/api/v1/identities/${encodeURIComponent(id)}/deactivate`
|
|
568
|
-
);
|
|
569
|
-
}
|
|
570
|
-
activate(id) {
|
|
571
|
-
return this.client.request(
|
|
572
|
-
"POST",
|
|
573
|
-
`/api/v1/identities/${encodeURIComponent(id)}/activate`
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
575
|
/**
|
|
577
576
|
* Every role this identity holds, and where — across all pages.
|
|
578
577
|
*
|
|
@@ -634,7 +633,7 @@ var Identities = class {
|
|
|
634
633
|
* Ends every session the identity holds, so the next refresh on any device
|
|
635
634
|
* fails and the person signs in again. Access tokens already issued keep
|
|
636
635
|
* working until their short lifetime runs out. For a suspected compromise;
|
|
637
|
-
* `
|
|
636
|
+
* `delete` also takes the identity out of this Environment.
|
|
638
637
|
*/
|
|
639
638
|
revokeSessions(id) {
|
|
640
639
|
return this.client.request(
|
|
@@ -1117,6 +1116,7 @@ var Canopy = class {
|
|
|
1117
1116
|
|
|
1118
1117
|
// src/authorizer.ts
|
|
1119
1118
|
var DEFAULT_TTL_MS = 6e4;
|
|
1119
|
+
var MAX_TTL_MS = 3e5;
|
|
1120
1120
|
var MAX_WALK_DEPTH = 256;
|
|
1121
1121
|
var LocalAuthorizer = class {
|
|
1122
1122
|
client;
|
|
@@ -1143,6 +1143,11 @@ var LocalAuthorizer = class {
|
|
|
1143
1143
|
constructor(client, options = {}) {
|
|
1144
1144
|
this.client = client;
|
|
1145
1145
|
this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
1146
|
+
if (!Number.isFinite(this.ttlMs) || this.ttlMs < 0 || this.ttlMs > MAX_TTL_MS) {
|
|
1147
|
+
throw new RangeError(
|
|
1148
|
+
`ttlMs must be between 0 and ${MAX_TTL_MS} (five minutes); got ${String(this.ttlMs)}. It is how long a revoked user keeps access, so it is capped.`
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1146
1151
|
this.now = options.now ?? (() => Date.now());
|
|
1147
1152
|
this.readOptions = {
|
|
1148
1153
|
...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
|
|
@@ -1210,7 +1215,9 @@ var LocalAuthorizer = class {
|
|
|
1210
1215
|
* With no argument, everything goes: grants and the hierarchy tree. Not
|
|
1211
1216
|
* needed in normal operation, where entries expire on their own; useful in
|
|
1212
1217
|
* tests and after a change whose reach you cannot name (a role's
|
|
1213
|
-
* permissions edited, a node moved).
|
|
1218
|
+
* permissions edited, a role deactivated or reactivated, a node moved). A
|
|
1219
|
+
* deactivated role grants nothing to anyone holding it, so until the cache
|
|
1220
|
+
* is cleared or expires, its holders keep being allowed locally.
|
|
1214
1221
|
*
|
|
1215
1222
|
* Multi-instance honesty: an invalidation reaches THIS process only. A
|
|
1216
1223
|
* webhook lands on one instance behind a load balancer; the others serve
|
|
@@ -1330,12 +1337,29 @@ var LocalAuthorizer = class {
|
|
|
1330
1337
|
};
|
|
1331
1338
|
|
|
1332
1339
|
// src/verify.ts
|
|
1333
|
-
var
|
|
1340
|
+
var HOSTED_ORIGIN = "https://auth.canopy-io.com";
|
|
1334
1341
|
var DEFAULT_JWKS_CACHE_MAX_AGE_MS = 10 * 60 * 1e3;
|
|
1335
1342
|
var DEFAULT_JWKS_MIN_REFETCH_INTERVAL_MS = 30 * 1e3;
|
|
1336
1343
|
var DEFAULT_JWKS_TIMEOUT_MS = 5e3;
|
|
1337
1344
|
var PRINCIPAL_TYPES = /* @__PURE__ */ new Set(["user", "identity", "api_key", "platform"]);
|
|
1338
1345
|
var DEFAULT_CLOCK_TOLERANCE_SEC = 60;
|
|
1346
|
+
function resolveIssuer(options) {
|
|
1347
|
+
const { environmentId, issuer } = options;
|
|
1348
|
+
if (environmentId && issuer) {
|
|
1349
|
+
throw new TypeError(
|
|
1350
|
+
"TokenVerifier takes environmentId or issuer, not both."
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
if (issuer) {
|
|
1354
|
+
return withoutTrailingSlashes(issuer);
|
|
1355
|
+
}
|
|
1356
|
+
if (environmentId) {
|
|
1357
|
+
return `${HOSTED_ORIGIN}/environments/${environmentId}`;
|
|
1358
|
+
}
|
|
1359
|
+
throw new TypeError(
|
|
1360
|
+
"TokenVerifier needs environmentId (the Environment your tokens come from) or, on a custom auth domain or self-hosted instance, issuer."
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1339
1363
|
function orgContext(claims) {
|
|
1340
1364
|
const { org_id, org_role } = claims;
|
|
1341
1365
|
if (typeof org_id !== "string" || org_id === "" || typeof org_role !== "string" || org_role === "") {
|
|
@@ -1380,7 +1404,7 @@ var TokenVerifier = class {
|
|
|
1380
1404
|
/** In-flight fetch, so a burst of requests triggers one call, not N. */
|
|
1381
1405
|
inFlight = null;
|
|
1382
1406
|
constructor(options = {}) {
|
|
1383
|
-
this.issuer = (options
|
|
1407
|
+
this.issuer = resolveIssuer(options);
|
|
1384
1408
|
this.audience = options.audience;
|
|
1385
1409
|
this.jwksUri = options.jwksUri ?? `${this.issuer}/.well-known/jwks.json`;
|
|
1386
1410
|
this.jwksCacheMaxAgeMs = options.jwksCacheMaxAgeMs ?? DEFAULT_JWKS_CACHE_MAX_AGE_MS;
|
|
@@ -1658,6 +1682,6 @@ function isWebhookEvent(delivery, name) {
|
|
|
1658
1682
|
return delivery.event === name;
|
|
1659
1683
|
}
|
|
1660
1684
|
|
|
1661
|
-
export { Assignments, Canopy, CanopyAuthorizerError, CanopyClient, CanopyConnectionError, CanopyError, CanopyTokenError, Identities, LocalAuthorizer, Organizations, Paginator, Permissions, Roles, TokenVerifier, isCanopyAuthorizerError, isCanopyConnectionError, isCanopyError, isCanopyTokenError, isCursorPagination, isWebhookEvent, orgContext, paginate, withConcurrency };
|
|
1685
|
+
export { Assignments, Canopy, CanopyAuthorizerError, CanopyClient, CanopyConnectionError, CanopyError, CanopyTokenError, Identities, LocalAuthorizer, MAX_TTL_MS, Organizations, Paginator, Permissions, Roles, TokenVerifier, isCanopyAuthorizerError, isCanopyConnectionError, isCanopyError, isCanopyTokenError, isCursorPagination, isWebhookEvent, orgContext, paginate, withConcurrency };
|
|
1662
1686
|
//# sourceMappingURL=index.js.map
|
|
1663
1687
|
//# sourceMappingURL=index.js.map
|