@drmhse/sso-sdk 0.3.13 → 0.4.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 CHANGED
@@ -98,7 +98,9 @@ const loginUrl = sso.auth.getLoginUrl('github', {
98
98
  await sso.auth.login({
99
99
  email: 'user@example.com',
100
100
  password: 'SecurePass123!',
101
- org_slug: 'acme-corp' // Optional: scopes JWT to this org
101
+ org_slug: 'acme-corp', // Optional: scopes JWT to this org
102
+ service_slug: 'main-app',
103
+ redirect_uri: 'https://app.acme.com/callback'
102
104
  });
103
105
  // JWT contains: { org: 'acme-corp', ... }
104
106
  ```
@@ -138,11 +140,15 @@ const loginUrl = sso.auth.getLoginUrl('github', {
138
140
  });
139
141
  window.location.href = loginUrl;
140
142
 
141
- // Handle callback - initialize client with token from OAuth callback
142
- const params = new URLSearchParams(window.location.search);
143
- const accessToken = params.get('access_token');
143
+ // Handle callback - tokens are returned in URL fragment (#) for security
144
+ // (prevents tokens from being logged in server access logs)
145
+ const hashParams = new URLSearchParams(window.location.hash.substring(1));
146
+ const accessToken = hashParams.get('access_token');
144
147
 
145
148
  if (accessToken) {
149
+ // Clear hash from URL for security
150
+ window.history.replaceState(null, '', window.location.pathname);
151
+
146
152
  // Initialize SDK with OAuth token - automatically stored
147
153
  const sso = new SsoClient({
148
154
  baseURL: 'https://sso.example.com',
@@ -183,6 +189,48 @@ const result = await sso.user.mfa.verify('123456'); // TOTP code from authentica
183
189
  console.log('Backup codes:', result.backup_codes); // Save these securely!
184
190
  ```
185
191
 
192
+ ### Hosted Auth Context & Passwordless
193
+
194
+ ```typescript
195
+ const context = await sso.auth.getContext({
196
+ org: 'acme-corp',
197
+ service: 'main-app',
198
+ redirect_uri: 'https://app.acme.com/callback'
199
+ });
200
+
201
+ console.log(context.organization?.name);
202
+ console.log(context.available_providers); // ['github', 'google', 'microsoft']
203
+
204
+ await sso.magicLinks.request({
205
+ email: 'user@example.com',
206
+ org_slug: 'acme-corp',
207
+ service_slug: 'main-app',
208
+ redirect_uri: 'https://app.acme.com/callback'
209
+ });
210
+
211
+ const passkeyLogin = await sso.passkeys.login('user@example.com', {
212
+ org_slug: 'acme-corp',
213
+ service_slug: 'main-app',
214
+ redirect_uri: 'https://app.acme.com/callback'
215
+ });
216
+
217
+ await sso.setSession({
218
+ access_token: passkeyLogin.access_token,
219
+ refresh_token: passkeyLogin.refresh_token
220
+ });
221
+ ```
222
+
223
+ ### Passkey Self-Service
224
+
225
+ ```typescript
226
+ const passkeys = await sso.passkeys.list();
227
+
228
+ if (passkeys.length > 0) {
229
+ await sso.passkeys.updateName(passkeys[0].id, 'Work Laptop');
230
+ await sso.passkeys.delete(passkeys[0].id);
231
+ }
232
+ ```
233
+
186
234
  ### Device Flow (for CLIs)
187
235
 
188
236
  ```typescript
@@ -251,7 +299,7 @@ if (currentRefreshToken) {
251
299
 
252
300
  ```typescript
253
301
  // Create organization
254
- const org = await sso.organizations.createPublic({
302
+ const org = await sso.organizations.create({
255
303
  name: 'Acme Corp',
256
304
  slug: 'acme-corp'
257
305
  });
@@ -263,7 +311,7 @@ await sso.organizations.oauthCredentials.set('acme-corp', 'github', {
263
311
  });
264
312
 
265
313
  // Invite team members
266
- await sso.organizations.invitations.create('acme-corp', {
314
+ await sso.invitations.create('acme-corp', {
267
315
  email: 'member@acme.com',
268
316
  role: 'admin'
269
317
  });
@@ -341,6 +389,26 @@ const backendClient = new SsoClient({
341
389
  baseURL: 'https://sso.example.com',
342
390
  apiKey: apiKey.key
343
391
  });
392
+
393
+ const rotated = await sso.services.rotateSecret('acme-corp', 'main-app');
394
+ console.log('New client secret:', rotated.client_secret);
395
+ ```
396
+
397
+ ## Fine-Grained Member Access
398
+
399
+ ```typescript
400
+ const access = await sso.organizations.members.updateServiceAccess(
401
+ 'acme-corp',
402
+ 'user-id',
403
+ {
404
+ grants: [
405
+ { service_slug: 'main-app', access: 'manager' },
406
+ { service_slug: 'docs-app', access: 'viewer' }
407
+ ]
408
+ }
409
+ );
410
+
411
+ console.log(access);
344
412
  ```
345
413
 
346
414
  ## Analytics
@@ -420,6 +488,10 @@ console.log(overview); // { total_users, total_orgs, total_logins, ... }
420
488
 
421
489
  // Search users across all organizations
422
490
  const users = await sso.platform.users.search('user@example.com');
491
+
492
+ // Inspect operational health
493
+ const ops = await sso.platform.getOperationsStatus();
494
+ console.log(ops.jobs_pending, ops.webhook_deliveries_failed);
423
495
  ```
424
496
 
425
497
  ## TypeScript Support