@centrali-io/centrali-sdk 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +107 -0
- package/index.ts +201 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1582,6 +1582,84 @@ class CentraliSDK {
|
|
|
1582
1582
|
return this.request('GET', path, null, queryParams);
|
|
1583
1583
|
});
|
|
1584
1584
|
}
|
|
1585
|
+
// ------------------ Authorization API Methods (BYOT) ------------------
|
|
1586
|
+
/**
|
|
1587
|
+
* Check if an action is authorized for an external token.
|
|
1588
|
+
*
|
|
1589
|
+
* Use this method when you want to authorize access using tokens from your
|
|
1590
|
+
* own identity provider (Clerk, Auth0, Okta, etc.) instead of Centrali's
|
|
1591
|
+
* built-in authentication.
|
|
1592
|
+
*
|
|
1593
|
+
* **Use Cases:**
|
|
1594
|
+
* 1. **AuthZ-as-a-Service**: Define custom resources (orders, invoices) in Centrali
|
|
1595
|
+
* and use it purely for authorization decisions.
|
|
1596
|
+
* 2. **External IdP for Centrali resources**: Access Centrali data (records, files)
|
|
1597
|
+
* using your corporate IdP tokens.
|
|
1598
|
+
*
|
|
1599
|
+
* **Prerequisites:**
|
|
1600
|
+
* - Configure an External Auth Provider in Centrali Console (Settings → External Auth)
|
|
1601
|
+
* - Define claim mappings to extract attributes from your JWT
|
|
1602
|
+
* - Create policies that reference the extracted attributes (prefixed with `ext_`)
|
|
1603
|
+
*
|
|
1604
|
+
* @example
|
|
1605
|
+
* // Simple authorization check
|
|
1606
|
+
* const result = await client.checkAuthorization({
|
|
1607
|
+
* token: clerkJWT,
|
|
1608
|
+
* resource: 'orders',
|
|
1609
|
+
* action: 'read'
|
|
1610
|
+
* });
|
|
1611
|
+
*
|
|
1612
|
+
* if (result.data.allowed) {
|
|
1613
|
+
* // Proceed with the action
|
|
1614
|
+
* }
|
|
1615
|
+
*
|
|
1616
|
+
* @example
|
|
1617
|
+
* // Authorization with context for policy evaluation
|
|
1618
|
+
* const result = await client.checkAuthorization({
|
|
1619
|
+
* token: clerkJWT,
|
|
1620
|
+
* resource: 'orders',
|
|
1621
|
+
* action: 'approve',
|
|
1622
|
+
* context: {
|
|
1623
|
+
* orderId: 'order-123',
|
|
1624
|
+
* orderAmount: 50000,
|
|
1625
|
+
* department: 'sales'
|
|
1626
|
+
* }
|
|
1627
|
+
* });
|
|
1628
|
+
*
|
|
1629
|
+
* // Policy can check: ext_role == 'manager' AND request_metadata.orderAmount > 10000
|
|
1630
|
+
*
|
|
1631
|
+
* @param options - Authorization check options
|
|
1632
|
+
* @returns Promise resolving to the authorization result
|
|
1633
|
+
*/
|
|
1634
|
+
checkAuthorization(options) {
|
|
1635
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1636
|
+
const { token, resource, action, resourceCategory = 'custom', context } = options;
|
|
1637
|
+
const path = `/workspace/${this.options.workspaceId}/api/v1/access/evaluate`;
|
|
1638
|
+
const body = {
|
|
1639
|
+
action,
|
|
1640
|
+
resource_name: resource,
|
|
1641
|
+
resource_category: resourceCategory,
|
|
1642
|
+
request_data: context ? { request_metadata: context } : undefined
|
|
1643
|
+
};
|
|
1644
|
+
// Make request with the external token
|
|
1645
|
+
const response = yield this.axios.request({
|
|
1646
|
+
method: 'POST',
|
|
1647
|
+
url: path,
|
|
1648
|
+
data: body,
|
|
1649
|
+
headers: {
|
|
1650
|
+
'Authorization': `Bearer ${token}`,
|
|
1651
|
+
'Content-Type': 'application/json'
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
return {
|
|
1655
|
+
data: {
|
|
1656
|
+
allowed: response.data.response === 'allow',
|
|
1657
|
+
decision: response.data.response,
|
|
1658
|
+
message: response.data.message
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1585
1663
|
}
|
|
1586
1664
|
exports.CentraliSDK = CentraliSDK;
|
|
1587
1665
|
/**
|
|
@@ -1675,5 +1753,34 @@ exports.CentraliSDK = CentraliSDK;
|
|
|
1675
1753
|
* structures: ['users', 'orders'],
|
|
1676
1754
|
* limit: 50
|
|
1677
1755
|
* });
|
|
1756
|
+
*
|
|
1757
|
+
* // ---- Authorization (BYOT - Bring Your Own Token) ----
|
|
1758
|
+
*
|
|
1759
|
+
* // Simple authorization check with external IdP token:
|
|
1760
|
+
* const authResult = await client.checkAuthorization({
|
|
1761
|
+
* token: clerkJWT, // Token from Clerk, Auth0, Okta, etc.
|
|
1762
|
+
* resource: 'orders',
|
|
1763
|
+
* action: 'read'
|
|
1764
|
+
* });
|
|
1765
|
+
*
|
|
1766
|
+
* if (authResult.data.allowed) {
|
|
1767
|
+
* console.log('Access granted');
|
|
1768
|
+
* } else {
|
|
1769
|
+
* console.log('Access denied:', authResult.data.message);
|
|
1770
|
+
* }
|
|
1771
|
+
*
|
|
1772
|
+
* // Authorization with context for policy evaluation:
|
|
1773
|
+
* const approveResult = await client.checkAuthorization({
|
|
1774
|
+
* token: clerkJWT,
|
|
1775
|
+
* resource: 'orders',
|
|
1776
|
+
* action: 'approve',
|
|
1777
|
+
* context: {
|
|
1778
|
+
* orderId: 'order-123',
|
|
1779
|
+
* orderAmount: 50000,
|
|
1780
|
+
* department: 'sales'
|
|
1781
|
+
* }
|
|
1782
|
+
* });
|
|
1783
|
+
* // Policy can reference: ext_role, ext_department (from JWT claims)
|
|
1784
|
+
* // and request_metadata.orderId, request_metadata.orderAmount (from context)
|
|
1678
1785
|
*```
|
|
1679
1786
|
*/
|
package/index.ts
CHANGED
|
@@ -412,6 +412,90 @@ export interface ApiResponse<T> {
|
|
|
412
412
|
updatedAt?: string;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
// =====================================================
|
|
416
|
+
// Authorization Types (BYOT - Bring Your Own Token)
|
|
417
|
+
// =====================================================
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Resource category for authorization.
|
|
421
|
+
* - 'workspace': Workspace-level resources (e.g., settings, members)
|
|
422
|
+
* - 'structure': Structure-level resources (e.g., specific records)
|
|
423
|
+
* - 'custom': Custom resources defined by the user for AuthZ-as-a-Service
|
|
424
|
+
*/
|
|
425
|
+
export type ResourceCategory = 'workspace' | 'structure' | 'custom';
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Options for authorization check.
|
|
429
|
+
* Use this when authorizing access using an external IdP token (BYOT).
|
|
430
|
+
*/
|
|
431
|
+
export interface CheckAuthorizationOptions {
|
|
432
|
+
/**
|
|
433
|
+
* The JWT token from your external identity provider (e.g., Clerk, Auth0, Okta).
|
|
434
|
+
* The token will be validated against the configured external auth provider.
|
|
435
|
+
*/
|
|
436
|
+
token: string;
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* The resource being accessed.
|
|
440
|
+
* Can be a Centrali system resource (e.g., 'records', 'files') or a custom
|
|
441
|
+
* resource you've defined for AuthZ-as-a-Service (e.g., 'orders', 'invoices').
|
|
442
|
+
*/
|
|
443
|
+
resource: string;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* The action being performed on the resource.
|
|
447
|
+
* Common actions: 'create', 'read', 'update', 'delete', 'admin'
|
|
448
|
+
* You can also define custom actions (e.g., 'approve', 'publish').
|
|
449
|
+
*/
|
|
450
|
+
action: string;
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Resource category for authorization evaluation.
|
|
454
|
+
* - 'workspace': Workspace-level resources
|
|
455
|
+
* - 'structure': Structure-level resources
|
|
456
|
+
* - 'custom': Custom resources for AuthZ-as-a-Service
|
|
457
|
+
* @default 'custom'
|
|
458
|
+
*/
|
|
459
|
+
resourceCategory?: ResourceCategory;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Optional context data for policy evaluation.
|
|
463
|
+
* This data becomes available as `request_metadata` in policies.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* // Policy can reference: request_metadata.orderId, request_metadata.amount
|
|
467
|
+
* context: {
|
|
468
|
+
* orderId: 'order-123',
|
|
469
|
+
* amount: 50000,
|
|
470
|
+
* department: 'sales'
|
|
471
|
+
* }
|
|
472
|
+
*/
|
|
473
|
+
context?: Record<string, unknown>;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Result of an authorization check.
|
|
478
|
+
*/
|
|
479
|
+
export interface AuthorizationResult {
|
|
480
|
+
/**
|
|
481
|
+
* Whether the action is allowed.
|
|
482
|
+
*/
|
|
483
|
+
allowed: boolean;
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* The decision from the policy evaluator.
|
|
487
|
+
* - 'allow': Access granted
|
|
488
|
+
* - 'deny': Access denied
|
|
489
|
+
* - 'not_applicable': No matching policy found
|
|
490
|
+
*/
|
|
491
|
+
decision: 'allow' | 'deny' | 'not_applicable';
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Human-readable message explaining the decision.
|
|
495
|
+
*/
|
|
496
|
+
message?: string;
|
|
497
|
+
}
|
|
498
|
+
|
|
415
499
|
// =====================================================
|
|
416
500
|
// Trigger Types
|
|
417
501
|
// =====================================================
|
|
@@ -2713,6 +2797,94 @@ export class CentraliSDK {
|
|
|
2713
2797
|
return this.request<SearchResponse>('GET', path, null, queryParams);
|
|
2714
2798
|
}
|
|
2715
2799
|
|
|
2800
|
+
// ------------------ Authorization API Methods (BYOT) ------------------
|
|
2801
|
+
|
|
2802
|
+
/**
|
|
2803
|
+
* Check if an action is authorized for an external token.
|
|
2804
|
+
*
|
|
2805
|
+
* Use this method when you want to authorize access using tokens from your
|
|
2806
|
+
* own identity provider (Clerk, Auth0, Okta, etc.) instead of Centrali's
|
|
2807
|
+
* built-in authentication.
|
|
2808
|
+
*
|
|
2809
|
+
* **Use Cases:**
|
|
2810
|
+
* 1. **AuthZ-as-a-Service**: Define custom resources (orders, invoices) in Centrali
|
|
2811
|
+
* and use it purely for authorization decisions.
|
|
2812
|
+
* 2. **External IdP for Centrali resources**: Access Centrali data (records, files)
|
|
2813
|
+
* using your corporate IdP tokens.
|
|
2814
|
+
*
|
|
2815
|
+
* **Prerequisites:**
|
|
2816
|
+
* - Configure an External Auth Provider in Centrali Console (Settings → External Auth)
|
|
2817
|
+
* - Define claim mappings to extract attributes from your JWT
|
|
2818
|
+
* - Create policies that reference the extracted attributes (prefixed with `ext_`)
|
|
2819
|
+
*
|
|
2820
|
+
* @example
|
|
2821
|
+
* // Simple authorization check
|
|
2822
|
+
* const result = await client.checkAuthorization({
|
|
2823
|
+
* token: clerkJWT,
|
|
2824
|
+
* resource: 'orders',
|
|
2825
|
+
* action: 'read'
|
|
2826
|
+
* });
|
|
2827
|
+
*
|
|
2828
|
+
* if (result.data.allowed) {
|
|
2829
|
+
* // Proceed with the action
|
|
2830
|
+
* }
|
|
2831
|
+
*
|
|
2832
|
+
* @example
|
|
2833
|
+
* // Authorization with context for policy evaluation
|
|
2834
|
+
* const result = await client.checkAuthorization({
|
|
2835
|
+
* token: clerkJWT,
|
|
2836
|
+
* resource: 'orders',
|
|
2837
|
+
* action: 'approve',
|
|
2838
|
+
* context: {
|
|
2839
|
+
* orderId: 'order-123',
|
|
2840
|
+
* orderAmount: 50000,
|
|
2841
|
+
* department: 'sales'
|
|
2842
|
+
* }
|
|
2843
|
+
* });
|
|
2844
|
+
*
|
|
2845
|
+
* // Policy can check: ext_role == 'manager' AND request_metadata.orderAmount > 10000
|
|
2846
|
+
*
|
|
2847
|
+
* @param options - Authorization check options
|
|
2848
|
+
* @returns Promise resolving to the authorization result
|
|
2849
|
+
*/
|
|
2850
|
+
public async checkAuthorization(
|
|
2851
|
+
options: CheckAuthorizationOptions
|
|
2852
|
+
): Promise<ApiResponse<AuthorizationResult>> {
|
|
2853
|
+
const { token, resource, action, resourceCategory = 'custom', context } = options;
|
|
2854
|
+
|
|
2855
|
+
const path = `/workspace/${this.options.workspaceId}/api/v1/access/evaluate`;
|
|
2856
|
+
|
|
2857
|
+
const body = {
|
|
2858
|
+
action,
|
|
2859
|
+
resource_name: resource,
|
|
2860
|
+
resource_category: resourceCategory,
|
|
2861
|
+
request_data: context ? { request_metadata: context } : undefined
|
|
2862
|
+
};
|
|
2863
|
+
|
|
2864
|
+
// Make request with the external token
|
|
2865
|
+
const response = await this.axios.request<{
|
|
2866
|
+
status: string;
|
|
2867
|
+
response: 'allow' | 'deny' | 'not_applicable';
|
|
2868
|
+
message?: string;
|
|
2869
|
+
}>({
|
|
2870
|
+
method: 'POST',
|
|
2871
|
+
url: path,
|
|
2872
|
+
data: body,
|
|
2873
|
+
headers: {
|
|
2874
|
+
'Authorization': `Bearer ${token}`,
|
|
2875
|
+
'Content-Type': 'application/json'
|
|
2876
|
+
}
|
|
2877
|
+
});
|
|
2878
|
+
|
|
2879
|
+
return {
|
|
2880
|
+
data: {
|
|
2881
|
+
allowed: response.data.response === 'allow',
|
|
2882
|
+
decision: response.data.response,
|
|
2883
|
+
message: response.data.message
|
|
2884
|
+
}
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2716
2888
|
}
|
|
2717
2889
|
|
|
2718
2890
|
/**
|
|
@@ -2806,5 +2978,34 @@ export class CentraliSDK {
|
|
|
2806
2978
|
* structures: ['users', 'orders'],
|
|
2807
2979
|
* limit: 50
|
|
2808
2980
|
* });
|
|
2981
|
+
*
|
|
2982
|
+
* // ---- Authorization (BYOT - Bring Your Own Token) ----
|
|
2983
|
+
*
|
|
2984
|
+
* // Simple authorization check with external IdP token:
|
|
2985
|
+
* const authResult = await client.checkAuthorization({
|
|
2986
|
+
* token: clerkJWT, // Token from Clerk, Auth0, Okta, etc.
|
|
2987
|
+
* resource: 'orders',
|
|
2988
|
+
* action: 'read'
|
|
2989
|
+
* });
|
|
2990
|
+
*
|
|
2991
|
+
* if (authResult.data.allowed) {
|
|
2992
|
+
* console.log('Access granted');
|
|
2993
|
+
* } else {
|
|
2994
|
+
* console.log('Access denied:', authResult.data.message);
|
|
2995
|
+
* }
|
|
2996
|
+
*
|
|
2997
|
+
* // Authorization with context for policy evaluation:
|
|
2998
|
+
* const approveResult = await client.checkAuthorization({
|
|
2999
|
+
* token: clerkJWT,
|
|
3000
|
+
* resource: 'orders',
|
|
3001
|
+
* action: 'approve',
|
|
3002
|
+
* context: {
|
|
3003
|
+
* orderId: 'order-123',
|
|
3004
|
+
* orderAmount: 50000,
|
|
3005
|
+
* department: 'sales'
|
|
3006
|
+
* }
|
|
3007
|
+
* });
|
|
3008
|
+
* // Policy can reference: ext_role, ext_department (from JWT claims)
|
|
3009
|
+
* // and request_metadata.orderId, request_metadata.orderAmount (from context)
|
|
2809
3010
|
*```
|
|
2810
3011
|
*/
|