@auth0/ai 1.0.2 → 2.0.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.
Files changed (137) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/authorizers/ciba/CIBAAuthorizerBase.js +81 -55
  3. package/dist/cjs/authorizers/ciba/CIBAAuthorizerBase.js.map +1 -1
  4. package/dist/cjs/authorizers/ciba/CIBAAuthorizerParams.js.map +1 -1
  5. package/dist/cjs/authorizers/ciba/asyncLocalStorage.js +1 -1
  6. package/dist/cjs/authorizers/ciba/asyncLocalStorage.js.map +1 -1
  7. package/dist/cjs/authorizers/context.js +20 -0
  8. package/dist/cjs/authorizers/context.js.map +1 -0
  9. package/dist/cjs/authorizers/device-authorizer/DeviceAuthResponse.js +18 -0
  10. package/dist/cjs/authorizers/device-authorizer/DeviceAuthResponse.js.map +1 -0
  11. package/dist/cjs/authorizers/device-authorizer/DeviceAuthorizerBase.js +231 -0
  12. package/dist/cjs/authorizers/device-authorizer/DeviceAuthorizerBase.js.map +1 -0
  13. package/dist/cjs/{TokenResponse.js → authorizers/device-authorizer/DeviceAuthorizerParams.js} +1 -1
  14. package/dist/cjs/authorizers/device-authorizer/DeviceAuthorizerParams.js.map +1 -0
  15. package/dist/cjs/authorizers/device-authorizer/asyncLocalStorage.js +14 -0
  16. package/dist/cjs/authorizers/device-authorizer/asyncLocalStorage.js.map +1 -0
  17. package/dist/cjs/authorizers/device-authorizer/index.js +9 -0
  18. package/dist/cjs/authorizers/device-authorizer/index.js.map +1 -0
  19. package/dist/cjs/authorizers/federated-connections/FederatedConnectionAuthorizerBase.js +158 -0
  20. package/dist/cjs/authorizers/federated-connections/FederatedConnectionAuthorizerBase.js.map +1 -0
  21. package/dist/cjs/authorizers/federated-connections/FederatedConnectionAuthorizerParams.js +3 -0
  22. package/dist/cjs/authorizers/federated-connections/FederatedConnectionAuthorizerParams.js.map +1 -0
  23. package/dist/cjs/authorizers/federated-connections/asyncLocalStorage.js +5 -5
  24. package/dist/cjs/authorizers/federated-connections/asyncLocalStorage.js.map +1 -1
  25. package/dist/cjs/authorizers/federated-connections/index.js +5 -125
  26. package/dist/cjs/authorizers/federated-connections/index.js.map +1 -1
  27. package/dist/cjs/authorizers/index.js.map +1 -1
  28. package/dist/cjs/authorizers/types.js +14 -0
  29. package/dist/cjs/authorizers/types.js.map +1 -0
  30. package/dist/cjs/credentials.js +13 -0
  31. package/dist/cjs/credentials.js.map +1 -1
  32. package/dist/cjs/index.js +0 -1
  33. package/dist/cjs/index.js.map +1 -1
  34. package/dist/cjs/interrupts/DeviceInterrupts.js +79 -0
  35. package/dist/cjs/interrupts/DeviceInterrupts.js.map +1 -0
  36. package/dist/cjs/interrupts/index.js +37 -1
  37. package/dist/cjs/interrupts/index.js.map +1 -1
  38. package/dist/cjs/stores/Store.js +12 -0
  39. package/dist/cjs/stores/Store.js.map +1 -0
  40. package/dist/cjs/stores/SubStore.js +52 -0
  41. package/dist/cjs/stores/SubStore.js.map +1 -0
  42. package/dist/cjs/stores/impl/FSStore.js +80 -0
  43. package/dist/cjs/stores/impl/FSStore.js.map +1 -0
  44. package/dist/cjs/stores/impl/MemoryStore.js +15 -0
  45. package/dist/cjs/stores/impl/MemoryStore.js.map +1 -0
  46. package/dist/cjs/stores/impl/TempBoxStore.js +22 -0
  47. package/dist/cjs/stores/impl/TempBoxStore.js.map +1 -0
  48. package/dist/cjs/stores/index.js +10 -0
  49. package/dist/cjs/stores/index.js.map +1 -0
  50. package/dist/cjs/util/index.js +12 -0
  51. package/dist/cjs/util/index.js.map +1 -0
  52. package/dist/esm/authorizers/ciba/CIBAAuthorizerBase.d.ts +12 -8
  53. package/dist/esm/authorizers/ciba/CIBAAuthorizerBase.js +78 -55
  54. package/dist/esm/authorizers/ciba/CIBAAuthorizerBase.js.map +1 -1
  55. package/dist/esm/authorizers/ciba/CIBAAuthorizerParams.d.ts +20 -20
  56. package/dist/esm/authorizers/ciba/CIBAAuthorizerParams.js.map +1 -1
  57. package/dist/esm/authorizers/ciba/asyncLocalStorage.d.ts +7 -3
  58. package/dist/esm/authorizers/ciba/asyncLocalStorage.js +1 -1
  59. package/dist/esm/authorizers/ciba/asyncLocalStorage.js.map +1 -1
  60. package/dist/esm/authorizers/context.d.ts +16 -0
  61. package/dist/esm/authorizers/context.js +16 -0
  62. package/dist/esm/authorizers/context.js.map +1 -0
  63. package/dist/esm/authorizers/device-authorizer/DeviceAuthResponse.d.ts +38 -0
  64. package/dist/esm/authorizers/device-authorizer/DeviceAuthResponse.js +15 -0
  65. package/dist/esm/authorizers/device-authorizer/DeviceAuthResponse.js.map +1 -0
  66. package/dist/esm/authorizers/device-authorizer/DeviceAuthorizerBase.d.ts +49 -0
  67. package/dist/esm/authorizers/device-authorizer/DeviceAuthorizerBase.js +224 -0
  68. package/dist/esm/authorizers/device-authorizer/DeviceAuthorizerBase.js.map +1 -0
  69. package/dist/esm/authorizers/device-authorizer/DeviceAuthorizerParams.d.ts +58 -0
  70. package/dist/esm/authorizers/device-authorizer/DeviceAuthorizerParams.js +2 -0
  71. package/dist/esm/authorizers/device-authorizer/DeviceAuthorizerParams.js.map +1 -0
  72. package/dist/esm/authorizers/device-authorizer/asyncLocalStorage.d.ts +16 -0
  73. package/dist/esm/authorizers/device-authorizer/asyncLocalStorage.js +10 -0
  74. package/dist/esm/authorizers/device-authorizer/asyncLocalStorage.js.map +1 -0
  75. package/dist/esm/authorizers/device-authorizer/index.d.ts +4 -0
  76. package/dist/esm/authorizers/device-authorizer/index.js +3 -0
  77. package/dist/esm/authorizers/device-authorizer/index.js.map +1 -0
  78. package/dist/esm/authorizers/federated-connections/FederatedConnectionAuthorizerBase.d.ts +30 -0
  79. package/dist/esm/authorizers/federated-connections/FederatedConnectionAuthorizerBase.js +151 -0
  80. package/dist/esm/authorizers/federated-connections/FederatedConnectionAuthorizerBase.js.map +1 -0
  81. package/dist/esm/authorizers/federated-connections/FederatedConnectionAuthorizerParams.d.ts +38 -0
  82. package/dist/esm/authorizers/federated-connections/FederatedConnectionAuthorizerParams.js +2 -0
  83. package/dist/esm/authorizers/federated-connections/FederatedConnectionAuthorizerParams.js.map +1 -0
  84. package/dist/esm/authorizers/federated-connections/asyncLocalStorage.d.ts +7 -5
  85. package/dist/esm/authorizers/federated-connections/asyncLocalStorage.js +3 -3
  86. package/dist/esm/authorizers/federated-connections/asyncLocalStorage.js.map +1 -1
  87. package/dist/esm/authorizers/federated-connections/index.d.ts +3 -36
  88. package/dist/esm/authorizers/federated-connections/index.js +2 -122
  89. package/dist/esm/authorizers/federated-connections/index.js.map +1 -1
  90. package/dist/esm/authorizers/index.d.ts +1 -12
  91. package/dist/esm/authorizers/index.js.map +1 -1
  92. package/dist/esm/authorizers/types.d.ts +37 -0
  93. package/dist/esm/authorizers/types.js +11 -0
  94. package/dist/esm/authorizers/types.js.map +1 -0
  95. package/dist/esm/credentials.d.ts +33 -8
  96. package/dist/esm/credentials.js +11 -1
  97. package/dist/esm/credentials.js.map +1 -1
  98. package/dist/esm/index.d.ts +1 -3
  99. package/dist/esm/index.js +0 -1
  100. package/dist/esm/index.js.map +1 -1
  101. package/dist/esm/interrupts/DeviceInterrupts.d.ts +55 -0
  102. package/dist/esm/interrupts/DeviceInterrupts.js +70 -0
  103. package/dist/esm/interrupts/DeviceInterrupts.js.map +1 -0
  104. package/dist/esm/interrupts/index.d.ts +2 -0
  105. package/dist/esm/interrupts/index.js +2 -0
  106. package/dist/esm/interrupts/index.js.map +1 -1
  107. package/dist/esm/stores/Store.d.ts +40 -0
  108. package/dist/esm/stores/Store.js +11 -0
  109. package/dist/esm/stores/Store.js.map +1 -0
  110. package/dist/esm/stores/SubStore.d.ts +31 -0
  111. package/dist/esm/stores/SubStore.js +48 -0
  112. package/dist/esm/stores/SubStore.js.map +1 -0
  113. package/dist/esm/stores/impl/FSStore.d.ts +19 -0
  114. package/dist/esm/stores/impl/FSStore.js +72 -0
  115. package/dist/esm/stores/impl/FSStore.js.map +1 -0
  116. package/dist/esm/stores/impl/MemoryStore.d.ts +8 -0
  117. package/dist/esm/stores/impl/MemoryStore.js +11 -0
  118. package/dist/esm/stores/impl/MemoryStore.js.map +1 -0
  119. package/dist/esm/stores/impl/TempBoxStore.d.ts +13 -0
  120. package/dist/esm/stores/impl/TempBoxStore.js +18 -0
  121. package/dist/esm/stores/impl/TempBoxStore.js.map +1 -0
  122. package/dist/esm/stores/index.d.ts +5 -0
  123. package/dist/esm/stores/index.js +4 -0
  124. package/dist/esm/stores/index.js.map +1 -0
  125. package/dist/esm/util/index.d.ts +3 -0
  126. package/dist/esm/util/index.js +8 -0
  127. package/dist/esm/util/index.js.map +1 -0
  128. package/package.json +20 -4
  129. package/dist/cjs/TokenResponse.js.map +0 -1
  130. package/dist/cjs/authorizers/device-authorizer.js +0 -130
  131. package/dist/cjs/authorizers/device-authorizer.js.map +0 -1
  132. package/dist/esm/TokenResponse.d.ts +0 -15
  133. package/dist/esm/TokenResponse.js +0 -2
  134. package/dist/esm/TokenResponse.js.map +0 -1
  135. package/dist/esm/authorizers/device-authorizer.d.ts +0 -15
  136. package/dist/esm/authorizers/device-authorizer.js +0 -90
  137. package/dist/esm/authorizers/device-authorizer.js.map +0 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@ This SDK provides base abstractions for authentication and authorization in AI a
