@drmhse/sso-sdk 0.2.9 → 0.3.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.
- package/README.md +4 -4
- package/dist/index.d.mts +612 -367
- package/dist/index.d.ts +612 -367
- package/dist/index.js +229 -29
- package/dist/index.mjs +229 -29
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -147,7 +147,7 @@ var HttpClient = class {
|
|
|
147
147
|
signal: controller.signal
|
|
148
148
|
});
|
|
149
149
|
clearTimeout(timeoutId);
|
|
150
|
-
if (response.status === 401 && this.sessionManager && !options._retry && !path.includes("/auth/login")) {
|
|
150
|
+
if (response.status === 401 && this.sessionManager && !options._retry && !path.includes("/auth/login") && !path.includes("/auth/refresh")) {
|
|
151
151
|
try {
|
|
152
152
|
const newToken = await this.sessionManager.refreshSession();
|
|
153
153
|
return this.request(path, {
|
|
@@ -731,6 +731,23 @@ var AuthModule = class {
|
|
|
731
731
|
const response = await this.http.post("/api/auth/register", payload);
|
|
732
732
|
return response.data;
|
|
733
733
|
}
|
|
734
|
+
/**
|
|
735
|
+
* Verify an email address using the token from the verification email.
|
|
736
|
+
*
|
|
737
|
+
* @param token Verification token
|
|
738
|
+
* @returns HTML success page string
|
|
739
|
+
*
|
|
740
|
+
* @example
|
|
741
|
+
* ```typescript
|
|
742
|
+
* const html = await sso.auth.verifyEmail('token-from-email');
|
|
743
|
+
* ```
|
|
744
|
+
*/
|
|
745
|
+
async verifyEmail(token) {
|
|
746
|
+
const response = await this.http.get("/auth/verify-email", {
|
|
747
|
+
params: { token }
|
|
748
|
+
});
|
|
749
|
+
return response.data;
|
|
750
|
+
}
|
|
734
751
|
/**
|
|
735
752
|
* Login with email and password.
|
|
736
753
|
* Automatically persists the session and configures the client.
|
|
@@ -1490,6 +1507,43 @@ var WebhooksModule = class {
|
|
|
1490
1507
|
var OrganizationsModule = class {
|
|
1491
1508
|
constructor(http) {
|
|
1492
1509
|
this.http = http;
|
|
1510
|
+
/**
|
|
1511
|
+
* SCIM token management methods
|
|
1512
|
+
*/
|
|
1513
|
+
this.scim = {
|
|
1514
|
+
/**
|
|
1515
|
+
* Create a new SCIM token.
|
|
1516
|
+
* The token is only returned once upon creation.
|
|
1517
|
+
*/
|
|
1518
|
+
createToken: async (orgSlug, payload) => {
|
|
1519
|
+
const response = await this.http.post(
|
|
1520
|
+
`/api/organizations/${orgSlug}/scim-tokens`,
|
|
1521
|
+
payload
|
|
1522
|
+
);
|
|
1523
|
+
return response.data;
|
|
1524
|
+
},
|
|
1525
|
+
/**
|
|
1526
|
+
* List all SCIM tokens.
|
|
1527
|
+
*/
|
|
1528
|
+
listTokens: async (orgSlug) => {
|
|
1529
|
+
const response = await this.http.get(
|
|
1530
|
+
`/api/organizations/${orgSlug}/scim-tokens`
|
|
1531
|
+
);
|
|
1532
|
+
return response.data;
|
|
1533
|
+
},
|
|
1534
|
+
/**
|
|
1535
|
+
* Revoke a SCIM token.
|
|
1536
|
+
*/
|
|
1537
|
+
revokeToken: async (orgSlug, tokenId) => {
|
|
1538
|
+
await this.http.post(`/api/organizations/${orgSlug}/scim-tokens/${tokenId}/revoke`);
|
|
1539
|
+
},
|
|
1540
|
+
/**
|
|
1541
|
+
* Delete a SCIM token.
|
|
1542
|
+
*/
|
|
1543
|
+
deleteToken: async (orgSlug, tokenId) => {
|
|
1544
|
+
await this.http.delete(`/api/organizations/${orgSlug}/scim-tokens/${tokenId}`);
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1493
1547
|
/**
|
|
1494
1548
|
* Member management methods
|
|
1495
1549
|
*/
|
|
@@ -1513,6 +1567,24 @@ var OrganizationsModule = class {
|
|
|
1513
1567
|
);
|
|
1514
1568
|
return response.data;
|
|
1515
1569
|
},
|
|
1570
|
+
/**
|
|
1571
|
+
* Add a member to the organization (Invite + Accept).
|
|
1572
|
+
* This is a convenience method that creates an invitation and immediately accepts it.
|
|
1573
|
+
* Useful for testing and admin operations.
|
|
1574
|
+
*
|
|
1575
|
+
* @param orgSlug Organization slug
|
|
1576
|
+
* @param payload Member details (email, role)
|
|
1577
|
+
* @returns The created invitation
|
|
1578
|
+
*/
|
|
1579
|
+
add: async (orgSlug, payload) => {
|
|
1580
|
+
const response = await this.http.post(
|
|
1581
|
+
`/api/organizations/${orgSlug}/invitations`,
|
|
1582
|
+
payload
|
|
1583
|
+
);
|
|
1584
|
+
const invitation = response.data;
|
|
1585
|
+
await this.http.post("/api/invitations/accept", { token: invitation.token });
|
|
1586
|
+
return invitation;
|
|
1587
|
+
},
|
|
1516
1588
|
/**
|
|
1517
1589
|
* Update a member's role.
|
|
1518
1590
|
* Requires 'owner' role.
|
|
@@ -2554,6 +2626,26 @@ var ServicesModule = class {
|
|
|
2554
2626
|
);
|
|
2555
2627
|
return response.data;
|
|
2556
2628
|
},
|
|
2629
|
+
/**
|
|
2630
|
+
* Initiate an IdP-initiated SAML login.
|
|
2631
|
+
* Returns an HTML page with an auto-submitting form that POSTs the SAML assertion to the Service Provider.
|
|
2632
|
+
*
|
|
2633
|
+
* @param orgSlug Organization slug
|
|
2634
|
+
* @param serviceSlug Service slug
|
|
2635
|
+
* @returns HTML page with auto-submitting form
|
|
2636
|
+
*
|
|
2637
|
+
* @example
|
|
2638
|
+
* ```typescript
|
|
2639
|
+
* const html = await sso.services.saml.initiateLogin('acme-corp', 'salesforce');
|
|
2640
|
+
* document.body.innerHTML = html; // Auto-submits
|
|
2641
|
+
* ```
|
|
2642
|
+
*/
|
|
2643
|
+
initiateLogin: async (orgSlug, serviceSlug) => {
|
|
2644
|
+
const response = await this.http.get(
|
|
2645
|
+
`/api/organizations/${orgSlug}/services/${serviceSlug}/saml/login`
|
|
2646
|
+
);
|
|
2647
|
+
return response.data;
|
|
2648
|
+
},
|
|
2557
2649
|
/**
|
|
2558
2650
|
* Generate a new SAML signing certificate for the IdP.
|
|
2559
2651
|
* Requires 'owner' or 'admin' role.
|
|
@@ -2807,7 +2899,7 @@ var InvitationsModule = class {
|
|
|
2807
2899
|
* @example
|
|
2808
2900
|
* ```typescript
|
|
2809
2901
|
* const invitation = await sso.invitations.create('acme-corp', {
|
|
2810
|
-
*
|
|
2902
|
+
* email: 'newuser@example.com',
|
|
2811
2903
|
* role: 'member'
|
|
2812
2904
|
* });
|
|
2813
2905
|
* ```
|
|
@@ -3343,6 +3435,78 @@ var ServiceApiModule = class {
|
|
|
3343
3435
|
constructor(http) {
|
|
3344
3436
|
this.http = http;
|
|
3345
3437
|
}
|
|
3438
|
+
/**
|
|
3439
|
+
* List all users for the service
|
|
3440
|
+
* Requires 'read:users' permission on the API key
|
|
3441
|
+
*
|
|
3442
|
+
* @param params Optional pagination parameters
|
|
3443
|
+
* @returns List of users with total count
|
|
3444
|
+
*/
|
|
3445
|
+
async listUsers(params) {
|
|
3446
|
+
const queryParams = new URLSearchParams();
|
|
3447
|
+
if (params?.limit) queryParams.set("limit", params.limit.toString());
|
|
3448
|
+
if (params?.offset) queryParams.set("offset", params.offset.toString());
|
|
3449
|
+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
|
|
3450
|
+
const response = await this.http.get(`/api/service/users${query}`);
|
|
3451
|
+
return response.data;
|
|
3452
|
+
}
|
|
3453
|
+
/**
|
|
3454
|
+
* Get a specific user by ID
|
|
3455
|
+
* Requires 'read:users' permission on the API key
|
|
3456
|
+
*
|
|
3457
|
+
* @param userId User ID to retrieve
|
|
3458
|
+
* @returns User details
|
|
3459
|
+
*/
|
|
3460
|
+
async getUser(userId) {
|
|
3461
|
+
const response = await this.http.get(`/api/service/users/${userId}`);
|
|
3462
|
+
return response.data;
|
|
3463
|
+
}
|
|
3464
|
+
/**
|
|
3465
|
+
* List all subscriptions for the service
|
|
3466
|
+
* Requires 'read:subscriptions' permission on the API key
|
|
3467
|
+
*
|
|
3468
|
+
* @param params Optional pagination parameters
|
|
3469
|
+
* @returns List of subscriptions with total count
|
|
3470
|
+
*/
|
|
3471
|
+
async listSubscriptions(params) {
|
|
3472
|
+
const queryParams = new URLSearchParams();
|
|
3473
|
+
if (params?.limit) queryParams.set("limit", params.limit.toString());
|
|
3474
|
+
if (params?.offset) queryParams.set("offset", params.offset.toString());
|
|
3475
|
+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
|
|
3476
|
+
const response = await this.http.get(`/api/service/subscriptions${query}`);
|
|
3477
|
+
return response.data;
|
|
3478
|
+
}
|
|
3479
|
+
/**
|
|
3480
|
+
* Get subscription for a specific user
|
|
3481
|
+
* Requires 'read:subscriptions' permission on the API key
|
|
3482
|
+
*
|
|
3483
|
+
* @param userId User ID whose subscription to retrieve
|
|
3484
|
+
* @returns User's subscription
|
|
3485
|
+
*/
|
|
3486
|
+
async getSubscription(userId) {
|
|
3487
|
+
const response = await this.http.get(`/api/service/subscriptions/${userId}`);
|
|
3488
|
+
return response.data;
|
|
3489
|
+
}
|
|
3490
|
+
/**
|
|
3491
|
+
* Get analytics for the service
|
|
3492
|
+
* Requires 'read:analytics' permission on the API key
|
|
3493
|
+
*
|
|
3494
|
+
* @returns Service analytics data
|
|
3495
|
+
*/
|
|
3496
|
+
async getAnalytics() {
|
|
3497
|
+
const response = await this.http.get("/api/service/analytics");
|
|
3498
|
+
return response.data;
|
|
3499
|
+
}
|
|
3500
|
+
/**
|
|
3501
|
+
* Get service information
|
|
3502
|
+
* Requires 'read:service' permission on the API key
|
|
3503
|
+
*
|
|
3504
|
+
* @returns Service information
|
|
3505
|
+
*/
|
|
3506
|
+
async getServiceInfo() {
|
|
3507
|
+
const response = await this.http.get("/api/service/info");
|
|
3508
|
+
return response.data;
|
|
3509
|
+
}
|
|
3346
3510
|
/**
|
|
3347
3511
|
* Create a new user
|
|
3348
3512
|
* Requires 'write:users' permission on the API key
|
|
@@ -3766,15 +3930,40 @@ var PasskeysModule = class {
|
|
|
3766
3930
|
* }
|
|
3767
3931
|
* ```
|
|
3768
3932
|
*/
|
|
3933
|
+
/**
|
|
3934
|
+
* Start the passkey registration ceremony.
|
|
3935
|
+
* returns the options required to create credentials in the browser.
|
|
3936
|
+
*/
|
|
3937
|
+
async registerStart(displayName) {
|
|
3938
|
+
const response = await this.http.post(
|
|
3939
|
+
"/api/auth/passkeys/register/start",
|
|
3940
|
+
{ name: displayName }
|
|
3941
|
+
);
|
|
3942
|
+
return response.data;
|
|
3943
|
+
}
|
|
3944
|
+
/**
|
|
3945
|
+
* Finish the passkey registration ceremony.
|
|
3946
|
+
* Verifies the credential created by the browser.
|
|
3947
|
+
*/
|
|
3948
|
+
async registerFinish(challengeId, credential) {
|
|
3949
|
+
const response = await this.http.post(
|
|
3950
|
+
"/api/auth/passkeys/register/finish",
|
|
3951
|
+
{
|
|
3952
|
+
challenge_id: challengeId,
|
|
3953
|
+
credential
|
|
3954
|
+
}
|
|
3955
|
+
);
|
|
3956
|
+
return response.data;
|
|
3957
|
+
}
|
|
3958
|
+
/**
|
|
3959
|
+
* Register a new passkey for the authenticated user
|
|
3960
|
+
* ...
|
|
3961
|
+
*/
|
|
3769
3962
|
async register(displayName) {
|
|
3770
3963
|
if (!this.isSupported()) {
|
|
3771
3964
|
throw new Error("WebAuthn is not supported in this browser");
|
|
3772
3965
|
}
|
|
3773
|
-
const
|
|
3774
|
-
"/auth/passkeys/register/start",
|
|
3775
|
-
{ name: displayName }
|
|
3776
|
-
);
|
|
3777
|
-
const startData = startResponse.data;
|
|
3966
|
+
const startData = await this.registerStart(displayName);
|
|
3778
3967
|
const createOptions = {
|
|
3779
3968
|
publicKey: {
|
|
3780
3969
|
...startData.options,
|
|
@@ -3808,14 +3997,8 @@ var PasskeysModule = class {
|
|
|
3808
3997
|
clientExtensionResults: credential.getClientExtensionResults(),
|
|
3809
3998
|
type: credential.type
|
|
3810
3999
|
};
|
|
3811
|
-
const finishResponse = await this.
|
|
3812
|
-
|
|
3813
|
-
{
|
|
3814
|
-
challenge_id: startData.challenge_id,
|
|
3815
|
-
credential: credentialJSON
|
|
3816
|
-
}
|
|
3817
|
-
);
|
|
3818
|
-
return finishResponse.data.passkey_id;
|
|
4000
|
+
const finishResponse = await this.registerFinish(startData.challenge_id, credentialJSON);
|
|
4001
|
+
return finishResponse.passkey_id;
|
|
3819
4002
|
}
|
|
3820
4003
|
/**
|
|
3821
4004
|
* Authenticate with a passkey and obtain a JWT token
|
|
@@ -3839,16 +4022,40 @@ var PasskeysModule = class {
|
|
|
3839
4022
|
* }
|
|
3840
4023
|
* ```
|
|
3841
4024
|
*/
|
|
4025
|
+
/**
|
|
4026
|
+
* Start the passkey authentication ceremony.
|
|
4027
|
+
* Returns the options required to get credentials from the browser.
|
|
4028
|
+
*/
|
|
4029
|
+
async authenticateStart(email) {
|
|
4030
|
+
const response = await this.http.post(
|
|
4031
|
+
"/api/auth/passkeys/authenticate/start",
|
|
4032
|
+
{ email }
|
|
4033
|
+
);
|
|
4034
|
+
return response.data;
|
|
4035
|
+
}
|
|
4036
|
+
/**
|
|
4037
|
+
* Finish the passkey authentication ceremony.
|
|
4038
|
+
* Verifies the assertion returned by the browser.
|
|
4039
|
+
*/
|
|
4040
|
+
async authenticateFinish(challengeId, credential) {
|
|
4041
|
+
const response = await this.http.post(
|
|
4042
|
+
"/api/auth/passkeys/authenticate/finish",
|
|
4043
|
+
{
|
|
4044
|
+
challenge_id: challengeId,
|
|
4045
|
+
credential
|
|
4046
|
+
}
|
|
4047
|
+
);
|
|
4048
|
+
return response.data;
|
|
4049
|
+
}
|
|
4050
|
+
/**
|
|
4051
|
+
* Authenticate with a passkey and obtain a JWT token
|
|
4052
|
+
* ...
|
|
4053
|
+
*/
|
|
3842
4054
|
async login(email) {
|
|
3843
4055
|
if (!this.isSupported()) {
|
|
3844
4056
|
throw new Error("WebAuthn is not supported in this browser");
|
|
3845
4057
|
}
|
|
3846
|
-
const
|
|
3847
|
-
const startResponse = await this.http.post(
|
|
3848
|
-
"/auth/passkeys/authenticate/start",
|
|
3849
|
-
startRequest
|
|
3850
|
-
);
|
|
3851
|
-
const startData = startResponse.data;
|
|
4058
|
+
const startData = await this.authenticateStart(email);
|
|
3852
4059
|
const getOptions = {
|
|
3853
4060
|
publicKey: {
|
|
3854
4061
|
...startData.options,
|
|
@@ -3879,14 +4086,7 @@ var PasskeysModule = class {
|
|
|
3879
4086
|
clientExtensionResults: credential.getClientExtensionResults(),
|
|
3880
4087
|
type: credential.type
|
|
3881
4088
|
};
|
|
3882
|
-
|
|
3883
|
-
"/auth/passkeys/authenticate/finish",
|
|
3884
|
-
{
|
|
3885
|
-
challenge_id: startData.challenge_id,
|
|
3886
|
-
credential: credentialJSON
|
|
3887
|
-
}
|
|
3888
|
-
);
|
|
3889
|
-
return finishResponse.data;
|
|
4089
|
+
return this.authenticateFinish(startData.challenge_id, credentialJSON);
|
|
3890
4090
|
}
|
|
3891
4091
|
/**
|
|
3892
4092
|
* Convert Base64URL string to Uint8Array
|
package/dist/index.mjs
CHANGED
|
@@ -104,7 +104,7 @@ var HttpClient = class {
|
|
|
104
104
|
signal: controller.signal
|
|
105
105
|
});
|
|
106
106
|
clearTimeout(timeoutId);
|
|
107
|
-
if (response.status === 401 && this.sessionManager && !options._retry && !path.includes("/auth/login")) {
|
|
107
|
+
if (response.status === 401 && this.sessionManager && !options._retry && !path.includes("/auth/login") && !path.includes("/auth/refresh")) {
|
|
108
108
|
try {
|
|
109
109
|
const newToken = await this.sessionManager.refreshSession();
|
|
110
110
|
return this.request(path, {
|
|
@@ -688,6 +688,23 @@ var AuthModule = class {
|
|
|
688
688
|
const response = await this.http.post("/api/auth/register", payload);
|
|
689
689
|
return response.data;
|
|
690
690
|
}
|
|
691
|
+
/**
|
|
692
|
+
* Verify an email address using the token from the verification email.
|
|
693
|
+
*
|
|
694
|
+
* @param token Verification token
|
|
695
|
+
* @returns HTML success page string
|
|
696
|
+
*
|
|
697
|
+
* @example
|
|
698
|
+
* ```typescript
|
|
699
|
+
* const html = await sso.auth.verifyEmail('token-from-email');
|
|
700
|
+
* ```
|
|
701
|
+
*/
|
|
702
|
+
async verifyEmail(token) {
|
|
703
|
+
const response = await this.http.get("/auth/verify-email", {
|
|
704
|
+
params: { token }
|
|
705
|
+
});
|
|
706
|
+
return response.data;
|
|
707
|
+
}
|
|
691
708
|
/**
|
|
692
709
|
* Login with email and password.
|
|
693
710
|
* Automatically persists the session and configures the client.
|
|
@@ -1447,6 +1464,43 @@ var WebhooksModule = class {
|
|
|
1447
1464
|
var OrganizationsModule = class {
|
|
1448
1465
|
constructor(http) {
|
|
1449
1466
|
this.http = http;
|
|
1467
|
+
/**
|
|
1468
|
+
* SCIM token management methods
|
|
1469
|
+
*/
|
|
1470
|
+
this.scim = {
|
|
1471
|
+
/**
|
|
1472
|
+
* Create a new SCIM token.
|
|
1473
|
+
* The token is only returned once upon creation.
|
|
1474
|
+
*/
|
|
1475
|
+
createToken: async (orgSlug, payload) => {
|
|
1476
|
+
const response = await this.http.post(
|
|
1477
|
+
`/api/organizations/${orgSlug}/scim-tokens`,
|
|
1478
|
+
payload
|
|
1479
|
+
);
|
|
1480
|
+
return response.data;
|
|
1481
|
+
},
|
|
1482
|
+
/**
|
|
1483
|
+
* List all SCIM tokens.
|
|
1484
|
+
*/
|
|
1485
|
+
listTokens: async (orgSlug) => {
|
|
1486
|
+
const response = await this.http.get(
|
|
1487
|
+
`/api/organizations/${orgSlug}/scim-tokens`
|
|
1488
|
+
);
|
|
1489
|
+
return response.data;
|
|
1490
|
+
},
|
|
1491
|
+
/**
|
|
1492
|
+
* Revoke a SCIM token.
|
|
1493
|
+
*/
|
|
1494
|
+
revokeToken: async (orgSlug, tokenId) => {
|
|
1495
|
+
await this.http.post(`/api/organizations/${orgSlug}/scim-tokens/${tokenId}/revoke`);
|
|
1496
|
+
},
|
|
1497
|
+
/**
|
|
1498
|
+
* Delete a SCIM token.
|
|
1499
|
+
*/
|
|
1500
|
+
deleteToken: async (orgSlug, tokenId) => {
|
|
1501
|
+
await this.http.delete(`/api/organizations/${orgSlug}/scim-tokens/${tokenId}`);
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1450
1504
|
/**
|
|
1451
1505
|
* Member management methods
|
|
1452
1506
|
*/
|
|
@@ -1470,6 +1524,24 @@ var OrganizationsModule = class {
|
|
|
1470
1524
|
);
|
|
1471
1525
|
return response.data;
|
|
1472
1526
|
},
|
|
1527
|
+
/**
|
|
1528
|
+
* Add a member to the organization (Invite + Accept).
|
|
1529
|
+
* This is a convenience method that creates an invitation and immediately accepts it.
|
|
1530
|
+
* Useful for testing and admin operations.
|
|
1531
|
+
*
|
|
1532
|
+
* @param orgSlug Organization slug
|
|
1533
|
+
* @param payload Member details (email, role)
|
|
1534
|
+
* @returns The created invitation
|
|
1535
|
+
*/
|
|
1536
|
+
add: async (orgSlug, payload) => {
|
|
1537
|
+
const response = await this.http.post(
|
|
1538
|
+
`/api/organizations/${orgSlug}/invitations`,
|
|
1539
|
+
payload
|
|
1540
|
+
);
|
|
1541
|
+
const invitation = response.data;
|
|
1542
|
+
await this.http.post("/api/invitations/accept", { token: invitation.token });
|
|
1543
|
+
return invitation;
|
|
1544
|
+
},
|
|
1473
1545
|
/**
|
|
1474
1546
|
* Update a member's role.
|
|
1475
1547
|
* Requires 'owner' role.
|
|
@@ -2511,6 +2583,26 @@ var ServicesModule = class {
|
|
|
2511
2583
|
);
|
|
2512
2584
|
return response.data;
|
|
2513
2585
|
},
|
|
2586
|
+
/**
|
|
2587
|
+
* Initiate an IdP-initiated SAML login.
|
|
2588
|
+
* Returns an HTML page with an auto-submitting form that POSTs the SAML assertion to the Service Provider.
|
|
2589
|
+
*
|
|
2590
|
+
* @param orgSlug Organization slug
|
|
2591
|
+
* @param serviceSlug Service slug
|
|
2592
|
+
* @returns HTML page with auto-submitting form
|
|
2593
|
+
*
|
|
2594
|
+
* @example
|
|
2595
|
+
* ```typescript
|
|
2596
|
+
* const html = await sso.services.saml.initiateLogin('acme-corp', 'salesforce');
|
|
2597
|
+
* document.body.innerHTML = html; // Auto-submits
|
|
2598
|
+
* ```
|
|
2599
|
+
*/
|
|
2600
|
+
initiateLogin: async (orgSlug, serviceSlug) => {
|
|
2601
|
+
const response = await this.http.get(
|
|
2602
|
+
`/api/organizations/${orgSlug}/services/${serviceSlug}/saml/login`
|
|
2603
|
+
);
|
|
2604
|
+
return response.data;
|
|
2605
|
+
},
|
|
2514
2606
|
/**
|
|
2515
2607
|
* Generate a new SAML signing certificate for the IdP.
|
|
2516
2608
|
* Requires 'owner' or 'admin' role.
|
|
@@ -2764,7 +2856,7 @@ var InvitationsModule = class {
|
|
|
2764
2856
|
* @example
|
|
2765
2857
|
* ```typescript
|
|
2766
2858
|
* const invitation = await sso.invitations.create('acme-corp', {
|
|
2767
|
-
*
|
|
2859
|
+
* email: 'newuser@example.com',
|
|
2768
2860
|
* role: 'member'
|
|
2769
2861
|
* });
|
|
2770
2862
|
* ```
|
|
@@ -3300,6 +3392,78 @@ var ServiceApiModule = class {
|
|
|
3300
3392
|
constructor(http) {
|
|
3301
3393
|
this.http = http;
|
|
3302
3394
|
}
|
|
3395
|
+
/**
|
|
3396
|
+
* List all users for the service
|
|
3397
|
+
* Requires 'read:users' permission on the API key
|
|
3398
|
+
*
|
|
3399
|
+
* @param params Optional pagination parameters
|
|
3400
|
+
* @returns List of users with total count
|
|
3401
|
+
*/
|
|
3402
|
+
async listUsers(params) {
|
|
3403
|
+
const queryParams = new URLSearchParams();
|
|
3404
|
+
if (params?.limit) queryParams.set("limit", params.limit.toString());
|
|
3405
|
+
if (params?.offset) queryParams.set("offset", params.offset.toString());
|
|
3406
|
+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
|
|
3407
|
+
const response = await this.http.get(`/api/service/users${query}`);
|
|
3408
|
+
return response.data;
|
|
3409
|
+
}
|
|
3410
|
+
/**
|
|
3411
|
+
* Get a specific user by ID
|
|
3412
|
+
* Requires 'read:users' permission on the API key
|
|
3413
|
+
*
|
|
3414
|
+
* @param userId User ID to retrieve
|
|
3415
|
+
* @returns User details
|
|
3416
|
+
*/
|
|
3417
|
+
async getUser(userId) {
|
|
3418
|
+
const response = await this.http.get(`/api/service/users/${userId}`);
|
|
3419
|
+
return response.data;
|
|
3420
|
+
}
|
|
3421
|
+
/**
|
|
3422
|
+
* List all subscriptions for the service
|
|
3423
|
+
* Requires 'read:subscriptions' permission on the API key
|
|
3424
|
+
*
|
|
3425
|
+
* @param params Optional pagination parameters
|
|
3426
|
+
* @returns List of subscriptions with total count
|
|
3427
|
+
*/
|
|
3428
|
+
async listSubscriptions(params) {
|
|
3429
|
+
const queryParams = new URLSearchParams();
|
|
3430
|
+
if (params?.limit) queryParams.set("limit", params.limit.toString());
|
|
3431
|
+
if (params?.offset) queryParams.set("offset", params.offset.toString());
|
|
3432
|
+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
|
|
3433
|
+
const response = await this.http.get(`/api/service/subscriptions${query}`);
|
|
3434
|
+
return response.data;
|
|
3435
|
+
}
|
|
3436
|
+
/**
|
|
3437
|
+
* Get subscription for a specific user
|
|
3438
|
+
* Requires 'read:subscriptions' permission on the API key
|
|
3439
|
+
*
|
|
3440
|
+
* @param userId User ID whose subscription to retrieve
|
|
3441
|
+
* @returns User's subscription
|
|
3442
|
+
*/
|
|
3443
|
+
async getSubscription(userId) {
|
|
3444
|
+
const response = await this.http.get(`/api/service/subscriptions/${userId}`);
|
|
3445
|
+
return response.data;
|
|
3446
|
+
}
|
|
3447
|
+
/**
|
|
3448
|
+
* Get analytics for the service
|
|
3449
|
+
* Requires 'read:analytics' permission on the API key
|
|
3450
|
+
*
|
|
3451
|
+
* @returns Service analytics data
|
|
3452
|
+
*/
|
|
3453
|
+
async getAnalytics() {
|
|
3454
|
+
const response = await this.http.get("/api/service/analytics");
|
|
3455
|
+
return response.data;
|
|
3456
|
+
}
|
|
3457
|
+
/**
|
|
3458
|
+
* Get service information
|
|
3459
|
+
* Requires 'read:service' permission on the API key
|
|
3460
|
+
*
|
|
3461
|
+
* @returns Service information
|
|
3462
|
+
*/
|
|
3463
|
+
async getServiceInfo() {
|
|
3464
|
+
const response = await this.http.get("/api/service/info");
|
|
3465
|
+
return response.data;
|
|
3466
|
+
}
|
|
3303
3467
|
/**
|
|
3304
3468
|
* Create a new user
|
|
3305
3469
|
* Requires 'write:users' permission on the API key
|
|
@@ -3723,15 +3887,40 @@ var PasskeysModule = class {
|
|
|
3723
3887
|
* }
|
|
3724
3888
|
* ```
|
|
3725
3889
|
*/
|
|
3890
|
+
/**
|
|
3891
|
+
* Start the passkey registration ceremony.
|
|
3892
|
+
* returns the options required to create credentials in the browser.
|
|
3893
|
+
*/
|
|
3894
|
+
async registerStart(displayName) {
|
|
3895
|
+
const response = await this.http.post(
|
|
3896
|
+
"/api/auth/passkeys/register/start",
|
|
3897
|
+
{ name: displayName }
|
|
3898
|
+
);
|
|
3899
|
+
return response.data;
|
|
3900
|
+
}
|
|
3901
|
+
/**
|
|
3902
|
+
* Finish the passkey registration ceremony.
|
|
3903
|
+
* Verifies the credential created by the browser.
|
|
3904
|
+
*/
|
|
3905
|
+
async registerFinish(challengeId, credential) {
|
|
3906
|
+
const response = await this.http.post(
|
|
3907
|
+
"/api/auth/passkeys/register/finish",
|
|
3908
|
+
{
|
|
3909
|
+
challenge_id: challengeId,
|
|
3910
|
+
credential
|
|
3911
|
+
}
|
|
3912
|
+
);
|
|
3913
|
+
return response.data;
|
|
3914
|
+
}
|
|
3915
|
+
/**
|
|
3916
|
+
* Register a new passkey for the authenticated user
|
|
3917
|
+
* ...
|
|
3918
|
+
*/
|
|
3726
3919
|
async register(displayName) {
|
|
3727
3920
|
if (!this.isSupported()) {
|
|
3728
3921
|
throw new Error("WebAuthn is not supported in this browser");
|
|
3729
3922
|
}
|
|
3730
|
-
const
|
|
3731
|
-
"/auth/passkeys/register/start",
|
|
3732
|
-
{ name: displayName }
|
|
3733
|
-
);
|
|
3734
|
-
const startData = startResponse.data;
|
|
3923
|
+
const startData = await this.registerStart(displayName);
|
|
3735
3924
|
const createOptions = {
|
|
3736
3925
|
publicKey: {
|
|
3737
3926
|
...startData.options,
|
|
@@ -3765,14 +3954,8 @@ var PasskeysModule = class {
|
|
|
3765
3954
|
clientExtensionResults: credential.getClientExtensionResults(),
|
|
3766
3955
|
type: credential.type
|
|
3767
3956
|
};
|
|
3768
|
-
const finishResponse = await this.
|
|
3769
|
-
|
|
3770
|
-
{
|
|
3771
|
-
challenge_id: startData.challenge_id,
|
|
3772
|
-
credential: credentialJSON
|
|
3773
|
-
}
|
|
3774
|
-
);
|
|
3775
|
-
return finishResponse.data.passkey_id;
|
|
3957
|
+
const finishResponse = await this.registerFinish(startData.challenge_id, credentialJSON);
|
|
3958
|
+
return finishResponse.passkey_id;
|
|
3776
3959
|
}
|
|
3777
3960
|
/**
|
|
3778
3961
|
* Authenticate with a passkey and obtain a JWT token
|
|
@@ -3796,16 +3979,40 @@ var PasskeysModule = class {
|
|
|
3796
3979
|
* }
|
|
3797
3980
|
* ```
|
|
3798
3981
|
*/
|
|
3982
|
+
/**
|
|
3983
|
+
* Start the passkey authentication ceremony.
|
|
3984
|
+
* Returns the options required to get credentials from the browser.
|
|
3985
|
+
*/
|
|
3986
|
+
async authenticateStart(email) {
|
|
3987
|
+
const response = await this.http.post(
|
|
3988
|
+
"/api/auth/passkeys/authenticate/start",
|
|
3989
|
+
{ email }
|
|
3990
|
+
);
|
|
3991
|
+
return response.data;
|
|
3992
|
+
}
|
|
3993
|
+
/**
|
|
3994
|
+
* Finish the passkey authentication ceremony.
|
|
3995
|
+
* Verifies the assertion returned by the browser.
|
|
3996
|
+
*/
|
|
3997
|
+
async authenticateFinish(challengeId, credential) {
|
|
3998
|
+
const response = await this.http.post(
|
|
3999
|
+
"/api/auth/passkeys/authenticate/finish",
|
|
4000
|
+
{
|
|
4001
|
+
challenge_id: challengeId,
|
|
4002
|
+
credential
|
|
4003
|
+
}
|
|
4004
|
+
);
|
|
4005
|
+
return response.data;
|
|
4006
|
+
}
|
|
4007
|
+
/**
|
|
4008
|
+
* Authenticate with a passkey and obtain a JWT token
|
|
4009
|
+
* ...
|
|
4010
|
+
*/
|
|
3799
4011
|
async login(email) {
|
|
3800
4012
|
if (!this.isSupported()) {
|
|
3801
4013
|
throw new Error("WebAuthn is not supported in this browser");
|
|
3802
4014
|
}
|
|
3803
|
-
const
|
|
3804
|
-
const startResponse = await this.http.post(
|
|
3805
|
-
"/auth/passkeys/authenticate/start",
|
|
3806
|
-
startRequest
|
|
3807
|
-
);
|
|
3808
|
-
const startData = startResponse.data;
|
|
4015
|
+
const startData = await this.authenticateStart(email);
|
|
3809
4016
|
const getOptions = {
|
|
3810
4017
|
publicKey: {
|
|
3811
4018
|
...startData.options,
|
|
@@ -3836,14 +4043,7 @@ var PasskeysModule = class {
|
|
|
3836
4043
|
clientExtensionResults: credential.getClientExtensionResults(),
|
|
3837
4044
|
type: credential.type
|
|
3838
4045
|
};
|
|
3839
|
-
|
|
3840
|
-
"/auth/passkeys/authenticate/finish",
|
|
3841
|
-
{
|
|
3842
|
-
challenge_id: startData.challenge_id,
|
|
3843
|
-
credential: credentialJSON
|
|
3844
|
-
}
|
|
3845
|
-
);
|
|
3846
|
-
return finishResponse.data;
|
|
4046
|
+
return this.authenticateFinish(startData.challenge_id, credentialJSON);
|
|
3847
4047
|
}
|
|
3848
4048
|
/**
|
|
3849
4049
|
* Convert Base64URL string to Uint8Array
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drmhse/sso-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Zero-dependency TypeScript SDK for the multi-tenant
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Zero-dependency TypeScript SDK for AuthOS, the multi-tenant authentication platform",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|