@optimizely-opal/opal-tool-ocp-sdk 0.0.0-beta.10 โ†’ 0.0.0-beta.11

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 (38) hide show
  1. package/README.md +43 -9
  2. package/dist/function/ToolFunction.d.ts +7 -4
  3. package/dist/function/ToolFunction.d.ts.map +1 -1
  4. package/dist/function/ToolFunction.js +10 -39
  5. package/dist/function/ToolFunction.js.map +1 -1
  6. package/dist/function/ToolFunction.test.js +196 -177
  7. package/dist/function/ToolFunction.test.js.map +1 -1
  8. package/dist/index.d.ts +0 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +0 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/service/Service.d.ts +7 -7
  13. package/dist/service/Service.d.ts.map +1 -1
  14. package/dist/service/Service.js +16 -22
  15. package/dist/service/Service.js.map +1 -1
  16. package/dist/service/Service.test.js +3 -8
  17. package/dist/service/Service.test.js.map +1 -1
  18. package/dist/types/Models.d.ts +5 -5
  19. package/dist/types/Models.d.ts.map +1 -1
  20. package/dist/types/Models.js +9 -9
  21. package/dist/types/Models.js.map +1 -1
  22. package/package.json +3 -5
  23. package/src/function/ToolFunction.test.ts +214 -194
  24. package/src/function/ToolFunction.ts +11 -45
  25. package/src/index.ts +0 -1
  26. package/src/service/Service.test.ts +3 -8
  27. package/src/service/Service.ts +17 -22
  28. package/src/types/Models.ts +4 -4
  29. package/dist/auth/TokenVerifier.d.ts +0 -31
  30. package/dist/auth/TokenVerifier.d.ts.map +0 -1
  31. package/dist/auth/TokenVerifier.js +0 -127
  32. package/dist/auth/TokenVerifier.js.map +0 -1
  33. package/dist/auth/TokenVerifier.test.d.ts +0 -2
  34. package/dist/auth/TokenVerifier.test.d.ts.map +0 -1
  35. package/dist/auth/TokenVerifier.test.js +0 -114
  36. package/dist/auth/TokenVerifier.test.js.map +0 -1
  37. package/src/auth/TokenVerifier.test.ts +0 -152
  38. package/src/auth/TokenVerifier.ts +0 -145
package/README.md CHANGED
@@ -10,7 +10,7 @@ A TypeScript SDK for building Opal tools in Optimizely Connect Platform. This SD
10
10
  - ๐Ÿ”ง **Type-safe Development** - Full TypeScript support with comprehensive type definitions
11
11
  - ๐Ÿ—๏ธ **Abstract Base Classes** - Extend `ToolFunction` for standardized request processing
12
12
  - ๐Ÿ” **Authentication Support** - OptiID authentication
13
- - ๐Ÿ›ก๏ธ **Authorization Support** - OptiID token tool authorization
13
+ - ๐Ÿ›ก๏ธ **Authorization Support** - Bearer token tool authorization
14
14
  - ๐Ÿ“ **Parameter Validation** - Define and validate tool parameters with types
15
15
  - ๐Ÿงช **Comprehensive Testing** - Fully tested with Jest
16
16
 