7
7
  ## Install
8
8
 
9
9
  > [!WARNING]
10
- > `@auth0/ai` is currently under development and it is not intended to be used in production, and therefore has no official support.
10
+ > `@auth0/ai` is currently **under heavy development**. We strictly follow [Semantic Versioning (SemVer)](https://semver.org/), meaning all **breaking changes will only occur in major versions**. However, please note that during this early phase, **major versions may be released frequently** as the API evolves. We recommend locking versions when using this in production.
11
11
 
12
12
  ```
13
13
  $ npm install @auth0/ai
@@ -1,9 +1,18 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.CIBAAuthorizerBase = void 0;
4
7
  const auth0_1 = require("auth0");
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const stable_hash_1 = __importDefault(require("stable-hash"));
10
+ const credentials_1 = require("../../credentials");
5
11
  const interrupts_1 = require("../../interrupts");
6
12
  const parameters_1 = require("../../parameters");
13
+ const stores_1 = require("../../stores");
14
+ const context_1 = require("../context");
15
+ const types_1 = require("../types");
7
16
  const asyncLocalStorage_1 = require("./asyncLocalStorage");
8
17
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
9
18
  function ensureOpenIdScope(scopes) {
@@ -15,28 +24,28 @@ function ensureOpenIdScope(scopes) {
15
24
  */
16
25
  class CIBAAuthorizerBase {
17
26
  constructor(auth0, params) {
18
- this.params = params;
19
- this.auth0 = new auth0_1.AuthenticationClient({
20
- domain: (auth0 === null || auth0 === void 0 ? void 0 : auth0.domain) || process.env.AUTH0_DOMAIN,
21
- clientId: (auth0 === null || auth0 === void 0 ? void 0 : auth0.clientId) || process.env.AUTH0_CLIENT_ID,
22
- clientSecret: (auth0 === null || auth0 === void 0 ? void 0 : auth0.clientSecret) || process.env.AUTH0_CLIENT_SECRET,
23
- clientAssertionSigningAlg: auth0 === null || auth0 === void 0 ? void 0 : auth0.clientAssertionSigningAlg,
24
- clientAssertionSigningKey: auth0 === null || auth0 === void 0 ? void 0 : auth0.clientAssertionSigningKey,
25
- idTokenSigningAlg: auth0 === null || auth0 === void 0 ? void 0 : auth0.idTokenSigningAlg,
26
- clockTolerance: auth0 === null || auth0 === void 0 ? void 0 : auth0.clockTolerance,
27
- useMTLS: auth0 === null || auth0 === void 0 ? void 0 : auth0.useMTLS,
27
+ this.auth0 = new auth0_1.AuthenticationClient(types_1.Auth0ClientSchema.parse(auth0));
28
+ this.params = {
29
+ credentialsContext: "tool-call",
30
+ ...params,
31
+ };
32
+ this.authResponseStore = new stores_1.SubStore(params.store, {
33
+ getTTL: (authResponse) => authResponse.expiresIn ? authResponse.expiresIn * 1000 : undefined,
34
+ });
35
+ this.credentialsStore = new stores_1.SubStore(params.store, {
36
+ getTTL: (credentials) => credentials.expiresIn ? credentials.expiresIn * 1000 : undefined,
28
37
  });
29
38
  }
30
- async start(toolContext) {
31
- var _a, _b, _c;
32
- const requestedAt = Date.now() / 1000;
33
- const authorizeParams = {
34
- scope: ensureOpenIdScope(this.params.scopes).join(" "),
35
- audience: this.params.audience || "",
36
- request_expiry: ((_a = this.params.requestExpiry) !== null && _a !== void 0 ? _a : 300).toString(),
37
- binding_message: (_b = (await (0, parameters_1.resolveParameter)(this.params.bindingMessage, toolContext))) !== null && _b !== void 0 ? _b : "",
38
- userId: (_c = (await (0, parameters_1.resolveParameter)(this.params.userID, toolContext))) !== null && _c !== void 0 ? _c : "",
39
+ getInstanceID(authorizeParams) {
40
+ const props = {
41
+ auth0: this.auth0,
42
+ params: authorizeParams,
39
43
  };
44
+ const sh = (0, stable_hash_1.default)(props);
45
+ return crypto_1.default.createHash("MD5").update(sh).digest("hex");
46
+ }
47
+ async start(authorizeParams) {
48
+ const requestedAt = Date.now() / 1000;
40
49
  try {
41
50
  const response = await this.auth0.backchannel.authorize(authorizeParams);
42
51
  return {
@@ -53,6 +62,16 @@ class CIBAAuthorizerBase {
53
62
  throw err;
54
63
  }
55
64
  }
65
+ async getAuthorizeParams(toolContext) {
66
+ var _a, _b, _c;
67
+ return {
68
+ scope: ensureOpenIdScope(this.params.scopes).join(" "),
69
+ audience: this.params.audience || "",
70
+ request_expiry: ((_a = this.params.requestExpiry) !== null && _a !== void 0 ? _a : 300).toString(),
71
+ binding_message: (_b = (await (0, parameters_1.resolveParameter)(this.params.bindingMessage, toolContext))) !== null && _b !== void 0 ? _b : "",
72
+ userId: (_c = (await (0, parameters_1.resolveParameter)(this.params.userID, toolContext))) !== null && _c !== void 0 ? _c : "",
73
+ };
74
+ }
56
75
  async getCredentialsInternal(authRequest) {
57
76
  try {
58
77
  const elapsedSeconds = Date.now() / 1000 - authRequest.requestedAt;
@@ -62,24 +81,7 @@ class CIBAAuthorizerBase {
62
81
  const response = await this.auth0.backchannel.backchannelGrant({
63
82
  auth_req_id: authRequest.id,
64
83
  });
65
- const credentials = {
66
- accessToken: {
67
- type: response.token_type || "bearer",
68
- value: response.access_token,
69
- },
70
- refreshToken: response.refresh_token
71
- ? {
72
- type: response.token_type || "bearer",
73
- value: response.refresh_token,
74
- }
75
- : undefined,
76
- idToken: response.id_token
77
- ? {
78
- type: response.token_type || "bearer",
79
- value: response.id_token,
80
- }
81
- : undefined,
82
- };
84
+ const credentials = (0, credentials_1.tokenSetFromTokenResponse)(response);
83
85
  return credentials;
84
86
  }
85
87
  catch (e) {
@@ -123,14 +125,13 @@ class CIBAAuthorizerBase {
123
125
  return credentials;
124
126
  }
125
127
  deleteAuthRequest() {
128
+ var _a;
126
129
  const store = asyncLocalStorage_1.asyncLocalStorage.getStore();
127
130
  if (!store) {
128
131
  throw new Error("This method should be called from within a tool.");
129
132
  }
130
- if (!this.params.onAuthorizationRequest ||
131
- this.params.onAuthorizationRequest === "interrupt") {
132
- return this.params.storeAuthorizationResponse(undefined, ...store.args);
133
- }
133
+ const { authResponseNS } = store;
134
+ return (_a = this.authResponseStore) === null || _a === void 0 ? void 0 : _a.delete(authResponseNS, "authResponse");
134
135
  }
135
136
  /**
136
137
  *
@@ -142,31 +143,57 @@ class CIBAAuthorizerBase {
142
143
  */
143
144
  protect(getContext, execute) {
144
145
  return async (...args) => {
145
- let authRequest;
146
+ let authResponse;
146
147
  if (asyncLocalStorage_1.asyncLocalStorage.getStore()) {
147
148
  throw new Error("Cannot nest tool calls that require CIBA authorization.");
148
149
  }
150
+ const context = getContext(...args);
151
+ const authorizeParams = await this.getAuthorizeParams(args);
152
+ const instanceID = this.getInstanceID(authorizeParams);
153
+ const authResponseNS = [
154
+ instanceID,
155
+ "AuthResponses",
156
+ ...(0, context_1.nsFromContext)("tool-call", context),
157
+ ];
158
+ const credentialsNS = [
159
+ instanceID,
160
+ "Credentials",
161
+ ...(0, context_1.nsFromContext)(this.params.credentialsContext, context),
162
+ ];
149
163
  const storeValue = {
150
164
  args,
151
- context: getContext(...args),
165
+ context,
166
+ authResponseNS,
152
167
  };
153
168
  return asyncLocalStorage_1.asyncLocalStorage.run(storeValue, async () => {
169
+ var _a, _b, _c, _d;
154
170
  let credentials;
155
171
  const interruptMode = typeof this.params.onAuthorizationRequest === "undefined" ||
156
172
  this.params.onAuthorizationRequest === "interrupt";
157
173
  try {
158
- if (interruptMode) {
159
- authRequest = await (0, parameters_1.resolveParameter)(this.params.getAuthorizationResponse, args);
160
- if (!authRequest) {
161
- //Initial request
162
- authRequest = await this.start(args);
163
- await this.params.storeAuthorizationResponse(authRequest, ...args);
174
+ credentials = await ((_a = this.credentialsStore) === null || _a === void 0 ? void 0 : _a.get(credentialsNS, "credential"));
175
+ if (!credentials) {
176
+ if (interruptMode) {
177
+ authResponse = await ((_b = this.authResponseStore) === null || _b === void 0 ? void 0 : _b.get(authResponseNS, "authResponse"));
178
+ if (!authResponse) {
179
+ //Initial request
180
+ authResponse = await this.start(authorizeParams);
181
+ await ((_c = this.authResponseStore) === null || _c === void 0 ? void 0 : _c.put(authResponseNS, "authResponse", authResponse));
182
+ }
183
+ credentials = await this.getCredentials(authResponse);
184
+ }
185
+ else {
186
+ authResponse = await this.start(authorizeParams);
187
+ const credentialsPromise = this.getCredentialsPolling(authResponse);
188
+ if (typeof this.params.onAuthorizationRequest === "function") {
189
+ await this.params.onAuthorizationRequest(authResponse, credentialsPromise);
190
+ }
191
+ credentials = await credentialsPromise;
192
+ }
193
+ await this.deleteAuthRequest();
194
+ if (typeof credentials !== "undefined") {
195
+ (_d = this.credentialsStore) === null || _d === void 0 ? void 0 : _d.put(credentialsNS, "credential", credentials);
164
196
  }
165
- credentials = await this.getCredentials(authRequest);
166
- }
167
- else {
168
- authRequest = await this.start(args);
169
- credentials = await this.getCredentialsPolling(authRequest);
170
197
  }
171
198
  }
172
199
  catch (err) {
@@ -185,7 +212,6 @@ class CIBAAuthorizerBase {
185
212
  }
186
213
  }
187
214
  }
188
- await this.deleteAuthRequest();
189
215
  storeValue.credentials = credentials;
190
216
  return execute(...args);
191
217
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CIBAAuthorizerBase.js","sourceRoot":"","sources":["../../../../src/authorizers/ciba/CIBAAuthorizerBase.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthenticationClient } from \"auth0\";\n\nimport { AuthorizerParams } from \"../\";\nimport { Credentials } from \"../../credentials\";\nimport {\n AccessDeniedInterrupt,\n AuthorizationPendingInterrupt,\n AuthorizationPollingInterrupt,\n AuthorizationRequestExpiredInterrupt,\n InvalidGrantInterrupt,\n UserDoesNotHavePushNotificationsInterrupt,\n} from \"../../interrupts\";\nimport { resolveParameter } from \"../../parameters\";\nimport { asyncLocalStorage, AsyncStorageValue } from \"./asyncLocalStorage\";\nimport { CIBAAuthorizationRequest } from \"./CIBAAuthorizationRequest\";\nimport { CIBAAuthorizerParams } from \"./CIBAAuthorizerParams\";\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\nfunction ensureOpenIdScope(scopes: string[]): string[] {\n return scopes.includes(\"openid\") ? scopes : [\"openid\", ...scopes];\n}\n/**\n * Requests authorization by prompting the user via an out-of-band channel from\n * the backend.\n */\nexport class CIBAAuthorizerBase<ToolExecuteArgs extends any[]> {\n auth0: AuthenticationClient;\n\n constructor(\n auth0: AuthorizerParams,\n private readonly params: CIBAAuthorizerParams<ToolExecuteArgs>\n ) {\n this.auth0 = new AuthenticationClient({\n domain: auth0?.domain || process.env.AUTH0_DOMAIN!,\n clientId: auth0?.clientId || process.env.AUTH0_CLIENT_ID!,\n clientSecret: auth0?.clientSecret || process.env.AUTH0_CLIENT_SECRET,\n clientAssertionSigningAlg: auth0?.clientAssertionSigningAlg,\n clientAssertionSigningKey: auth0?.clientAssertionSigningKey,\n idTokenSigningAlg: auth0?.idTokenSigningAlg,\n clockTolerance: auth0?.clockTolerance,\n useMTLS: auth0?.useMTLS,\n });\n }\n\n private async start(\n toolContext: ToolExecuteArgs\n ): Promise<CIBAAuthorizationRequest> {\n const requestedAt = Date.now() / 1000;\n const authorizeParams = {\n scope: ensureOpenIdScope(this.params.scopes).join(\" \"),\n audience: this.params.audience || \"\",\n request_expiry: (this.params.requestExpiry ?? 300).toString(),\n binding_message:\n (await resolveParameter(this.params.bindingMessage, toolContext)) ?? \"\",\n userId: (await resolveParameter(this.params.userID, toolContext)) ?? \"\",\n };\n\n try {\n const response = await this.auth0.backchannel.authorize(authorizeParams);\n\n return {\n id: response.auth_req_id,\n requestedAt: requestedAt,\n expiresIn: response.expires_in,\n interval: response.interval,\n };\n } catch (err: any) {\n if (err.error == \"invalid_request\") {\n throw new UserDoesNotHavePushNotificationsInterrupt(\n err.error_description\n );\n }\n throw err;\n }\n }\n\n private async getCredentialsInternal(\n authRequest: CIBAAuthorizationRequest\n ): Promise<Credentials | undefined> {\n try {\n const elapsedSeconds = Date.now() / 1000 - authRequest.requestedAt;\n\n if (elapsedSeconds >= authRequest.expiresIn) {\n throw new AuthorizationRequestExpiredInterrupt(\n \"The authorization request has expired.\",\n authRequest\n );\n }\n\n const response = await this.auth0.backchannel.backchannelGrant({\n auth_req_id: authRequest.id,\n });\n\n const credentials = {\n accessToken: {\n type: response.token_type || \"bearer\",\n value: response.access_token,\n },\n refreshToken: response.refresh_token\n ? {\n type: response.token_type || \"bearer\",\n value: response.refresh_token,\n }\n : undefined,\n idToken: response.id_token\n ? {\n type: response.token_type || \"bearer\",\n value: response.id_token,\n }\n : undefined,\n };\n\n return credentials;\n } catch (e: any) {\n if (e.error === \"authorization_pending\") {\n throw new AuthorizationPendingInterrupt(\n e.error_description,\n authRequest\n );\n }\n\n if (e.error === \"slow_down\") {\n throw new AuthorizationPollingInterrupt(\n e.error_description,\n authRequest\n );\n }\n\n if (e.error == \"invalid_grant\") {\n throw new InvalidGrantInterrupt(e.error_description, authRequest);\n }\n\n if (e.error == \"invalid_request\") {\n throw new UserDoesNotHavePushNotificationsInterrupt(\n e.error_description\n );\n }\n\n if (e.error == \"access_denied\") {\n throw new AccessDeniedInterrupt(e.error_description, authRequest);\n }\n\n throw e;\n }\n }\n\n protected async getCredentials(authRequest: CIBAAuthorizationRequest) {\n return this.getCredentialsInternal(authRequest);\n }\n\n protected async getCredentialsPolling(\n authRequest: CIBAAuthorizationRequest\n ): Promise<Credentials | undefined> {\n let credentials: Credentials | undefined = undefined;\n\n do {\n try {\n credentials = await this.getCredentialsInternal(authRequest);\n } catch (err) {\n if (\n err instanceof AuthorizationPendingInterrupt ||\n err instanceof AuthorizationPollingInterrupt\n ) {\n await sleep(err.request.interval * 1000);\n } else {\n throw err;\n }\n }\n } while (!credentials);\n\n return credentials;\n }\n\n protected deleteAuthRequest() {\n const store = asyncLocalStorage.getStore();\n if (!store) {\n throw new Error(\"This method should be called from within a tool.\");\n }\n if (\n !this.params.onAuthorizationRequest ||\n this.params.onAuthorizationRequest === \"interrupt\"\n ) {\n return this.params.storeAuthorizationResponse(\n undefined,\n ...(store.args as ToolExecuteArgs)\n );\n }\n }\n\n /**\n *\n * Wraps the execute method of a AI tool to handle CIBA authorization.\n *\n * @param getContext - A function that returns the context of the tool execution.\n * @param execute - The tool execute method.\n * @returns The wrapped execute method.\n */\n protect(\n getContext: (...args: ToolExecuteArgs) => any,\n execute: (...args: ToolExecuteArgs) => any\n ): (...args: ToolExecuteArgs) => any {\n return async (...args: ToolExecuteArgs) => {\n let authRequest: CIBAAuthorizationRequest | undefined;\n if (asyncLocalStorage.getStore()) {\n throw new Error(\n \"Cannot nest tool calls that require CIBA authorization.\"\n );\n }\n\n const storeValue: AsyncStorageValue<any> = {\n args,\n context: getContext(...args),\n };\n\n return asyncLocalStorage.run(storeValue, async () => {\n let credentials: Credentials | undefined;\n\n const interruptMode =\n typeof this.params.onAuthorizationRequest === \"undefined\" ||\n this.params.onAuthorizationRequest === \"interrupt\";\n\n try {\n if (interruptMode) {\n authRequest = await resolveParameter(\n this.params.getAuthorizationResponse,\n args\n );\n if (!authRequest) {\n //Initial request\n authRequest = await this.start(args);\n await this.params.storeAuthorizationResponse(\n authRequest,\n ...args\n );\n }\n credentials = await this.getCredentials(authRequest);\n } else {\n authRequest = await this.start(args);\n credentials = await this.getCredentialsPolling(authRequest);\n }\n } catch (err) {\n const shouldInterrupt =\n err instanceof AuthorizationPendingInterrupt ||\n err instanceof AuthorizationPollingInterrupt;\n if (shouldInterrupt) {\n return this.handleAuthorizationInterrupts(err);\n } else {\n await this.deleteAuthRequest();\n if (typeof this.params.onUnauthorized === \"function\") {\n return this.params.onUnauthorized(err as Error, ...args);\n } else {\n return err;\n }\n }\n }\n await this.deleteAuthRequest();\n storeValue.credentials = credentials;\n return execute(...args);\n });\n };\n }\n\n protected handleAuthorizationInterrupts(\n err: AuthorizationPendingInterrupt | AuthorizationPollingInterrupt\n ) {\n throw err;\n }\n}\n"]}
1
+ {"version":3,"file":"CIBAAuthorizerBase.js","sourceRoot":"","sources":["../../../../src/authorizers/ciba/CIBAAuthorizerBase.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthenticationClient } from \"auth0\";\nimport crypto from \"crypto\";\nimport stableHash from \"stable-hash\";\n\nimport { TokenSet, tokenSetFromTokenResponse } from \"../../credentials\";\nimport {\n AccessDeniedInterrupt,\n AuthorizationPendingInterrupt,\n AuthorizationPollingInterrupt,\n AuthorizationRequestExpiredInterrupt,\n InvalidGrantInterrupt,\n UserDoesNotHavePushNotificationsInterrupt,\n} from \"../../interrupts\";\nimport { resolveParameter } from \"../../parameters\";\nimport { SubStore } from \"../../stores\";\nimport { RequireFields } from \"../../util\";\nimport { ContextGetter, nsFromContext } from \"../context\";\nimport { Auth0ClientParams, Auth0ClientSchema } from \"../types\";\nimport { asyncLocalStorage, AsyncStorageValue } from \"./asyncLocalStorage\";\nimport { CIBAAuthorizationRequest } from \"./CIBAAuthorizationRequest\";\nimport { CIBAAuthorizerParams } from \"./CIBAAuthorizerParams\";\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\nfunction ensureOpenIdScope(scopes: string[]): string[] {\n return scopes.includes(\"openid\") ? scopes : [\"openid\", ...scopes];\n}\n/**\n * Requests authorization by prompting the user via an out-of-band channel from\n * the backend.\n */\nexport class CIBAAuthorizerBase<ToolExecuteArgs extends any[]> {\n private readonly auth0: AuthenticationClient;\n private readonly authResponseStore: SubStore | undefined;\n private readonly credentialsStore: SubStore<TokenSet> | undefined;\n\n private readonly params: RequireFields<\n CIBAAuthorizerParams<ToolExecuteArgs>,\n \"credentialsContext\"\n >;\n\n constructor(\n auth0: Partial<Auth0ClientParams>,\n params: CIBAAuthorizerParams<ToolExecuteArgs>\n ) {\n this.auth0 = new AuthenticationClient(Auth0ClientSchema.parse(auth0));\n this.params = {\n credentialsContext: \"tool-call\",\n ...params,\n };\n\n this.authResponseStore = new SubStore<CIBAAuthorizationRequest>(\n params.store,\n {\n getTTL: (authResponse) =>\n authResponse.expiresIn ? authResponse.expiresIn * 1000 : undefined,\n }\n );\n\n this.credentialsStore = new SubStore<TokenSet>(params.store, {\n getTTL: (credentials) =>\n credentials.expiresIn ? credentials.expiresIn * 1000 : undefined,\n });\n }\n\n private getInstanceID(authorizeParams: any): string {\n const props = {\n auth0: this.auth0,\n params: authorizeParams,\n };\n const sh = stableHash(props);\n return crypto.createHash(\"MD5\").update(sh).digest(\"hex\");\n }\n\n private async start(authorizeParams: any): Promise<CIBAAuthorizationRequest> {\n const requestedAt = Date.now() / 1000;\n\n try {\n const response = await this.auth0.backchannel.authorize(authorizeParams);\n\n return {\n id: response.auth_req_id,\n requestedAt: requestedAt,\n expiresIn: response.expires_in,\n interval: response.interval,\n };\n } catch (err: any) {\n if (err.error == \"invalid_request\") {\n throw new UserDoesNotHavePushNotificationsInterrupt(\n err.error_description\n );\n }\n throw err;\n }\n }\n\n private async getAuthorizeParams(toolContext: ToolExecuteArgs) {\n return {\n scope: ensureOpenIdScope(this.params.scopes).join(\" \"),\n audience: this.params.audience || \"\",\n request_expiry: (this.params.requestExpiry ?? 300).toString(),\n binding_message:\n (await resolveParameter(this.params.bindingMessage, toolContext)) ?? \"\",\n userId: (await resolveParameter(this.params.userID, toolContext)) ?? \"\",\n };\n }\n\n private async getCredentialsInternal(\n authRequest: CIBAAuthorizationRequest\n ): Promise<TokenSet | undefined> {\n try {\n const elapsedSeconds = Date.now() / 1000 - authRequest.requestedAt;\n\n if (elapsedSeconds >= authRequest.expiresIn) {\n throw new AuthorizationRequestExpiredInterrupt(\n \"The authorization request has expired.\",\n authRequest\n );\n }\n\n const response = await this.auth0.backchannel.backchannelGrant({\n auth_req_id: authRequest.id,\n });\n\n const credentials = tokenSetFromTokenResponse(response);\n\n return credentials;\n } catch (e: any) {\n if (e.error === \"authorization_pending\") {\n throw new AuthorizationPendingInterrupt(\n e.error_description,\n authRequest\n );\n }\n\n if (e.error === \"slow_down\") {\n throw new AuthorizationPollingInterrupt(\n e.error_description,\n authRequest\n );\n }\n\n if (e.error == \"invalid_grant\") {\n throw new InvalidGrantInterrupt(e.error_description, authRequest);\n }\n\n if (e.error == \"invalid_request\") {\n throw new UserDoesNotHavePushNotificationsInterrupt(\n e.error_description\n );\n }\n\n if (e.error == \"access_denied\") {\n throw new AccessDeniedInterrupt(e.error_description, authRequest);\n }\n\n throw e;\n }\n }\n\n protected async getCredentials(authRequest: CIBAAuthorizationRequest) {\n return this.getCredentialsInternal(authRequest);\n }\n\n protected async getCredentialsPolling(\n authRequest: CIBAAuthorizationRequest\n ): Promise<TokenSet | undefined> {\n let credentials: TokenSet | undefined = undefined;\n\n do {\n try {\n credentials = await this.getCredentialsInternal(authRequest);\n } catch (err) {\n if (\n err instanceof AuthorizationPendingInterrupt ||\n err instanceof AuthorizationPollingInterrupt\n ) {\n await sleep(err.request.interval * 1000);\n } else {\n throw err;\n }\n }\n } while (!credentials);\n\n return credentials;\n }\n\n protected deleteAuthRequest() {\n const store = asyncLocalStorage.getStore();\n if (!store) {\n throw new Error(\"This method should be called from within a tool.\");\n }\n const { authResponseNS } = store;\n return this.authResponseStore?.delete(authResponseNS, \"authResponse\");\n }\n\n /**\n *\n * Wraps the execute method of a AI tool to handle CIBA authorization.\n *\n * @param getContext - A function that returns the context of the tool execution.\n * @param execute - The tool execute method.\n * @returns The wrapped execute method.\n */\n protect(\n getContext: ContextGetter<ToolExecuteArgs>,\n execute: (...args: ToolExecuteArgs) => any\n ): (...args: ToolExecuteArgs) => any {\n return async (...args: ToolExecuteArgs) => {\n let authResponse: CIBAAuthorizationRequest | undefined;\n if (asyncLocalStorage.getStore()) {\n throw new Error(\n \"Cannot nest tool calls that require CIBA authorization.\"\n );\n }\n\n const context = getContext(...args);\n const authorizeParams = await this.getAuthorizeParams(args);\n const instanceID = this.getInstanceID(authorizeParams);\n const authResponseNS = [\n instanceID,\n \"AuthResponses\",\n ...nsFromContext(\"tool-call\", context),\n ];\n const credentialsNS = [\n instanceID,\n \"Credentials\",\n ...nsFromContext(this.params.credentialsContext, context),\n ];\n\n const storeValue: AsyncStorageValue<any> = {\n args,\n context,\n authResponseNS,\n };\n\n return asyncLocalStorage.run(storeValue, async () => {\n let credentials: TokenSet | undefined;\n\n const interruptMode =\n typeof this.params.onAuthorizationRequest === \"undefined\" ||\n this.params.onAuthorizationRequest === \"interrupt\";\n\n try {\n credentials = await this.credentialsStore?.get(\n credentialsNS,\n \"credential\"\n );\n if (!credentials) {\n if (interruptMode) {\n authResponse = await this.authResponseStore?.get(\n authResponseNS,\n \"authResponse\"\n );\n if (!authResponse) {\n //Initial request\n authResponse = await this.start(authorizeParams);\n await this.authResponseStore?.put(\n authResponseNS,\n \"authResponse\",\n authResponse\n );\n }\n credentials = await this.getCredentials(authResponse);\n } else {\n authResponse = await this.start(authorizeParams);\n const credentialsPromise =\n this.getCredentialsPolling(authResponse);\n if (typeof this.params.onAuthorizationRequest === \"function\") {\n await this.params.onAuthorizationRequest(\n authResponse,\n credentialsPromise\n );\n }\n credentials = await credentialsPromise;\n }\n await this.deleteAuthRequest();\n if (typeof credentials !== \"undefined\") {\n this.credentialsStore?.put(\n credentialsNS,\n \"credential\",\n credentials\n );\n }\n }\n } catch (err) {\n const shouldInterrupt =\n err instanceof AuthorizationPendingInterrupt ||\n err instanceof AuthorizationPollingInterrupt;\n if (shouldInterrupt) {\n return this.handleAuthorizationInterrupts(err);\n } else {\n await this.deleteAuthRequest();\n if (typeof this.params.onUnauthorized === \"function\") {\n return this.params.onUnauthorized(err as Error, ...args);\n } else {\n return err;\n }\n }\n }\n storeValue.credentials = credentials;\n return execute(...args);\n });\n };\n }\n\n protected handleAuthorizationInterrupts(\n err: AuthorizationPendingInterrupt | AuthorizationPollingInterrupt\n ) {\n throw err;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CIBAAuthorizerParams.js","sourceRoot":"","sources":["../../../../src/authorizers/ciba/CIBAAuthorizerParams.ts"],"names":[],"mappings":"","sourcesContent":["import { CIBAInterrupt } from \"../../interrupts\";\nimport { AuthorizerToolParameter } from \"../../parameters\";\nimport { CIBAAuthorizationRequest } from \"./CIBAAuthorizationRequest\";\n\nexport type OnAuthorizationRequest = \"block\" | \"interrupt\";\n\nexport type CIBAAuthorizerParams<ToolExecuteArgs extends any[]> = {\n /**\n * The user ID to request authorization for.\n */\n userID: AuthorizerToolParameter<ToolExecuteArgs>;\n\n /**\n * The binding message to send to the user.\n */\n bindingMessage: AuthorizerToolParameter<ToolExecuteArgs>;\n\n /**\n * The scope to request authorization for.\n */\n scopes: string[];\n\n /**\n * The audience to request authorization for.\n */\n audience?: string;\n\n /**\n * The time in seconds for the authorization request to expire.\n *\n * Defaults to 5m.\n */\n requestExpiry?: number;\n\n /**\n * The behavior when the authorization request is made.\n *\n * - `block`: The tool execution is blocked until the user completes the authorization.\n * - `interrupt`: The tool execution is interrupted until the user completes the authorization.\n *\n * Defaults to `interrupt`.\n * Note: The block mode is only useful for development purposes and should not be used in production.\n */\n onAuthorizationRequest?: OnAuthorizationRequest;\n\n /**\n *\n * Optional callback to generate a tool result when the invocation is not authorized.\n *\n * By default it will return the instance of the Error.\n *\n * @param args - The tool execution arguments.\n * @returns The response to return when the invocation is not authorized.\n */\n onUnauthorized?: (\n err: Error | CIBAInterrupt,\n ...args: ToolExecuteArgs\n ) => any;\n} & (\n | {\n onAuthorizationRequest: \"block\";\n }\n | {\n onAuthorizationRequest?: \"interrupt\";\n\n /**\n * Retrieves the authorization response data.\n * @param args - The tool execution arguments.\n * @returns The authorization response data.\n * @remarks The data should be stored in a way that it can be retrieved later by the `storeAuthorizationResponse` parameter.\n */\n getAuthorizationResponse: AuthorizerToolParameter<\n ToolExecuteArgs,\n CIBAAuthorizationRequest | undefined\n >;\n\n /**\n * Stores the authorization response data.\n * @param request - The authorization response data.\n * @param args - The tool execution arguments.\n * @returns A promise that resolves when the data is stored.\n * @remarks The data should be stored in a way that it can be retrieved later by the `getAuthorizationResponse` parameter.\n **/\n storeAuthorizationResponse: (\n request: CIBAAuthorizationRequest | undefined,\n ...args: ToolExecuteArgs\n ) => Promise<void>;\n }\n);\n"]}
1
+ {"version":3,"file":"CIBAAuthorizerParams.js","sourceRoot":"","sources":["../../../../src/authorizers/ciba/CIBAAuthorizerParams.ts"],"names":[],"mappings":"","sourcesContent":["import { TokenSet } from \"../../credentials\";\nimport { CIBAInterrupt } from \"../../interrupts\";\nimport { AuthorizerToolParameter } from \"../../parameters\";\nimport { Store } from \"../../stores\";\nimport { AuthContext } from \"../context\";\nimport { OnAuthorizationRequest } from \"../types\";\nimport { CIBAAuthorizationRequest } from \"./CIBAAuthorizationRequest\";\n\nexport type CIBAAuthorizerParams<ToolExecuteArgs extends any[]> = {\n /**\n * The user ID to request authorization for.\n */\n userID: AuthorizerToolParameter<ToolExecuteArgs>;\n\n /**\n * The binding message to send to the user.\n */\n bindingMessage: AuthorizerToolParameter<ToolExecuteArgs>;\n\n /**\n * The scope to request authorization for.\n */\n scopes: string[];\n\n /**\n * The audience to request authorization for.\n */\n audience?: string;\n\n /**\n * The time in seconds for the authorization request to expire.\n *\n * Defaults to 5m.\n */\n requestExpiry?: number;\n\n /**\n * The behavior when the authorization request is made.\n *\n * - `block`: The tool execution is blocked until the user completes the authorization.\n * - `interrupt`: The tool execution is interrupted until the user completes the authorization.\n * - a callback: Same as \"block\" but give access to the auth request and executing logic.\n *\n * Defaults to `interrupt`.\n * Note: The block mode is only useful for development purposes and should not be used in production.\n */\n onAuthorizationRequest?:\n | OnAuthorizationRequest\n | ((\n authReq: CIBAAuthorizationRequest,\n poll: Promise<TokenSet | undefined>\n ) => Promise<void>);\n\n /**\n * AuthContext defines the scope of credential sharing:\n * - \"tool-call\": Credentials are valid only for a single invocation of the tool.\n * - \"tool\": Credentials are shared across multiple calls to the same tool within the same thread.\n * - \"thread\": Credentials are shared across all tools using the same authorizer within the current thread.\n * - \"agent\": Credentials are shared globally across all threads and tools in the agent.\n *\n * @default \"tool-call\"\n */\n credentialsContext?: AuthContext;\n\n /**\n *\n * Optional callback to generate a tool result when the invocation is not authorized.\n *\n * By default it will return the instance of the Error.\n *\n * @param args - The tool execution arguments.\n * @returns The response to return when the invocation is not authorized.\n */\n onUnauthorized?: (\n err: Error | CIBAInterrupt,\n ...args: ToolExecuteArgs\n ) => any;\n\n /**\n * An store used to temporarly store the authorization response data\n * while the user is completing the authorization in another device.\n */\n store: Store;\n};\n"]}
@@ -6,7 +6,7 @@ exports.asyncLocalStorage = new async_hooks_1.AsyncLocalStorage();
6
6
  const getCIBACredentials = () => {
7
7
  const t = exports.asyncLocalStorage.getStore();
8
8
  if (typeof t === "undefined") {
9
- throw new Error("The tool must be wrapped with the withCIBA function.");
9
+ throw new Error("The tool must be wrapped with the withAsyncUserConfirmation function.");
10
10
  }
11
11
  return t.credentials;
12
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"asyncLocalStorage.js","sourceRoot":"","sources":["../../../../src/authorizers/ciba/asyncLocalStorage.ts"],"names":[],"mappings":";;;AAAA,6CAAgD;AAkBnC,QAAA,iBAAiB,GAAG,IAAI,+BAAiB,EAEnD,CAAC;AAEG,MAAM,kBAAkB,GAAG,GAAG,EAAE;IACrC,MAAM,CAAC,GAAG,yBAAiB,CAAC,QAAQ,EAAE,CAAC;IACvC,IAAI,OAAO,CAAC,KAAK,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,CAAC,CAAC,WAAW,CAAC;AACvB,CAAC,CAAC;AANW,QAAA,kBAAkB,sBAM7B","sourcesContent":["import { AsyncLocalStorage } from \"async_hooks\";\n\nimport { Credentials } from \"../../credentials\";\n\nexport type AsyncStorageValue<TContext> = {\n credentials?: Credentials;\n\n /**\n * The tool execution context.\n */\n context: TContext;\n\n /**\n * The tool execution arguments.\n */\n args: any[];\n};\n\nexport const asyncLocalStorage = new AsyncLocalStorage<\n AsyncStorageValue<any>\n>();\n\nexport const getCIBACredentials = () => {\n const t = asyncLocalStorage.getStore();\n if (typeof t === \"undefined\") {\n throw new Error(\"The tool must be wrapped with the withCIBA function.\");\n }\n return t.credentials;\n};\n"]}
1
+ {"version":3,"file":"asyncLocalStorage.js","sourceRoot":"","sources":["../../../../src/authorizers/ciba/asyncLocalStorage.ts"],"names":[],"mappings":";;;AAAA,6CAAgD;AAuBnC,QAAA,iBAAiB,GAAG,IAAI,+BAAiB,EAEnD,CAAC;AAEG,MAAM,kBAAkB,GAAG,GAAG,EAAE;IACrC,MAAM,CAAC,GAAG,yBAAiB,CAAC,QAAQ,EAAE,CAAC;IACvC,IAAI,OAAO,CAAC,KAAK,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC,WAAW,CAAC;AACvB,CAAC,CAAC;AARW,QAAA,kBAAkB,sBAQ7B","sourcesContent":["import { AsyncLocalStorage } from \"async_hooks\";\n\nimport { TokenSet } from \"../../credentials\";\n\nexport type AsyncStorageValue<TContext> = {\n credentials?: TokenSet;\n\n /**\n * The tool execution context.\n */\n context: TContext;\n\n /**\n * The tool execution arguments.\n */\n args: any[];\n\n /**\n * The namespace in the Store for the CIBA authorization response.\n */\n authResponseNS: string[];\n};\n\nexport const asyncLocalStorage = new AsyncLocalStorage<\n AsyncStorageValue<any>\n>();\n\nexport const getCIBACredentials = () => {\n const t = asyncLocalStorage.getStore();\n if (typeof t === \"undefined\") {\n throw new Error(\n \"The tool must be wrapped with the withAsyncUserConfirmation function.\"\n );\n }\n return t.credentials;\n};\n"]}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nsFromContext = void 0;
4
+ const nsFromContext = (authContext, callContext) => {
5
+ const threadNS = ["Threads", callContext.threadID];
6
+ const toolNS = ["Tools", callContext.toolName];
7
+ const toolCallNS = ["ToolCalls", callContext.toolCallID];
8
+ switch (authContext) {
9
+ case "tool-call":
10
+ return [...threadNS, ...toolNS, ...toolCallNS];
11
+ case "tool":
12
+ return [...threadNS, ...toolNS];
13
+ case "thread":
14
+ return threadNS;
15
+ case "agent":
16
+ return [];
17
+ }
18
+ };
19
+ exports.nsFromContext = nsFromContext;
20
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/authorizers/context.ts"],"names":[],"mappings":";;;AAmBO,MAAM,aAAa,GAAG,CAC3B,WAAwB,EACxB,WAA4B,EAC5B,EAAE;IACF,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAEzD,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,WAAW;YACd,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC;QACjD,KAAK,MAAM;YACT,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC;QAClC,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,OAAO;YACV,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAlBW,QAAA,aAAa,iBAkBxB","sourcesContent":["export type ToolCallContext = {\n threadID: string;\n toolCallID: string;\n toolName: string;\n};\n\nexport type ContextGetter<ToolExecuteArgs extends any[]> = (\n ...args: ToolExecuteArgs\n) => ToolCallContext;\n\n/**\n * AuthContext defines the scope of credential sharing:\n * - \"tool-call\": Credentials are valid only for a single invocation of the tool.\n * - \"tool\": Credentials are shared across multiple calls to the same tool within the same thread.\n * - \"thread\": Credentials are shared across all tools using the same authorizer within the current thread.\n * - \"agent\": Credentials are shared globally across all threads and tools in the agent.\n */\nexport type AuthContext = \"tool-call\" | \"tool\" | \"thread\" | \"agent\";\n\nexport const nsFromContext = (\n authContext: AuthContext,\n callContext: ToolCallContext\n) => {\n const threadNS = [\"Threads\", callContext.threadID];\n const toolNS = [\"Tools\", callContext.toolName];\n const toolCallNS = [\"ToolCalls\", callContext.toolCallID];\n\n switch (authContext) {\n case \"tool-call\":\n return [...threadNS, ...toolNS, ...toolCallNS];\n case \"tool\":\n return [...threadNS, ...toolNS];\n case \"thread\":\n return threadNS;\n case \"agent\":\n return [];\n }\n};\n"]}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseDeviceAuthResponse = parseDeviceAuthResponse;
4
+ // Function to map from DeviceAuthorizationResponseOIDC to DeviceAuthorizationResponse
5
+ function parseDeviceAuthResponse(oidcResponse, requestedAt) {
6
+ const { device_code, user_code, verification_uri, expires_in, verification_uri_complete, interval, ...rest } = oidcResponse;
7
+ return {
8
+ deviceCode: device_code,
9
+ userCode: user_code,
10
+ verificationUri: verification_uri,
11
+ expiresIn: expires_in,
12
+ verificationUriComplete: verification_uri_complete,
13
+ interval: interval,
14
+ requestedAt,
15
+ ...rest,
16
+ };
17
+ }
18
+ //# sourceMappingURL=DeviceAuthResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceAuthResponse.js","sourceRoot":"","sources":["../../../../src/authorizers/device-authorizer/DeviceAuthResponse.ts"],"names":[],"mappings":";;AA2CA,0DAuBC;AAxBD,sFAAsF;AACtF,SAAgB,uBAAuB,CACrC,YAA6C,EAC7C,WAAmB;IAEnB,MAAM,EACJ,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,yBAAyB,EACzB,QAAQ,EACR,GAAG,IAAI,EACR,GAAG,YAAY,CAAC;IACjB,OAAO;QACL,UAAU,EAAE,WAAW;QACvB,QAAQ,EAAE,SAAS;QACnB,eAAe,EAAE,gBAAgB;QACjC,SAAS,EAAE,UAAU;QACrB,uBAAuB,EAAE,yBAAyB;QAClD,QAAQ,EAAE,QAAQ;QAClB,WAAW;QACX,GAAG,IAAI;KACR,CAAC;AACJ,CAAC","sourcesContent":["import { DeviceAuthorizationResponse as DeviceAuthorizationResponseOIDC } from \"openid-client\";\n\nexport interface DeviceAuthorizationResponse {\n /**\n * The device verification code\n */\n readonly deviceCode: string;\n /**\n * The end-user verification code\n */\n readonly userCode: string;\n /**\n * The end-user verification URI on the authorization server. The URI should be short and easy to\n * remember as end users will be asked to manually type it into their user agent.\n */\n readonly verificationUri: string;\n\n /**\n * The lifetime in seconds of the \"device_code\" and \"user_code\".\n */\n readonly expiresIn: number;\n\n /**\n * A verification URI that includes the \"user_code\" (or other information with the same function\n * as the \"user_code\"), which is designed for non-textual transmission\n */\n readonly verificationUriComplete?: string;\n /**\n * The minimum amount of time in seconds that the client\n * should wait between polling requests to the token endpoint.\n */\n readonly interval?: number;\n\n /**\n * The time at which the request was made\n * (in secs since the Unix epoch)\n */\n readonly requestedAt: number;\n\n readonly [parameter: string]: any | undefined;\n}\n\n// Function to map from DeviceAuthorizationResponseOIDC to DeviceAuthorizationResponse\nexport function parseDeviceAuthResponse(\n oidcResponse: DeviceAuthorizationResponseOIDC,\n requestedAt: number\n): DeviceAuthorizationResponse {\n const {\n device_code,\n user_code,\n verification_uri,\n expires_in,\n verification_uri_complete,\n interval,\n ...rest\n } = oidcResponse;\n return {\n deviceCode: device_code,\n userCode: user_code,\n verificationUri: verification_uri,\n expiresIn: expires_in,\n verificationUriComplete: verification_uri_complete,\n interval: interval,\n requestedAt,\n ...rest,\n };\n}\n"]}
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DeviceAuthorizerBase = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const openid_client_1 = require("openid-client");
9
+ const stable_hash_1 = require("stable-hash");
10
+ const credentials_1 = require("../../credentials");
11
+ const DeviceInterrupts_1 = require("../../interrupts/DeviceInterrupts");
12
+ const stores_1 = require("../../stores");
13
+ const util_1 = require("../../util");
14
+ const context_1 = require("../context");
15
+ const types_1 = require("../types");
16
+ const asyncLocalStorage_1 = require("./asyncLocalStorage");
17
+ const DeviceAuthResponse_1 = require("./DeviceAuthResponse");
18
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
19
+ /**
20
+ * The DeviceAuthorizerBase class acts as a guard and wrapper around tools or agent
21
+ * capabilities that require authenticated access. It encapsulates the
22
+ * OpenID Connect Device Authorization Flow, allowing tools to interrupt execution
23
+ * to request user authorization and resume seamlessly once authorization is granted.
24
+ *
25
+ * Enable agentic tools to be wrapped with secure, lazy-triggered device authorization,
26
+ * with a clean interrupt/resume model for user-in-the-loop authentication.
27
+ *
28
+ * Core Concepts
29
+ *
30
+ * - Interrupt-driven flow: If no valid token is present, the tool throws a DeviceAuthInterrupt,
31
+ * which contains the verification_uri, user_code, and other relevant metadata.
32
+ *
33
+ * - Polling/resumption: The Agent client can poll the agent to resume execution.
34
+ *
35
+ * - Token management: Tokens (and refresh tokens, if applicable) are stored and reused
36
+ * transparently.
37
+ *
38
+ */
39
+ class DeviceAuthorizerBase {
40
+ constructor(auth0, params) {
41
+ this.auth0 = types_1.Auth0PublicClientSchema.parse(auth0);
42
+ if (!this.auth0.domain) {
43
+ throw new Error("Domain is required.");
44
+ }
45
+ if (!this.auth0.clientId) {
46
+ throw new Error("Client ID is required.");
47
+ }
48
+ if (!params.store) {
49
+ throw new Error("Store is required.");
50
+ }
51
+ this.params = {
52
+ credentialsContext: "thread",
53
+ ...params,
54
+ };
55
+ const instanceID = this.getInstanceID();
56
+ this.credentialsStore = new stores_1.SubStore(params.store, {
57
+ baseNamespace: [instanceID, "Credentials"],
58
+ getTTL: (credentials) => credentials.expiresIn ? credentials.expiresIn * 1000 : undefined,
59
+ });
60
+ this.authResponseStore = new stores_1.SubStore(params.store, {
61
+ baseNamespace: [instanceID, "AuthResponses"],
62
+ getTTL: (authResponse) => authResponse.expiresIn ? authResponse.expiresIn * 1000 : undefined,
63
+ });
64
+ }
65
+ async start() {
66
+ var _a;
67
+ const requestedAt = Date.now() / 1000;
68
+ const config = await (0, openid_client_1.discovery)(new URL(`https://${this.auth0.domain}`), this.auth0.clientId);
69
+ const handle = await (0, openid_client_1.initiateDeviceAuthorization)(config, {
70
+ scope: ((_a = this.params.scopes) !== null && _a !== void 0 ? _a : []).join(" "),
71
+ audience: this.params.audience,
72
+ });
73
+ return (0, DeviceAuthResponse_1.parseDeviceAuthResponse)(handle, requestedAt);
74
+ }
75
+ /**
76
+ *
77
+ * Wraps the execute method of a AI tool to handle CIBA authorization.
78
+ *
79
+ * @param getContext - A function that returns the context of the tool execution.
80
+ * @param execute - The tool execute method.
81
+ * @returns The wrapped execute method.
82
+ */
83
+ protect(getContext, execute) {
84
+ return async (...args) => {
85
+ let authResponse;
86
+ if (asyncLocalStorage_1.asyncLocalStorage.getStore()) {
87
+ throw new Error("Cannot nest tool calls that require CIBA authorization.");
88
+ }
89
+ const context = getContext(...args);
90
+ const storeValue = {
91
+ args,
92
+ context: context,
93
+ };
94
+ return asyncLocalStorage_1.asyncLocalStorage.run(storeValue, async () => {
95
+ let credentials;
96
+ let credentialsObtained = false;
97
+ const authResponseNS = (0, context_1.nsFromContext)("tool-call", context);
98
+ const credentialsNS = (0, context_1.nsFromContext)(this.params.credentialsContext, context);
99
+ try {
100
+ credentials = await this.credentialsStore.get(credentialsNS, "credential");
101
+ if (!credentials) {
102
+ if (!this.params.onAuthorizationRequest ||
103
+ this.params.onAuthorizationRequest === "interrupt") {
104
+ authResponse = await this.authResponseStore.get(authResponseNS, "authResponse");
105
+ if (!authResponse) {
106
+ //Initial request
107
+ authResponse = await this.start();
108
+ await this.authResponseStore.put(authResponseNS, "authResponse", authResponse);
109
+ }
110
+ credentials = await this.getCredentials(authResponse);
111
+ }
112
+ else {
113
+ // Block mode
114
+ authResponse = await this.start();
115
+ const credentialsPromise = this.getCredentialsPolling(authResponse);
116
+ if (typeof this.params.onAuthorizationRequest === "function") {
117
+ await this.params.onAuthorizationRequest(authResponse, credentialsPromise);
118
+ }
119
+ credentials = await credentialsPromise;
120
+ }
121
+ if (typeof credentials !== "undefined") {
122
+ this.credentialsStore.put(credentialsNS, "credential", credentials);
123
+ }
124
+ credentialsObtained = true;
125
+ }
126
+ }
127
+ catch (err) {
128
+ const shouldInterrupt = err instanceof DeviceInterrupts_1.AuthorizationPendingInterrupt ||
129
+ err instanceof DeviceInterrupts_1.AuthorizationPollingInterrupt;
130
+ if (shouldInterrupt) {
131
+ return this.handleAuthorizationInterrupts(err);
132
+ }
133
+ else {
134
+ await this.deleteAuthRequest();
135
+ if (typeof this.params.onUnauthorized === "function") {
136
+ return this.params.onUnauthorized(err, ...args);
137
+ }
138
+ else {
139
+ return err;
140
+ }
141
+ }
142
+ }
143
+ if (credentialsObtained) {
144
+ await this.deleteAuthRequest();
145
+ }
146
+ storeValue.credentials = credentials;
147
+ return execute(...args);
148
+ });
149
+ };
150
+ }
151
+ async getCredentials(authResponse) {
152
+ var _a;
153
+ //TODO: this is not supported neither by the OIDC client library
154
+ // or the auth0 client.
155
+ const url = `https://${this.auth0.domain}/oauth/token`;
156
+ const response = await fetch(url, {
157
+ method: "POST",
158
+ headers: {
159
+ "Content-Type": "application/x-www-form-urlencoded",
160
+ },
161
+ body: new URLSearchParams({
162
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
163
+ device_code: authResponse.deviceCode,
164
+ client_id: this.auth0.clientId,
165
+ }),
166
+ });
167
+ if (!response.ok) {
168
+ if ((_a = response.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.includes("application/json")) {
169
+ const { error, error_description } = await response.json();
170
+ if (error === "authorization_pending") {
171
+ throw new DeviceInterrupts_1.AuthorizationPendingInterrupt(error_description, authResponse);
172
+ }
173
+ if (error === "slow_down") {
174
+ throw new DeviceInterrupts_1.AuthorizationPollingInterrupt(error_description, authResponse);
175
+ }
176
+ if (error === "expired_token") {
177
+ throw new DeviceInterrupts_1.AuthorizationRequestExpiredInterrupt(error_description, authResponse);
178
+ }
179
+ if (error === "access_denied") {
180
+ throw new DeviceInterrupts_1.AccessDeniedInterrupt(error_description, authResponse);
181
+ }
182
+ throw new Error(error_description);
183
+ }
184
+ const errText = await response.text();
185
+ throw new Error(`Failed to obtain tokens: ${errText}`);
186
+ }
187
+ const tr = await response.json();
188
+ const credentials = (0, credentials_1.tokenSetFromTokenResponse)(tr);
189
+ return credentials;
190
+ }
191
+ async getCredentialsPolling(authResponse) {
192
+ var _a;
193
+ let credentials = undefined;
194
+ do {
195
+ try {
196
+ credentials = await this.getCredentials(authResponse);
197
+ }
198
+ catch (err) {
199
+ if (err instanceof DeviceInterrupts_1.AuthorizationPendingInterrupt ||
200
+ err instanceof DeviceInterrupts_1.AuthorizationPollingInterrupt) {
201
+ await sleep(((_a = err.response.interval) !== null && _a !== void 0 ? _a : 10) * 1000);
202
+ }
203
+ else {
204
+ throw err;
205
+ }
206
+ }
207
+ } while (!credentials);
208
+ return credentials;
209
+ }
210
+ getInstanceID() {
211
+ const props = {
212
+ auth0: this.auth0,
213
+ params: (0, util_1.omit)(this.params, ["store", "onUnauthorized"]),
214
+ };
215
+ const sh = (0, stable_hash_1.stableHash)(props);
216
+ return node_crypto_1.default.createHash("MD5").update(sh).digest("hex");
217
+ }
218
+ deleteAuthRequest() {
219
+ const store = asyncLocalStorage_1.asyncLocalStorage.getStore();
220
+ if (!store) {
221
+ throw new Error("This method should be called from within a tool.");
222
+ }
223
+ const authResponseNS = (0, context_1.nsFromContext)("tool-call", store.context);
224
+ return this.authResponseStore.delete(authResponseNS, "authResponse");
225
+ }
226
+ handleAuthorizationInterrupts(err) {
227
+ throw err;
228
+ }
229
+ }
230
+ exports.DeviceAuthorizerBase = DeviceAuthorizerBase;
231
+ //# sourceMappingURL=DeviceAuthorizerBase.js.map