@optimizely-opal/opal-tool-ocp-sdk 0.0.0-OCP-1487.5 → 0.0.0-OCP-1487.7

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.
@@ -3,64 +3,115 @@ import { getTokenVerifier } from './TokenVerifier';
3
3
  import { OptiIdAuthData } from '../types/Models';
4
4
 
5
5
  /**
6
- * Common authentication utilities for all function types
6
+ * Validate the OptiID access token
7
+ *
8
+ * @param accessToken - The access token to validate
9
+ * @returns true if the token is valid
7
10
  */
8
- export class AuthUtils {
9
-
10
- /**
11
- * Validate the OptiID access token
12
- *
13
- * @param accessToken - The access token to validate
14
- * @returns true if the token is valid
15
- */
16
- public static async validateAccessToken(accessToken: string | undefined): Promise<boolean> {
17
- try {
18
- if (!accessToken) {
19
- return false;
20
- }
21
- const tokenVerifier = await getTokenVerifier();
22
- return await tokenVerifier.verify(accessToken);
23
- } catch (error) {
24
- logger.error('OptiID token validation failed:', error);
11
+ async function validateAccessToken(accessToken: string | undefined): Promise<boolean> {
12
+ try {
13
+ if (!accessToken) {
25
14
  return false;
26
15
  }
16
+ const tokenVerifier = await getTokenVerifier();
17
+ return await tokenVerifier.verify(accessToken);
18
+ } catch (error) {
19
+ logger.error('OptiID token validation failed:', error);
20
+ return false;
27
21
  }
22
+ }
28
23
 
29
- /**
30
- * Extract and validate basic OptiID authentication data from request
31
- *
32
- * @param request - The incoming request
33
- * @returns object with authData and accessToken, or null if invalid
34
- */
35
- public static extractAuthData(request: any): { authData: OptiIdAuthData; accessToken: string } | null {
36
- const authData = request?.bodyJSON?.auth as OptiIdAuthData;
37
- const accessToken = authData?.credentials?.access_token;
38
- if (!accessToken || authData?.provider?.toLowerCase() !== 'optiid') {
39
- logger.error('OptiID token is required but not provided');
40
- return null;
41
- }
24
+ /**
25
+ * Extract and validate basic OptiID authentication data from request
26
+ *
27
+ * @param request - The incoming request
28
+ * @returns object with authData and accessToken, or null if invalid
29
+ */
30
+ function extractAuthData(request: any): { authData: OptiIdAuthData; accessToken: string } | null {
31
+ const authData = request?.bodyJSON?.auth as OptiIdAuthData;
32
+ const accessToken = authData?.credentials?.access_token;
33
+ if (!accessToken || authData?.provider?.toLowerCase() !== 'optiid') {
34
+ logger.error('OptiID token is required but not provided');
35
+ return null;
36
+ }
37
+
38
+ return { authData, accessToken };
39
+ }
40
+
41
+ /**
42
+ * Validate organization ID matches the app context
43
+ *
44
+ * @param customerId - The customer ID from the auth data
45
+ * @returns true if the organization ID is valid
46
+ */
47
+ function validateOrganizationId(customerId: string | undefined): boolean {
48
+ if (!customerId) {
49
+ logger.error('Organisation ID is required but not provided');
50
+ return false;
51
+ }
42
52
 
43
- return { authData, accessToken };
53
+ const appOrganisationId = getAppContext()?.account?.organizationId;
54
+ if (customerId !== appOrganisationId) {
55
+ logger.error(`Invalid organisation ID: expected ${appOrganisationId}, received ${customerId}`);
56
+ return false;
44
57
  }
45
58
 
46
- /**
47
- * Validate organization ID matches the app context
48
- *
49
- * @param customerId - The customer ID from the auth data
50
- * @returns true if the organization ID is valid
51
- */
52
- public static validateOrganizationId(customerId: string | undefined): boolean {
53
- if (!customerId) {
54
- logger.error('Organisation ID is required but not provided');
55
- return false;
56
- }
59
+ return true;
60
+ }
57
61
 
58
- const appOrganisationId = getAppContext()?.account?.organizationId;
59
- if (customerId !== appOrganisationId) {
60
- logger.error(`Invalid organisation ID: expected ${appOrganisationId}, received ${customerId}`);
61
- return false;
62
- }
62
+ /**
63
+ * Check if a request should skip authentication (discovery/ready endpoints)
64
+ *
65
+ * @param request - The incoming request
66
+ * @returns true if auth should be skipped
67
+ */
68
+ function shouldSkipAuth(request: any): boolean {
69
+ return request.path === '/discovery' || request.path === '/ready';
70
+ }
63
71
 
72
+ /**
73
+ * Core authentication flow - extracts auth data and validates token
74
+ *
75
+ * @param request - The incoming request
76
+ * @param validateOrg - Whether to validate organization ID
77
+ * @returns true if authentication succeeds
78
+ */
79
+ async function authenticateRequest(request: any, validateOrg: boolean = false): Promise<boolean> {
80
+ if (shouldSkipAuth(request)) {
64
81
  return true;
65
82
  }
83
+
84
+ const authInfo = extractAuthData(request);
85
+ if (!authInfo) {
86
+ return false;
87
+ }
88
+
89
+ const { authData, accessToken } = authInfo;
90
+
91
+ // Validate organization ID if required
92
+ if (validateOrg && !validateOrganizationId(authData.credentials?.customer_id)) {
93
+ return false;
94
+ }
95
+
96
+ return await validateAccessToken(accessToken);
97
+ }
98
+
99
+ /**
100
+ * Authenticate a request for regular functions (with organization validation)
101
+ *
102
+ * @param request - The incoming request
103
+ * @returns true if authentication and authorization succeed
104
+ */
105
+ export async function authenticateRegularRequest(request: any): Promise<boolean> {
106
+ return await authenticateRequest(request, true);
107
+ }
108
+
109
+ /**
110
+ * Authenticate a request for global functions (without organization validation)
111
+ *
112
+ * @param request - The incoming request
113
+ * @returns true if authentication succeeds
114
+ */
115
+ export async function authenticateGlobalRequest(request: any): Promise<boolean> {
116
+ return await authenticateRequest(request, false);
66
117
  }
@@ -1,5 +1,5 @@
1
1
  import { GlobalFunction, Response, amendLogContext } from '@zaiusinc/app-sdk';
2
- import { AuthUtils } from '../auth/AuthUtils';
2
+ import { authenticateGlobalRequest } from '../auth/AuthUtils';
3
3
  import { toolsService } from '../service/Service';
4
4
 
5
5
  /**
@@ -41,21 +41,9 @@ export abstract class GlobalToolFunction extends GlobalFunction {
41
41
  /**
42
42
  * Authenticate the incoming request by validating only the OptiID token
43
43
  *
44
- * @param request - The incoming request
45
44
  * @returns true if authentication succeeds
46
45
  */
47
46
  private async authorizeRequest(): Promise<boolean> {
48
- if (this.request.path === '/discovery' || this.request.path === '/ready') {
49
- return true;
50
- }
51
-
52
- const authInfo = AuthUtils.extractAuthData(this.request);
53
- if (!authInfo) {
54
- return false;
55
- }
56
-
57
- const { accessToken } = authInfo;
58
-
59
- return await AuthUtils.validateAccessToken(accessToken);
47
+ return await authenticateGlobalRequest(this.request);
60
48
  }
61
49
  }
@@ -1,5 +1,5 @@
1
1
  import { Function, Response, amendLogContext } from '@zaiusinc/app-sdk';
2
- import { AuthUtils } from '../auth/AuthUtils';
2
+ import { authenticateRegularRequest } from '../auth/AuthUtils';
3
3
  import { toolsService } from '../service/Service';
4
4
 
5
5
  /**
@@ -40,25 +40,9 @@ export abstract class ToolFunction extends Function {
40
40
  /**
41
41
  * Authenticate the incoming request by validating the OptiID token and organization ID
42
42
  *
43
- * @param request - The incoming request
44
43
  * @returns true if authentication succeeds
45
44
  */
46
45
  private async authorizeRequest(): Promise<boolean> {
47
- if (this.request.path === '/discovery' || this.request.path === '/ready') {
48
- return true;
49
- }
50
-
51
- const authInfo = AuthUtils.extractAuthData(this.request);
52
- if (!authInfo) {
53
- return false;
54
- }
55
-
56
- const { authData, accessToken } = authInfo;
57
-
58
- if (!AuthUtils.validateOrganizationId(authData.credentials?.customer_id)) {
59
- return false;
60
- }
61
-
62
- return await AuthUtils.validateAccessToken(accessToken);
46
+ return await authenticateRegularRequest(this.request);
63
47
  }
64
48
  }