@optimizely-opal/opal-tool-ocp-sdk 0.0.0-beta.11 โ 0.0.0-beta.13
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/README.md +114 -55
- package/dist/auth/AuthUtils.d.ts +26 -0
- package/dist/auth/AuthUtils.d.ts.map +1 -0
- package/dist/auth/AuthUtils.js +109 -0
- package/dist/auth/AuthUtils.js.map +1 -0
- package/dist/auth/AuthUtils.test.d.ts +2 -0
- package/dist/auth/AuthUtils.test.d.ts.map +1 -0
- package/dist/auth/AuthUtils.test.js +601 -0
- package/dist/auth/AuthUtils.test.js.map +1 -0
- package/dist/auth/TokenVerifier.d.ts +31 -0
- package/dist/auth/TokenVerifier.d.ts.map +1 -0
- package/dist/auth/TokenVerifier.js +127 -0
- package/dist/auth/TokenVerifier.js.map +1 -0
- package/dist/auth/TokenVerifier.test.d.ts +2 -0
- package/dist/auth/TokenVerifier.test.d.ts.map +1 -0
- package/dist/auth/TokenVerifier.test.js +125 -0
- package/dist/auth/TokenVerifier.test.js.map +1 -0
- package/dist/function/GlobalToolFunction.d.ts +27 -0
- package/dist/function/GlobalToolFunction.d.ts.map +1 -0
- package/dist/function/GlobalToolFunction.js +53 -0
- package/dist/function/GlobalToolFunction.js.map +1 -0
- package/dist/function/GlobalToolFunction.test.d.ts +2 -0
- package/dist/function/GlobalToolFunction.test.d.ts.map +1 -0
- package/dist/function/GlobalToolFunction.test.js +425 -0
- package/dist/function/GlobalToolFunction.test.js.map +1 -0
- package/dist/function/ToolFunction.d.ts +3 -7
- package/dist/function/ToolFunction.d.ts.map +1 -1
- package/dist/function/ToolFunction.js +6 -10
- package/dist/function/ToolFunction.js.map +1 -1
- package/dist/function/ToolFunction.test.js +177 -196
- package/dist/function/ToolFunction.test.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/service/Service.d.ts +14 -13
- package/dist/service/Service.d.ts.map +1 -1
- package/dist/service/Service.js +22 -16
- package/dist/service/Service.js.map +1 -1
- package/dist/service/Service.test.js +8 -3
- package/dist/service/Service.test.js.map +1 -1
- package/dist/types/Models.d.ts +5 -5
- package/dist/types/Models.d.ts.map +1 -1
- package/dist/types/Models.js +9 -9
- package/dist/types/Models.js.map +1 -1
- package/package.json +4 -3
- package/src/auth/AuthUtils.test.ts +729 -0
- package/src/auth/AuthUtils.ts +117 -0
- package/src/auth/TokenVerifier.test.ts +165 -0
- package/src/auth/TokenVerifier.ts +145 -0
- package/src/function/GlobalToolFunction.test.ts +505 -0
- package/src/function/GlobalToolFunction.ts +56 -0
- package/src/function/ToolFunction.test.ts +194 -214
- package/src/function/ToolFunction.ts +6 -10
- package/src/index.ts +2 -0
- package/src/service/Service.test.ts +8 -3
- package/src/service/Service.ts +53 -24
- package/src/types/Models.ts +4 -4
package/README.md
CHANGED
|
@@ -7,10 +7,11 @@ A TypeScript SDK for building Opal tools in Optimizely Connect Platform. This SD
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- ๐ฏ **Decorator-based Tool Registration** - Use `@tool` and `@interaction` decorators to easily register functions
|
|
10
|
+
- ๐ **Global and Regular Function Modes** - SDK can be used in either global or organization-scoped mode
|
|
10
11
|
- ๐ง **Type-safe Development** - Full TypeScript support with comprehensive type definitions
|
|
11
|
-
- ๐๏ธ **Abstract Base Classes** - Extend `ToolFunction` for standardized request processing
|
|
12
|
+
- ๐๏ธ **Abstract Base Classes** - Extend `ToolFunction` or `GlobalToolFunction` for standardized request processing
|
|
12
13
|
- ๐ **Authentication Support** - OptiID authentication
|
|
13
|
-
- ๐ก๏ธ **Authorization Support** -
|
|
14
|
+
- ๐ก๏ธ **Authorization Support** - OptiID token tool authorization
|
|
14
15
|
- ๐ **Parameter Validation** - Define and validate tool parameters with types
|
|
15
16
|
- ๐งช **Comprehensive Testing** - Fully tested with Jest
|
|
16
17
|
|
|
@@ -28,7 +29,14 @@ yarn add @optimizely-opal/opal-tool-ocp-sdk
|
|
|
28
29
|
|
|
29
30
|
## Quick Start
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
The SDK supports two function modes:
|
|
33
|
+
|
|
34
|
+
- **Regular Functions** (`ToolFunction`) - Organization-scoped functions that validate customer organization IDs
|
|
35
|
+
- **Global Functions** (`GlobalToolFunction`) - Platform-wide functions that work across all organizations
|
|
36
|
+
|
|
37
|
+
### Regular Tool Function
|
|
38
|
+
|
|
39
|
+
Create a tool function class by extending `ToolFunction` for organization-scoped functionality:
|
|
32
40
|
|
|
33
41
|
```typescript
|
|
34
42
|
import { ToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-tool-ocp-sdk';
|
|
@@ -89,12 +97,12 @@ export class MyToolFunction extends ToolFunction {
|
|
|
89
97
|
throw new Error('OptiID authentication required');
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
const {
|
|
100
|
+
const { customer_id, instance_id, access_token } = authData.credentials;
|
|
93
101
|
return {
|
|
94
102
|
id: '456',
|
|
95
103
|
title: params.title,
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
customer_id,
|
|
105
|
+
instance_id
|
|
98
106
|
};
|
|
99
107
|
}
|
|
100
108
|
|
|
@@ -112,10 +120,50 @@ export class MyToolFunction extends ToolFunction {
|
|
|
112
120
|
}
|
|
113
121
|
```
|
|
114
122
|
|
|
115
|
-
|
|
123
|
+
### Global Tool Function
|
|
124
|
+
|
|
125
|
+
Create a global tool function by extending `GlobalToolFunction` for platform-wide functionality:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { GlobalToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-tool-ocp-sdk';
|
|
129
|
+
|
|
130
|
+
export class MyGlobalToolFunction extends GlobalToolFunction {
|
|
131
|
+
|
|
132
|
+
@tool({
|
|
133
|
+
name: 'global_utility',
|
|
134
|
+
description: 'A utility tool available to all organizations',
|
|
135
|
+
endpoint: '/global-utility',
|
|
136
|
+
parameters: [
|
|
137
|
+
{
|
|
138
|
+
name: 'operation',
|
|
139
|
+
type: ParameterType.String,
|
|
140
|
+
description: 'The operation to perform',
|
|
141
|
+
required: true
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
})
|
|
145
|
+
async globalUtility(params: { operation: string }, authData?: OptiIdAuthData) {
|
|
146
|
+
return {
|
|
147
|
+
result: `Performed ${params.operation} globally`,
|
|
148
|
+
organizationId: authData?.credentials.customer_id || 'unknown'
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Function Modes
|
|
155
|
+
|
|
156
|
+
The SDK operates in one of two modes based on the base class you extend:
|
|
157
|
+
|
|
158
|
+
- **Regular Function Mode** (`ToolFunction`): All tools are organization-scoped and validate organization IDs
|
|
159
|
+
- **Global Function Mode** (`GlobalToolFunction`): All tools are platform-wide.
|
|
160
|
+
|
|
161
|
+
The discovery endpoint returns all tools registered within that function mode.
|
|
162
|
+
|
|
163
|
+
Your function class inherits a `perform()` method from `ToolFunction` or `GlobalToolFunction` that serves as the main entry point for handling all incoming requests. When called, the SDK automatically:
|
|
116
164
|
|
|
117
165
|
- **Routes requests** to your registered tools and interactions based on endpoints
|
|
118
|
-
- **Handles authentication** and
|
|
166
|
+
- **Handles authentication** and OptiID token validation before calling your methods
|
|
119
167
|
- **Provides discovery** at `/discovery` endpoint for OCP platform integration
|
|
120
168
|
- **Returns proper HTTP responses** with correct status codes and JSON formatting
|
|
121
169
|
|
|
@@ -129,6 +177,28 @@ Tools are functions that can be discovered and executed through the OCP platform
|
|
|
129
177
|
- Define parameters with types and validation
|
|
130
178
|
- Can require authentication
|
|
131
179
|
- Return structured responses
|
|
180
|
+
- Are automatically registered based on the function mode you choose
|
|
181
|
+
|
|
182
|
+
### Function Modes
|
|
183
|
+
|
|
184
|
+
#### Regular Functions (`ToolFunction`)
|
|
185
|
+
|
|
186
|
+
Regular functions are scoped to specific organizations and validate that requests come from the same organization:
|
|
187
|
+
|
|
188
|
+
- Validate OptiID organization ID matches the function's organization context
|
|
189
|
+
- All tools within the function are organization-scoped
|
|
190
|
+
- **Per-Organization Configuration**: Can implement organization-specific configuration, authentication credentials, and API keys since they're tied to a single organization
|
|
191
|
+
- **Per-Organization Authentication**: Can store and use organization-specific authentication tokens, connection strings, and other sensitive data securely
|
|
192
|
+
|
|
193
|
+
#### Global Functions (`GlobalToolFunction`)
|
|
194
|
+
|
|
195
|
+
Global functions work across all organizations without organization validation:
|
|
196
|
+
|
|
197
|
+
- Accept OptiID authentication
|
|
198
|
+
- All tools within the function are platform-wide
|
|
199
|
+
- **No Per-Organization Configuration**: Cannot implement per-organization configuration since they work across all organizations
|
|
200
|
+
- **No Per-Organization Authentication**: Cannot store organization-specific credentials or authentication data
|
|
201
|
+
- **Global Discovery**: Have a global discovery URL that can be used by any organization without requiring them to install the app first
|
|
132
202
|
|
|
133
203
|
### Interactions
|
|
134
204
|
|
|
@@ -169,29 +239,19 @@ interface AuthRequirementConfig {
|
|
|
169
239
|
}
|
|
170
240
|
```
|
|
171
241
|
|
|
172
|
-
####
|
|
242
|
+
#### OptiID Token Authorization
|
|
173
243
|
|
|
174
|
-
The SDK automatically
|
|
244
|
+
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.
|
|
175
245
|
|
|
176
246
|
**Token Validation:**
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
- **
|
|
180
|
-
-
|
|
181
|
-
-
|
|
247
|
+
- The SDK extracts and validates OptiID tokens from the request body
|
|
248
|
+
- **Regular Tools**: Validation includes verifying that requests come from the same organization as the tool
|
|
249
|
+
- **Global Tools**: Token validation occurs but organization ID matching is skipped
|
|
250
|
+
- If validation fails, returns HTTP 403 Unauthorized before reaching your handler methods
|
|
251
|
+
- No additional configuration needed - validation is handled automatically
|
|
182
252
|
|
|
183
253
|
```typescript
|
|
184
254
|
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
|
-
|
|
195
255
|
@tool({
|
|
196
256
|
name: 'secure_tool',
|
|
197
257
|
description: 'Tool that validates requests from Opal',
|
|
@@ -215,15 +275,6 @@ export class MyToolFunction extends ToolFunction {
|
|
|
215
275
|
}
|
|
216
276
|
```
|
|
217
277
|
|
|
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
|
-
|
|
227
278
|
## API Reference
|
|
228
279
|
|
|
229
280
|
### Handler Function Signatures
|
|
@@ -240,7 +291,6 @@ async handlerMethod(
|
|
|
240
291
|
- **params**: The input parameters for tools, or interaction data for webhooks
|
|
241
292
|
- **authData**: Available when OptiID user authentication is configured and successful
|
|
242
293
|
|
|
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
294
|
|
|
245
295
|
### Decorators
|
|
246
296
|
|
|
@@ -273,17 +323,29 @@ interface InteractionConfig {
|
|
|
273
323
|
|
|
274
324
|
#### `ToolFunction`
|
|
275
325
|
|
|
276
|
-
Abstract base class for OCP functions:
|
|
326
|
+
Abstract base class for organization-scoped OCP functions:
|
|
277
327
|
|
|
278
328
|
```typescript
|
|
279
329
|
export abstract class ToolFunction extends Function {
|
|
280
330
|
protected ready(): Promise<boolean>;
|
|
281
331
|
public async perform(): Promise<Response>;
|
|
282
|
-
protected validateBearerToken(token: string): boolean;
|
|
283
332
|
}
|
|
284
333
|
```
|
|
285
334
|
|
|
286
|
-
Extend this class
|
|
335
|
+
Extend this class for regular tools that validate organization IDs. The `perform` method automatically routes requests to registered tools and enforces organization validation.
|
|
336
|
+
|
|
337
|
+
#### `GlobalToolFunction`
|
|
338
|
+
|
|
339
|
+
Abstract base class for global OCP functions:
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
export abstract class GlobalToolFunction extends GlobalFunction {
|
|
343
|
+
protected ready(): Promise<boolean>;
|
|
344
|
+
public async perform(): Promise<Response>;
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Extend this class for tools that work across organizations. The `perform` method routes requests to registered tools but skips organization validation for tools.
|
|
287
349
|
|
|
288
350
|
### Models
|
|
289
351
|
|
|
@@ -302,7 +364,14 @@ The SDK automatically provides two important endpoints:
|
|
|
302
364
|
|
|
303
365
|
### Discovery Endpoint (`/discovery`)
|
|
304
366
|
|
|
305
|
-
Returns all registered tools in the proper OCP format for platform integration:
|
|
367
|
+
Returns all registered tools in the proper OCP format for platform integration. The discovery endpoint returns all tools registered within the function, regardless of their individual configuration:
|
|
368
|
+
|
|
369
|
+
- **Regular Functions** (`ToolFunction`): Returns all tools with organization-scoped behavior
|
|
370
|
+
- **Global Functions** (`GlobalToolFunction`): Returns all tools with platform-wide behavior
|
|
371
|
+
|
|
372
|
+
All tools within a function operate in the same mode - there is no mixing of global and organization-scoped tools within a single function.
|
|
373
|
+
|
|
374
|
+
Example response for a regular function and global function:
|
|
306
375
|
|
|
307
376
|
```json
|
|
308
377
|
{
|
|
@@ -407,11 +476,6 @@ yarn lint
|
|
|
407
476
|
import { ToolFunction, tool, interaction, ParameterType, OptiIdAuthData, InteractionResult } from '@optimizely-opal/opal-ocp-sdk';
|
|
408
477
|
|
|
409
478
|
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
|
-
}
|
|
415
479
|
|
|
416
480
|
// OptiID authentication example
|
|
417
481
|
@tool({
|
|
@@ -424,9 +488,9 @@ export class AuthenticatedFunction extends ToolFunction {
|
|
|
424
488
|
async secureOperation(params: unknown, authData?: OptiIdAuthData) {
|
|
425
489
|
if (!authData) throw new Error('OptiID authentication required');
|
|
426
490
|
|
|
427
|
-
const {
|
|
491
|
+
const { customer_id, access_token } = authData.credentials;
|
|
428
492
|
// Use OptiID credentials for API calls
|
|
429
|
-
return { success: true,
|
|
493
|
+
return { success: true, customer_id };
|
|
430
494
|
}
|
|
431
495
|
|
|
432
496
|
// Interaction with authentication example
|
|
@@ -439,11 +503,11 @@ export class AuthenticatedFunction extends ToolFunction {
|
|
|
439
503
|
return new InteractionResult('Authentication required for webhook processing');
|
|
440
504
|
}
|
|
441
505
|
|
|
442
|
-
const {
|
|
506
|
+
const { customer_id } = authData.credentials;
|
|
443
507
|
|
|
444
508
|
// Process webhook data with authentication context
|
|
445
509
|
return new InteractionResult(
|
|
446
|
-
`Webhook processed for customer ${
|
|
510
|
+
`Webhook processed for customer ${customer_id}: ${data.eventType}`,
|
|
447
511
|
`https://app.example.com/events/${data.eventId}`
|
|
448
512
|
);
|
|
449
513
|
}
|
|
@@ -461,7 +525,8 @@ src/
|
|
|
461
525
|
โ โโโ index.ts
|
|
462
526
|
โ โโโ TaskTool.ts
|
|
463
527
|
โ โโโ NotificationTool.ts
|
|
464
|
-
|
|
528
|
+
โโโ MyToolFunction.ts
|
|
529
|
+
โโโ MyGlobalToolFunction.ts
|
|
465
530
|
```
|
|
466
531
|
|
|
467
532
|
**tools/TaskTool.ts:**
|
|
@@ -573,12 +638,6 @@ import { ToolFunction } from '@optimizely-opal/opal-ocp-sdk';
|
|
|
573
638
|
import * from './tools';
|
|
574
639
|
|
|
575
640
|
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
|
-
}
|
|
582
641
|
}
|
|
583
642
|
```
|
|
584
643
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { OptiIdAuthData } from '../types/Models';
|
|
2
|
+
/**
|
|
3
|
+
* Extract and validate basic OptiID authentication data from request
|
|
4
|
+
*
|
|
5
|
+
* @param request - The incoming request
|
|
6
|
+
* @returns object with authData and accessToken, or null if invalid
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractAuthData(request: any): {
|
|
9
|
+
authData: OptiIdAuthData;
|
|
10
|
+
accessToken: string;
|
|
11
|
+
} | null;
|
|
12
|
+
/**
|
|
13
|
+
* Authenticate a request for regular functions (with organization validation)
|
|
14
|
+
*
|
|
15
|
+
* @param request - The incoming request
|
|
16
|
+
* @returns true if authentication and authorization succeed
|
|
17
|
+
*/
|
|
18
|
+
export declare function authenticateRegularRequest(request: any): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Authenticate a request for global functions (without organization validation)
|
|
21
|
+
*
|
|
22
|
+
* @param request - The incoming request
|
|
23
|
+
* @returns true if authentication succeeds
|
|
24
|
+
*/
|
|
25
|
+
export declare function authenticateGlobalRequest(request: any): Promise<boolean>;
|
|
26
|
+
//# sourceMappingURL=AuthUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthUtils.d.ts","sourceRoot":"","sources":["../../src/auth/AuthUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAqBjD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAStG;AA4DD;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAE/E;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAE9E"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractAuthData = extractAuthData;
|
|
4
|
+
exports.authenticateRegularRequest = authenticateRegularRequest;
|
|
5
|
+
exports.authenticateGlobalRequest = authenticateGlobalRequest;
|
|
6
|
+
const app_sdk_1 = require("@zaiusinc/app-sdk");
|
|
7
|
+
const TokenVerifier_1 = require("./TokenVerifier");
|
|
8
|
+
/**
|
|
9
|
+
* Validate the OptiID access token
|
|
10
|
+
*
|
|
11
|
+
* @param accessToken - The access token to validate
|
|
12
|
+
* @returns true if the token is valid
|
|
13
|
+
*/
|
|
14
|
+
async function validateAccessToken(accessToken) {
|
|
15
|
+
try {
|
|
16
|
+
if (!accessToken) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const tokenVerifier = await (0, TokenVerifier_1.getTokenVerifier)();
|
|
20
|
+
return await tokenVerifier.verify(accessToken);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
app_sdk_1.logger.error('OptiID token validation failed:', error);
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract and validate basic OptiID authentication data from request
|
|
29
|
+
*
|
|
30
|
+
* @param request - The incoming request
|
|
31
|
+
* @returns object with authData and accessToken, or null if invalid
|
|
32
|
+
*/
|
|
33
|
+
function extractAuthData(request) {
|
|
34
|
+
const authData = request?.bodyJSON?.auth;
|
|
35
|
+
const accessToken = authData?.credentials?.access_token;
|
|
36
|
+
if (!accessToken || authData?.provider?.toLowerCase() !== 'optiid') {
|
|
37
|
+
app_sdk_1.logger.error('OptiID token is required but not provided');
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return { authData, accessToken };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate organization ID matches the app context
|
|
44
|
+
*
|
|
45
|
+
* @param customerId - The customer ID from the auth data
|
|
46
|
+
* @returns true if the organization ID is valid
|
|
47
|
+
*/
|
|
48
|
+
function validateOrganizationId(customerId) {
|
|
49
|
+
if (!customerId) {
|
|
50
|
+
app_sdk_1.logger.error('Organisation ID is required but not provided');
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const appOrganisationId = (0, app_sdk_1.getAppContext)()?.account?.organizationId;
|
|
54
|
+
if (customerId !== appOrganisationId) {
|
|
55
|
+
app_sdk_1.logger.error(`Invalid organisation ID: expected ${appOrganisationId}, received ${customerId}`);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if a request should skip authentication (discovery/ready endpoints)
|
|
62
|
+
*
|
|
63
|
+
* @param request - The incoming request
|
|
64
|
+
* @returns true if auth should be skipped
|
|
65
|
+
*/
|
|
66
|
+
function shouldSkipAuth(request) {
|
|
67
|
+
return request.path === '/discovery' || request.path === '/ready';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Core authentication flow - extracts auth data and validates token
|
|
71
|
+
*
|
|
72
|
+
* @param request - The incoming request
|
|
73
|
+
* @param validateOrg - Whether to validate organization ID
|
|
74
|
+
* @returns true if authentication succeeds
|
|
75
|
+
*/
|
|
76
|
+
async function authenticateRequest(request, validateOrg) {
|
|
77
|
+
if (shouldSkipAuth(request)) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
const authInfo = extractAuthData(request);
|
|
81
|
+
if (!authInfo) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const { authData, accessToken } = authInfo;
|
|
85
|
+
// Validate organization ID if required
|
|
86
|
+
if (validateOrg && !validateOrganizationId(authData.credentials?.customer_id)) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return await validateAccessToken(accessToken);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Authenticate a request for regular functions (with organization validation)
|
|
93
|
+
*
|
|
94
|
+
* @param request - The incoming request
|
|
95
|
+
* @returns true if authentication and authorization succeed
|
|
96
|
+
*/
|
|
97
|
+
async function authenticateRegularRequest(request) {
|
|
98
|
+
return await authenticateRequest(request, true);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Authenticate a request for global functions (without organization validation)
|
|
102
|
+
*
|
|
103
|
+
* @param request - The incoming request
|
|
104
|
+
* @returns true if authentication succeeds
|
|
105
|
+
*/
|
|
106
|
+
async function authenticateGlobalRequest(request) {
|
|
107
|
+
return await authenticateRequest(request, false);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=AuthUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthUtils.js","sourceRoot":"","sources":["../../src/auth/AuthUtils.ts"],"names":[],"mappings":";;AA6BA,0CASC;AAkED,gEAEC;AAQD,8DAEC;AApHD,+CAA0D;AAC1D,mDAAmD;AAGnD;;;;;GAKG;AACH,KAAK,UAAU,mBAAmB,CAAC,WAA+B;IAChE,IAAI,CAAC;QACH,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,IAAA,gCAAgB,GAAE,CAAC;QAC/C,OAAO,MAAM,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,OAAY;IAC1C,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAsB,CAAC;IAC3D,MAAM,WAAW,GAAG,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC;IACxD,IAAI,CAAC,WAAW,IAAI,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;QACnE,gBAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,UAA8B;IAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,gBAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAA,uBAAa,GAAE,EAAE,OAAO,EAAE,cAAc,CAAC;IACnE,IAAI,UAAU,KAAK,iBAAiB,EAAE,CAAC;QACrC,gBAAM,CAAC,KAAK,CAAC,qCAAqC,iBAAiB,cAAc,UAAU,EAAE,CAAC,CAAC;QAC/F,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAY;IAClC,OAAO,OAAO,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC;AACpE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,mBAAmB,CAAC,OAAY,EAAE,WAAoB;IACnE,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC;IAE3C,uCAAuC;IACvC,IAAI,WAAW,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QAC9E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,MAAM,mBAAmB,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,0BAA0B,CAAC,OAAY;IAC3D,OAAO,MAAM,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,yBAAyB,CAAC,OAAY;IAC1D,OAAO,MAAM,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthUtils.test.d.ts","sourceRoot":"","sources":["../../src/auth/AuthUtils.test.ts"],"names":[],"mappings":""}
|