@drmhse/sso-sdk 0.2.7 → 0.2.9

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
@@ -12,6 +12,8 @@ A zero-dependency, strongly-typed TypeScript SDK for the multi-tenant SSO Platfo
12
12
  - **Zero Dependencies** - Built on native `fetch` API
13
13
  - **Strongly Typed** - Complete TypeScript definitions
14
14
  - **Framework Agnostic** - Works in any JavaScript environment
15
+ - **Automatic Session Management** - Invisible token persistence and auto-refresh
16
+ - **Smart Token Handling** - Auto-inject tokens and handle 401 errors transparently
15
17
  - **OAuth 2.0 Flows** - Support for GitHub, Google, Microsoft
16
18
  - **Password Authentication** - Native email/password auth with MFA
17
19
  - **Device Flow** - RFC 8628 for CLIs and headless apps
@@ -31,17 +33,21 @@ npm install @drmhse/sso-sdk
31
33
  ```typescript
32
34
  import { SsoClient } from '@drmhse/sso-sdk';
33
35
 
34
- // Initialize the client
36
+ // Initialize the client - automatically loads tokens from localStorage
35
37
  const sso = new SsoClient({
36
- baseURL: 'https://sso.example.com',
37
- token: localStorage.getItem('sso_access_token')
38
+ baseURL: 'https://sso.example.com'
38
39
  });
39
40
 
40
- // Get user profile
41
+ // Login - session is automatically saved
42
+ await sso.auth.login({
43
+ email: 'user@example.com',
44
+ password: 'SecurePass123!'
45
+ });
46
+
47
+ // Make authenticated requests - tokens auto-injected and auto-refreshed
41
48
  const profile = await sso.user.getProfile();
42
49
  console.log(profile.email);
43
50
 
44
- // List organizations
45
51
  const orgs = await sso.organizations.list();
46
52
  console.log(orgs);
47
53
  ```
@@ -67,15 +73,18 @@ const loginUrl = sso.auth.getLoginUrl('github', {
67
73
  });
68
74
  window.location.href = loginUrl;
69
75
 
70
- // Handle callback
76
+ // Handle callback - initialize client with token from OAuth callback
71
77
  const params = new URLSearchParams(window.location.search);
72
78
  const accessToken = params.get('access_token');
73
- const refreshToken = params.get('refresh_token');
74
79
 
75
- if (accessToken && refreshToken) {
76
- sso.setAuthToken(accessToken);
77
- localStorage.setItem('sso_access_token', accessToken);
78
- localStorage.setItem('sso_refresh_token', refreshToken);
80
+ if (accessToken) {
81
+ // Initialize SDK with OAuth token - automatically stored
82
+ const sso = new SsoClient({
83
+ baseURL: 'https://sso.example.com',
84
+ token: accessToken
85
+ });
86
+ // Token is now automatically stored and managed
87
+ window.location.href = '/dashboard';
79
88
  }
80
89
  ```
81
90
 
@@ -89,19 +98,20 @@ await sso.auth.register({
89
98
  org_slug: 'acme-corp'
90
99
  });
91
100
 
92
- // Login with password
93
- const tokens = await sso.auth.login({
101
+ // Login with password - session automatically saved
102
+ await sso.auth.login({
94
103
  email: 'user@example.com',
95
104
  password: 'SecurePass123!'
96
105
  });
97
- sso.setAuthToken(tokens.access_token);
106
+ // Tokens are now automatically stored and injected on all requests
98
107
 
99
108
  // Enable MFA
100
109
  const mfaSetup = await sso.user.mfa.setup();
101
- console.log(mfaSetup.qr_code); // Display QR code to user
110
+ console.log(mfaSetup.qr_code_svg); // Display QR code to user
102
111
 
103
- // Verify and enable
104
- await sso.user.mfa.verify('123456'); // TOTP code from authenticator app
112
+ // Verify and enable - automatically saves backup codes
113
+ const result = await sso.user.mfa.verify('123456'); // TOTP code from authenticator app
114
+ console.log('Backup codes:', result.backup_codes); // Save these securely!
105
115
  ```
106
116
 
107
117
  ### Device Flow (for CLIs)
@@ -122,10 +132,16 @@ const interval = setInterval(async () => {
122
132
  try {
123
133
  const tokens = await sso.auth.deviceCode.exchangeToken({
124
134
  device_code: deviceAuth.device_code,
125
- client_id: 'cli-client'
135
+ client_id: 'cli-client',
136
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code'
137
+ });
138
+
139
+ // Initialize SDK with the token - automatically stored
140
+ const authenticatedSso = new SsoClient({
141
+ baseURL: 'https://sso.example.com',
142
+ token: tokens.access_token
126
143
  });
127
144
 
128
- sso.setAuthToken(tokens.access_token);
129
145
  clearInterval(interval);
130
146
  console.log('Authentication successful!');
131
147
  } catch (error) {
@@ -136,16 +152,29 @@ const interval = setInterval(async () => {
136
152
 
137
153
  ### Token Refresh
138
154
 
155
+ **Automatic Token Refresh** - The SDK automatically refreshes expired tokens when it detects a 401 error:
156
+
139
157
  ```typescript
158
+ // No manual refresh needed! Just make your API calls
140
159
  try {
141
- const tokens = await sso.auth.refreshToken(storedRefreshToken);
142
-
143
- sso.setAuthToken(tokens.access_token);
144
- localStorage.setItem('sso_access_token', tokens.access_token);
145
- localStorage.setItem('sso_refresh_token', tokens.refresh_token);
160
+ // If the access token is expired, the SDK will:
161
+ // 1. Detect the 401 error
162
+ // 2. Use the refresh token to get new tokens
163
+ // 3. Retry the request automatically
164
+ // 4. Return the result - you never see the 401!
165
+ const profile = await sso.user.getProfile();
166
+ console.log(profile);
146
167
  } catch (error) {
147
- // Refresh failed - redirect to login
148
- console.error('Token refresh failed:', error);
168
+ // You'll only see errors if refresh fails (e.g., refresh token expired)
169
+ console.error('Session expired - please log in again');
170
+ // Redirect to login
171
+ }
172
+
173
+ // Optional: Manually refresh if needed (advanced use case)
174
+ const currentRefreshToken = await sso.getToken();
175
+ if (currentRefreshToken) {
176
+ const tokens = await sso.auth.refreshToken(currentRefreshToken);
177
+ // Tokens automatically updated
149
178
  }
150
179
  ```
151
180
 
@@ -239,14 +268,26 @@ try {
239
268
  console.error(`Code: ${error.errorCode}`);
240
269
 
241
270
  if (error.status === 401) {
242
- // Token expired - refresh or re-authenticate
271
+ // Session expired (refresh token also expired)
272
+ // Automatic refresh already tried and failed
273
+ // Redirect to login
274
+ window.location.href = '/login';
243
275
  } else if (error.status === 403) {
244
276
  // Forbidden - insufficient permissions
277
+ console.error('You do not have permission to access this resource');
245
278
  }
246
279
  } else {
247
280
  console.error('Unexpected error:', error);
248
281
  }
249
282
  }
283
+
284
+ // React to authentication state changes
285
+ sso.onAuthStateChange((isAuthenticated) => {
286
+ if (!isAuthenticated) {
287
+ // User logged out or session expired
288
+ window.location.href = '/login';
289
+ }
290
+ });
250
291
  ```
251
292
 
252
293
  ## Platform Administration