@canopy-io/node 0.6.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/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).replace(/\/+$/, "");
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;
@@ -1107,6 +1116,7 @@ var Canopy = class {
1107
1116
 
1108
1117
  // src/authorizer.ts
1109
1118
  var DEFAULT_TTL_MS = 6e4;
1119
+ var MAX_TTL_MS = 3e5;
1110
1120
  var MAX_WALK_DEPTH = 256;
1111
1121
  var LocalAuthorizer = class {
1112
1122
  client;
@@ -1133,6 +1143,11 @@ var LocalAuthorizer = class {
1133
1143
  constructor(client, options = {}) {
1134
1144
  this.client = client;
1135
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
+ }
1136
1151
  this.now = options.now ?? (() => Date.now());
1137
1152
  this.readOptions = {
1138
1153
  ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
@@ -1322,12 +1337,29 @@ var LocalAuthorizer = class {
1322
1337
  };
1323
1338
 
1324
1339
  // src/verify.ts
1325
- var DEFAULT_ISSUER = "https://auth.canopy-io.com";
1340
+ var HOSTED_ORIGIN = "https://auth.canopy-io.com";
1326
1341
  var DEFAULT_JWKS_CACHE_MAX_AGE_MS = 10 * 60 * 1e3;
1327
1342
  var DEFAULT_JWKS_MIN_REFETCH_INTERVAL_MS = 30 * 1e3;
1328
1343
  var DEFAULT_JWKS_TIMEOUT_MS = 5e3;
1329
1344
  var PRINCIPAL_TYPES = /* @__PURE__ */ new Set(["user", "identity", "api_key", "platform"]);
1330
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
+ }
1331
1363
  function orgContext(claims) {
1332
1364
  const { org_id, org_role } = claims;
1333
1365
  if (typeof org_id !== "string" || org_id === "" || typeof org_role !== "string" || org_role === "") {
@@ -1372,7 +1404,7 @@ var TokenVerifier = class {
1372
1404
  /** In-flight fetch, so a burst of requests triggers one call, not N. */
1373
1405
  inFlight = null;
1374
1406
  constructor(options = {}) {
1375
- this.issuer = (options.issuer ?? DEFAULT_ISSUER).replace(/\/+$/, "");
1407
+ this.issuer = resolveIssuer(options);
1376
1408
  this.audience = options.audience;
1377
1409
  this.jwksUri = options.jwksUri ?? `${this.issuer}/.well-known/jwks.json`;
1378
1410
  this.jwksCacheMaxAgeMs = options.jwksCacheMaxAgeMs ?? DEFAULT_JWKS_CACHE_MAX_AGE_MS;
@@ -1650,6 +1682,6 @@ function isWebhookEvent(delivery, name) {
1650
1682
  return delivery.event === name;
1651
1683
  }
1652
1684
 
1653
- 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 };
1654
1686
  //# sourceMappingURL=index.js.map
1655
1687
  //# sourceMappingURL=index.js.map