@@ -115,7 +115,7 @@ export class MyToolFunction extends ToolFunction {
115
115
  Your function class inherits a `perform()` method from `ToolFunction` that serves as the main entry point for handling all incoming requests. When called, the SDK automatically:
116
116
 
117
117
  - **Routes requests** to your registered tools and interactions based on endpoints
118
- - **Handles authentication** and OptiID token validation before calling your methods
118
+ - **Handles authentication** and bearer token validation before calling your methods
119
119
  - **Provides discovery** at `/discovery` endpoint for OCP platform integration
120
120
  - **Returns proper HTTP responses** with correct status codes and JSON formatting
121
121
 
@@ -169,18 +169,29 @@ interface AuthRequirementConfig {
169
169
  }
170
170
  ```
171
171
 
172
- #### OptiID Token Authorization
172
+ #### Bearer Token Support
173
173
 
174
- The SDK automatically handles OptiID token validation for tool authorization. OptiID tokens provide both user authentication and authorization for tools, ensuring that only authenticated users with proper permissions can access your tools.
174
+ The SDK automatically extracts Bearer tokens from the `authorization` header for tool authorization. When users register tools in Opal, they can specify a Bearer token that Opal will include in requests to validate the tool's identity.
175
175
 
176
176
  **Token Validation:**
177
- - The SDK extracts and validates OptiID tokens from the request body
178
- - Validation includes verifying that requests come from the same organization
179
- - If validation fails, returns HTTP 403 Unauthorized before reaching your handler methods
180
- - No additional configuration needed - validation is handled automatically
177
+ - Bearer tokens are extracted from the `authorization: Bearer <token>` header
178
+ - Empty strings and `undefined` tokens are treated as missing (no validation performed)
179
+ - **Optionally override** the `validateBearerToken(token: string): boolean` method to implement custom validation logic
180
+ - The default implementation returns `true` (accepts all tokens) - override if you need custom authorization
181
+ - If validation fails, returns HTTP 403 Forbidden before reaching your handler methods
181
182
 
182
183
  ```typescript
183
184
  export class MyToolFunction extends ToolFunction {
185
+ // Optional: Override this method to implement custom bearer token validation
186
+ protected override validateBearerToken(token: string): boolean {
187
+ // If you don't need bearer token validation, don't override this method
188
+ // The default implementation returns true
189
+
190
+ // For custom validation, compare against expected token
191
+ const expectedToken = process.env.OPAL_TOOL_TOKEN;
192
+ return token === expectedToken;
193
+ }
194
+
184
195
  @tool({
185
196
  name: 'secure_tool',
186
197
  description: 'Tool that validates requests from Opal',
@@ -204,6 +215,15 @@ export class MyToolFunction extends ToolFunction {
204
215
  }
205
216
  ```
206
217
 
218
+ **Bearer Token Usage:**
219
+ - Set by users when registering tools in Opal
220
+ - Used to authorize tool requests from Opal instances
221
+ - Validates that requests are coming from trusted Opal sources
222
+ - **Optionally override** the `validateBearerToken(token: string): boolean` method for custom authorization
223
+ - Default implementation accepts all tokens - override for security
224
+ - If validation fails, returns HTTP 403 Forbidden before reaching your handler methods
225
+
226
+
207
227
  ## API Reference
208
228
 
209
229
  ### Handler Function Signatures
@@ -220,6 +240,8 @@ async handlerMethod(
220
240
  - **params**: The input parameters for tools, or interaction data for webhooks
221
241
  - **authData**: Available when OptiID user authentication is configured and successful
222
242
 
243
+ **Note**: Bearer token validation is handled automatically by the base class. If a bearer token is present and fails validation, the request is rejected before reaching your handler methods.
244
+
223
245
  ### Decorators
224
246
 
225
247
  #### `@tool(config: ToolConfig)`
@@ -257,10 +279,11 @@ Abstract base class for OCP functions:
257
279
  export abstract class ToolFunction extends Function {
258
280
  protected ready(): Promise<boolean>;
259
281
  public async perform(): Promise<Response>;
282
+ protected validateBearerToken(token: string): boolean;
260
283
  }
261
284
  ```
262
285
 
263
- Extend this class and implement your OCP function. The `perform` method automatically routes requests to registered tools.
286
+ Extend this class and implement your OCP function. The `perform` method automatically routes requests to registered tools and handles bearer token validation. **You can optionally override the `validateBearerToken` method** to define custom bearer token authorization for your tools.
264
287
 
265
288
  ### Models
266
289
 
@@ -384,6 +407,11 @@ yarn lint
384
407
  import { ToolFunction, tool, interaction, ParameterType, OptiIdAuthData, InteractionResult } from '@optimizely-opal/opal-ocp-sdk';
385
408
 
386
409
  export class AuthenticatedFunction extends ToolFunction {
410
+ // Optional: Override this method for custom bearer token validation
411
+ protected override validateBearerToken(token: string): boolean {
412
+ const expectedToken = process.env.OPAL_TOOL_TOKEN;
413
+ return token === expectedToken;
414
+ }
387
415
 
388
416
  // OptiID authentication example
389
417
  @tool({
@@ -545,6 +573,12 @@ import { ToolFunction } from '@optimizely-opal/opal-ocp-sdk';
545
573
  import * from './tools';
546
574
 
547
575
  export class MyToolFunction extends ToolFunction {
576
+
577
+ // Optional: Override this method for custom bearer token validation
578
+ protected override validateBearerToken(token: string): boolean {
579
+ const expectedToken = process.env.OPAL_TOOL_TOKEN;
580
+ return token === expectedToken;
581
+ }
548
582
  }
549
583
  ```
550
584
 
@@ -18,11 +18,14 @@ export declare abstract class ToolFunction extends Function {
18
18
  */
19
19
  perform(): Promise<Response>;
20
20
  /**
21
- * Authenticate the incoming request by validating the OptiID token and organization ID
21
+ * Validates the bearer token for authorization.
22
22
  *
23
- * @throws true if authentication succeeds
23
+ * This method provides a default implementation that accepts all tokens.
24
+ * Subclasses can override this method to implement custom bearer token validation logic.
25
+ *
26
+ * @param _bearerToken - The bearer token extracted from the Authorization header
27
+ * @returns true if the token is valid and the request should proceed, false to return 403 Forbidden
24
28
  */
25
- private authorizeRequest;
26
- private validateAccessToken;
29
+ protected validateBearerToken(_bearerToken: string): boolean;
27
30
  }
28
31
  //# sourceMappingURL=ToolFunction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolFunction.d.ts","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAA0C,MAAM,mBAAmB,CAAC;AAK/F;;;GAGG;AACH,8BAAsB,YAAa,SAAQ,QAAQ;IAEjD;;;;;OAKG;IACH,SAAS,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;IAczC;;;;OAIG;YACW,gBAAgB;YA2BhB,mBAAmB;CAalC"}
1
+ {"version":3,"file":"ToolFunction.d.ts","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAmB,MAAM,mBAAmB,CAAC;AAGxE;;;GAGG;AACH,8BAAsB,YAAa,SAAQ,QAAQ;IAEjD;;;;;OAKG;IACH,SAAS,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;IAezC;;;;;;;;OAQG;IACH,SAAS,CAAC,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;CAG7D"}
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ToolFunction = void 0;
4
4
  const app_sdk_1 = require("@zaiusinc/app-sdk");
5
5
  const Service_1 = require("../service/Service");
6
- const TokenVerifier_1 = require("../auth/TokenVerifier");
7
6
  /**
8
7
  * Abstract base class for tool-based function execution
9
8
  * Provides a standard interface for processing requests through registered tools
@@ -25,7 +24,8 @@ class ToolFunction extends app_sdk_1.Function {
25
24
  */
26
25
  async perform() {
27
26
  (0, app_sdk_1.amendLogContext)({ opalThreadId: this.request.headers.get('x-opal-thread-id') || '' });
28
- if (!(await this.authorizeRequest())) {
27
+ const bearerToken = Service_1.toolsService.extractBearerToken(this.request.headers);
28
+ if (bearerToken && !this.validateBearerToken(bearerToken)) {
29
29
  return new app_sdk_1.Response(403, { error: 'Forbidden' });
30
30
  }
31
31
  if (this.request.path === '/ready') {
@@ -36,45 +36,16 @@ class ToolFunction extends app_sdk_1.Function {
36
36
  return Service_1.toolsService.processRequest(this.request, this);
37
37
  }
38
38
  /**
39
- * Authenticate the incoming request by validating the OptiID token and organization ID
39
+ * Validates the bearer token for authorization.
40
40
  *
41
- * @throws true if authentication succeeds
41
+ * This method provides a default implementation that accepts all tokens.
42
+ * Subclasses can override this method to implement custom bearer token validation logic.
43
+ *
44
+ * @param _bearerToken - The bearer token extracted from the Authorization header
45
+ * @returns true if the token is valid and the request should proceed, false to return 403 Forbidden
42
46
  */
43
- async authorizeRequest() {
44
- if (this.request.path === '/discovery' || this.request.path === '/ready') {
45
- return true;
46
- }
47
- app_sdk_1.logger.debug('Authorizing request:', this.request.bodyJSON);
48
- const authData = this.request.bodyJSON?.auth;
49
- const accessToken = authData?.credentials?.access_token;
50
- if (!accessToken || authData?.provider?.toLowerCase() !== 'optiid') {
51
- app_sdk_1.logger.error('OptiID token is required but not provided');
52
- return false;
53
- }
54
- const customerId = authData.credentials?.customer_id;
55
- if (!customerId) {
56
- app_sdk_1.logger.error('Organisation ID is required but not provided');
57
- return false;
58
- }
59
- const appOrganisationId = (0, app_sdk_1.getAppContext)().account.organizationId;
60
- if (customerId !== appOrganisationId) {
61
- app_sdk_1.logger.error(`Invalid organisation ID: expected ${appOrganisationId}, received ${customerId}`);
62
- return false;
63
- }
64
- return await this.validateAccessToken(accessToken);
65
- }
66
- async validateAccessToken(accessToken) {
67
- try {
68
- if (!accessToken) {
69
- return false;
70
- }
71
- const tokenVerifier = await (0, TokenVerifier_1.getTokenVerifier)();
72
- return await tokenVerifier.verify(accessToken);
73
- }
74
- catch (error) {
75
- app_sdk_1.logger.error('OptiID token validation failed:', error);
76
- return false;
77
- }
47
+ validateBearerToken(_bearerToken) {
48
+ return true;
78
49
  }
79
50
  }
80
51
  exports.ToolFunction = ToolFunction;
@@ -1 +1 @@
1
- {"version":3,"file":"ToolFunction.js","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ToolFunction.js","sourceRoot":"","sources":["../../src/function/ToolFunction.ts"],"names":[],"mappings":";;;AAAA,+CAAwE;AACxE,gDAAkD;AAElD;;;GAGG;AACH,MAAsB,YAAa,SAAQ,kBAAQ;IAEjD;;;;;OAKG;IACO,KAAK;QACb,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAO;QAClB,IAAA,yBAAe,EAAC,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtF,MAAM,WAAW,GAAG,sBAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC1D,OAAO,IAAI,kBAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACnC,OAAO,IAAI,kBAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,4EAA4E;QAC5E,OAAO,sBAAY,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;OAQG;IACO,mBAAmB,CAAC,YAAoB;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA5CD,oCA4CC"}