tenneo-auth-plugin 0.1.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 +596 -0
- package/dist/index.d.mts +558 -0
- package/dist/index.d.ts +558 -0
- package/dist/index.js +3436 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3385 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
# @tenneo/auth-plugin
|
|
2
|
+
|
|
3
|
+
Production-ready ReactJS authentication plugin using TypeScript with full OAuth 2.0 PKCE lifecycle support.
|
|
4
|
+
|
|
5
|
+
> **Note:** This is an internal scoped package with restricted access.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Full OAuth 2.0 PKCE flow implementation
|
|
10
|
+
- Multi-tenant support via tenant code resolution
|
|
11
|
+
- Automatic token refresh
|
|
12
|
+
- Session-based storage with namespacing
|
|
13
|
+
- React hooks and Context API integration
|
|
14
|
+
- TypeScript with strict typing
|
|
15
|
+
- Configurable storage adapters (session, cookie, memory)
|
|
16
|
+
- Auth engine architecture for advanced use cases
|
|
17
|
+
- Protected route component
|
|
18
|
+
- Callback handling component
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
### Installation from npm registry (stable)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @tenneo/auth-plugin
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Installation from npm registry (beta)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @tenneo/auth-plugin@beta
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Installation from hosted .tgz file (without pack)
|
|
35
|
+
|
|
36
|
+
If the plugin is hosted on a server as a `.tgz` file, install directly from the URL:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install https://your-server.com/path/tenneo-auth-plugin-0.1.0-beta.1.tgz
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or add it to your `package.json`:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@tenneo/auth-plugin": "https://your-server.com/path/tenneo-auth-plugin-0.1.0-beta.1.tgz"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then run:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Installation with npm pack
|
|
59
|
+
|
|
60
|
+
Use this method to create a distributable package from the source:
|
|
61
|
+
|
|
62
|
+
**Step 1: Build the plugin**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd tenneo-auth-plugin
|
|
66
|
+
npm install
|
|
67
|
+
npm run build
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Step 2: Create the package**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm pack
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This creates a file like `tenneo-auth-plugin-0.1.0-beta.1.tgz` in the current directory.
|
|
77
|
+
|
|
78
|
+
**Step 3: Install in your application**
|
|
79
|
+
|
|
80
|
+
Copy the `.tgz` file to your application directory and install:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm install ./tenneo-auth-plugin-0.1.0-beta.1.tgz
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Or specify the full path:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm install /path/to/tenneo-auth-plugin-0.1.0-beta.1.tgz
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Installation with local source (development)
|
|
93
|
+
|
|
94
|
+
Use this method during development to link the plugin directly without packing:
|
|
95
|
+
|
|
96
|
+
**Method 1: npm link (recommended for development)**
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# In the plugin directory
|
|
100
|
+
cd tenneo-auth-plugin
|
|
101
|
+
npm install
|
|
102
|
+
npm run build
|
|
103
|
+
npm link
|
|
104
|
+
|
|
105
|
+
# In your application directory
|
|
106
|
+
cd your-application
|
|
107
|
+
npm link @tenneo/auth-plugin
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
To unlink when done:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# In your application directory
|
|
114
|
+
npm unlink @tenneo/auth-plugin
|
|
115
|
+
|
|
116
|
+
# In the plugin directory
|
|
117
|
+
npm unlink
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Method 2: File path in package.json**
|
|
121
|
+
|
|
122
|
+
Add the local path to your application's `package.json`:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"dependencies": {
|
|
127
|
+
"@tenneo/auth-plugin": "file:../tenneo-auth-plugin"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then run:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npm install
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Method 3: Direct file install**
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm install ../tenneo-auth-plugin
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
> **Note:** For local development methods, ensure you run `npm run build` in the plugin directory whenever you make changes to the plugin source code.
|
|
145
|
+
|
|
146
|
+
## Quick Start
|
|
147
|
+
|
|
148
|
+
### 1. Wrap your app with AuthProvider
|
|
149
|
+
|
|
150
|
+
**Basic Usage:**
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { AuthProvider } from '@tenneo/auth-plugin';
|
|
154
|
+
|
|
155
|
+
function App() {
|
|
156
|
+
return (
|
|
157
|
+
<AuthProvider tenantCode="your-tenant-code">
|
|
158
|
+
<YourApp />
|
|
159
|
+
</AuthProvider>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**With App ID (for storage namespacing):**
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { AuthProvider } from '@tenneo/auth-plugin';
|
|
168
|
+
|
|
169
|
+
function App() {
|
|
170
|
+
return (
|
|
171
|
+
<AuthProvider
|
|
172
|
+
tenantCode="your-tenant-code"
|
|
173
|
+
appId="my-app"
|
|
174
|
+
>
|
|
175
|
+
<YourApp />
|
|
176
|
+
</AuthProvider>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 2. Use authentication in your components
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import { useAuth } from '@tenneo/auth-plugin';
|
|
185
|
+
|
|
186
|
+
function MyComponent() {
|
|
187
|
+
const { isAuthenticated, accessToken, isLoading, logout } = useAuth();
|
|
188
|
+
|
|
189
|
+
if (isLoading) {
|
|
190
|
+
return <div>Loading...</div>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!isAuthenticated) {
|
|
194
|
+
return <div>Not authenticated</div>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div>
|
|
199
|
+
<p>Authenticated!</p>
|
|
200
|
+
<button onClick={logout}>Logout</button>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 3. Setup callback route
|
|
207
|
+
|
|
208
|
+
Add the `AuthCallback` component to handle OAuth redirects:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { AuthCallback } from '@tenneo/auth-plugin';
|
|
212
|
+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
213
|
+
|
|
214
|
+
function App() {
|
|
215
|
+
return (
|
|
216
|
+
<AuthProvider tenantCode="your-tenant-code">
|
|
217
|
+
<BrowserRouter>
|
|
218
|
+
<Routes>
|
|
219
|
+
<Route path="/callback" element={<AuthCallback successPath="/dashboard" />} />
|
|
220
|
+
<Route path="/dashboard" element={<Dashboard />} />
|
|
221
|
+
{/* ... other routes */}
|
|
222
|
+
</Routes>
|
|
223
|
+
</BrowserRouter>
|
|
224
|
+
</AuthProvider>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 4. Protect routes (optional)
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { ProtectedRoute } from '@tenneo/auth-plugin';
|
|
233
|
+
|
|
234
|
+
function App() {
|
|
235
|
+
return (
|
|
236
|
+
<AuthProvider tenantCode="your-tenant-code">
|
|
237
|
+
<BrowserRouter>
|
|
238
|
+
<Routes>
|
|
239
|
+
<Route path="/callback" element={<AuthCallback />} />
|
|
240
|
+
<Route
|
|
241
|
+
path="/dashboard"
|
|
242
|
+
element={
|
|
243
|
+
<ProtectedRoute fallback={<div>Loading...</div>}>
|
|
244
|
+
<Dashboard />
|
|
245
|
+
</ProtectedRoute>
|
|
246
|
+
}
|
|
247
|
+
/>
|
|
248
|
+
</Routes>
|
|
249
|
+
</BrowserRouter>
|
|
250
|
+
</AuthProvider>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## AuthProvider Props
|
|
256
|
+
|
|
257
|
+
| Prop | Type | Default | Description |
|
|
258
|
+
|------|------|---------|-------------|
|
|
259
|
+
| `tenantCode` | `string` | - | Tenant code used to resolve tenant configuration via API |
|
|
260
|
+
| `appId` | `string` | `''` | App identifier for storage namespacing |
|
|
261
|
+
| `autoInit` | `boolean` | `true` | Auto-initialize authentication on mount |
|
|
262
|
+
| `storageAdapter` | `StorageAdapter` | `null` | Custom storage adapter (defaults to secure session storage) |
|
|
263
|
+
|
|
264
|
+
### Configuration Priority
|
|
265
|
+
|
|
266
|
+
1. **Props** - Values passed to `AuthProvider`
|
|
267
|
+
2. **Window config** - `window.__AUTH_CONFIG__` or `window.__APP_CONFIG__`
|
|
268
|
+
3. **Environment variables** - `VITE_*` prefixed variables
|
|
269
|
+
4. **Defaults** - Built-in fallback values
|
|
270
|
+
|
|
271
|
+
## API Reference
|
|
272
|
+
|
|
273
|
+
### Hooks
|
|
274
|
+
|
|
275
|
+
#### `useAuth()`
|
|
276
|
+
|
|
277
|
+
Returns authentication state and methods:
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
const {
|
|
281
|
+
isAuthenticated: boolean; // Whether user is authenticated
|
|
282
|
+
accessToken: string | null; // Current access token
|
|
283
|
+
isLoading: boolean; // Loading state
|
|
284
|
+
error: string | null; // Error message if any
|
|
285
|
+
login: () => Promise<void>; // Trigger login flow
|
|
286
|
+
logout: () => Promise<void>; // Logout and clear session
|
|
287
|
+
refreshToken: () => Promise<string>; // Refresh access token
|
|
288
|
+
getAccessToken: () => Promise<string>; // Get valid token (auto-refresh)
|
|
289
|
+
} = useAuth();
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### `useAuthInit()`
|
|
293
|
+
|
|
294
|
+
Manual initialization hook for advanced use cases:
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
const { isLoading, error, init } = useAuthInit();
|
|
298
|
+
|
|
299
|
+
// Manually trigger initialization
|
|
300
|
+
await init();
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Components
|
|
304
|
+
|
|
305
|
+
#### `AuthCallback`
|
|
306
|
+
|
|
307
|
+
Handles OAuth callback and token exchange:
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
<AuthCallback
|
|
311
|
+
loginPath="/login" // Redirect path on error (default: '/login')
|
|
312
|
+
successPath="/dashboard" // Redirect path on success (default: '/dashboard')
|
|
313
|
+
homePath="/" // Home path fallback (default: '/')
|
|
314
|
+
/>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### `ProtectedRoute`
|
|
318
|
+
|
|
319
|
+
Wraps components that require authentication:
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
<ProtectedRoute
|
|
323
|
+
fallback={<Loading />} // Component to show while checking auth
|
|
324
|
+
autoLogin={true} // Auto-trigger login if not authenticated (default: true)
|
|
325
|
+
>
|
|
326
|
+
<ProtectedContent />
|
|
327
|
+
</ProtectedRoute>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Core Functions
|
|
331
|
+
|
|
332
|
+
#### `bootstrap()`
|
|
333
|
+
|
|
334
|
+
Initializes authentication flow (called automatically by AuthProvider):
|
|
335
|
+
|
|
336
|
+
```tsx
|
|
337
|
+
import { bootstrap } from '@tenneo/auth-plugin';
|
|
338
|
+
await bootstrap();
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### `getAccessToken()`
|
|
342
|
+
|
|
343
|
+
Gets current access token (auto-refreshes if expired):
|
|
344
|
+
|
|
345
|
+
```tsx
|
|
346
|
+
import { getAccessToken } from '@tenneo/auth-plugin';
|
|
347
|
+
const token = await getAccessToken();
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
#### `logout()`
|
|
351
|
+
|
|
352
|
+
Logs out user and clears session:
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
import { logout } from '@tenneo/auth-plugin';
|
|
356
|
+
await logout();
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Configuration
|
|
360
|
+
|
|
361
|
+
#### `Config` Object
|
|
362
|
+
|
|
363
|
+
Access resolved configuration values:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
import { Config } from '@tenneo/auth-plugin';
|
|
367
|
+
|
|
368
|
+
Config.getAuthServerUrl(); // OAuth server URL
|
|
369
|
+
Config.getClientId(); // OAuth client ID
|
|
370
|
+
Config.getTenantId(); // Resolved tenant ID
|
|
371
|
+
Config.getClientCode(); // Tenant code
|
|
372
|
+
Config.getRedirectUri(); // OAuth redirect URI
|
|
373
|
+
Config.getBasePath(); // App base path
|
|
374
|
+
Config.getAll(); // All config as object
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### `setConfig()`
|
|
378
|
+
|
|
379
|
+
Override runtime configuration:
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
import { setConfig } from '@tenneo/auth-plugin';
|
|
383
|
+
|
|
384
|
+
setConfig({
|
|
385
|
+
clientId: 'custom-client-id',
|
|
386
|
+
tenantId: 'custom-tenant-id',
|
|
387
|
+
basePath: '/my-app',
|
|
388
|
+
redirectUri: 'https://myapp.com/callback',
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Storage Adapters
|
|
393
|
+
|
|
394
|
+
Create custom storage adapters or use built-in ones:
|
|
395
|
+
|
|
396
|
+
```tsx
|
|
397
|
+
import {
|
|
398
|
+
createSecureSessionStorageAdapter,
|
|
399
|
+
createCookieStorageAdapter,
|
|
400
|
+
createMemoryStorageAdapter,
|
|
401
|
+
setStorageContext,
|
|
402
|
+
} from '@tenneo/auth-plugin';
|
|
403
|
+
|
|
404
|
+
// Session storage (default)
|
|
405
|
+
const sessionAdapter = createSecureSessionStorageAdapter({
|
|
406
|
+
tenantId: 'tenant-123',
|
|
407
|
+
appId: 'my-app'
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// Cookie storage
|
|
411
|
+
const cookieAdapter = createCookieStorageAdapter({
|
|
412
|
+
tenantId: 'tenant-123',
|
|
413
|
+
appId: 'my-app'
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// Memory storage (for testing)
|
|
417
|
+
const memoryAdapter = createMemoryStorageAdapter({
|
|
418
|
+
tenantId: 'tenant-123',
|
|
419
|
+
appId: 'my-app'
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
// Use custom adapter
|
|
423
|
+
<AuthProvider tenantCode="abc" storageAdapter={cookieAdapter}>
|
|
424
|
+
<App />
|
|
425
|
+
</AuthProvider>
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Auth Engine (Advanced)
|
|
429
|
+
|
|
430
|
+
For advanced use cases, create and manage auth engine directly:
|
|
431
|
+
|
|
432
|
+
```tsx
|
|
433
|
+
import { createAuthEngine, type AuthEngine } from '@tenneo/auth-plugin';
|
|
434
|
+
|
|
435
|
+
const engine = createAuthEngine(runtime);
|
|
436
|
+
|
|
437
|
+
// Subscribe to state changes
|
|
438
|
+
const unsubscribe = engine.subscribe((state) => {
|
|
439
|
+
console.log('Auth state:', state.status);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// Initialize
|
|
443
|
+
await engine.init();
|
|
444
|
+
|
|
445
|
+
// Get current state
|
|
446
|
+
const state = engine.getState();
|
|
447
|
+
|
|
448
|
+
// Manual operations
|
|
449
|
+
await engine.login();
|
|
450
|
+
await engine.logout();
|
|
451
|
+
await engine.refresh();
|
|
452
|
+
const token = await engine.getAccessToken();
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Events
|
|
456
|
+
|
|
457
|
+
Subscribe to authentication events:
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
import {
|
|
461
|
+
subscribeAuthEvent,
|
|
462
|
+
emitAuthEvent,
|
|
463
|
+
AuthEventNames
|
|
464
|
+
} from '@tenneo/auth-plugin';
|
|
465
|
+
|
|
466
|
+
// Subscribe to events
|
|
467
|
+
const unsubscribe = subscribeAuthEvent('auth:login', (payload) => {
|
|
468
|
+
console.log('User logged in');
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// Available events
|
|
472
|
+
AuthEventNames.LOGIN // 'auth:login'
|
|
473
|
+
AuthEventNames.LOGOUT // 'auth:logout'
|
|
474
|
+
AuthEventNames.REFRESH // 'auth:refresh'
|
|
475
|
+
AuthEventNames.ERROR // 'auth:error'
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Environment Variables
|
|
479
|
+
|
|
480
|
+
Configure the plugin via environment variables (Vite apps use `VITE_` prefix):
|
|
481
|
+
|
|
482
|
+
```env
|
|
483
|
+
# Auth Server URL - Your OAuth authorization server
|
|
484
|
+
VITE_AUTH_SERVER_URL=https://auth.example.com
|
|
485
|
+
|
|
486
|
+
# API base URLs
|
|
487
|
+
VITE_API_TENANT_RESOLUTION_BASE_URL=https://api.example.com/api/v1
|
|
488
|
+
VITE_API_AUTH_BASE_URL=https://auth.example.com
|
|
489
|
+
|
|
490
|
+
# Default values (optional)
|
|
491
|
+
VITE_CLIENT_ID=your-client-id
|
|
492
|
+
VITE_TENANT_ID=your-tenant-id
|
|
493
|
+
VITE_CLIENTCODE=your-tenant-code
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
See `.env.example` for a complete template.
|
|
497
|
+
|
|
498
|
+
## Window Configuration
|
|
499
|
+
|
|
500
|
+
For runtime configuration without rebuilding:
|
|
501
|
+
|
|
502
|
+
```html
|
|
503
|
+
<script>
|
|
504
|
+
window.__AUTH_CONFIG__ = {
|
|
505
|
+
clientId: 'runtime-client-id',
|
|
506
|
+
tenantId: 'runtime-tenant-id',
|
|
507
|
+
basePath: '/my-app',
|
|
508
|
+
};
|
|
509
|
+
</script>
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
## Architecture
|
|
513
|
+
|
|
514
|
+
```
|
|
515
|
+
@tenneo/auth-plugin/
|
|
516
|
+
└── src/
|
|
517
|
+
├── index.ts # Main exports
|
|
518
|
+
├── application/ # Application layer (bootstrap, flows, engine)
|
|
519
|
+
│ ├── bootstrap.ts # Auth initialization
|
|
520
|
+
│ ├── engine/ # Auth state machine
|
|
521
|
+
│ ├── flows/ # OAuth flow implementations
|
|
522
|
+
│ └── events/ # Event system
|
|
523
|
+
├── infrastructure/ # Infrastructure adapters
|
|
524
|
+
│ ├── storage/ # Storage adapters
|
|
525
|
+
│ ├── runtime/ # Runtime context
|
|
526
|
+
│ ├── tenant/ # Tenant resolution
|
|
527
|
+
│ └── watchers/ # Storage/cookie watchers
|
|
528
|
+
├── strategies/ # Auth strategies
|
|
529
|
+
│ └── oauth2-pkce/ # OAuth 2.0 PKCE implementation
|
|
530
|
+
├── context/ # React Context
|
|
531
|
+
├── components/ # React components
|
|
532
|
+
├── hooks/ # React hooks
|
|
533
|
+
├── config/ # Configuration
|
|
534
|
+
├── domain/ # Domain types
|
|
535
|
+
└── utils/ # Utilities
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
## Storage Keys
|
|
539
|
+
|
|
540
|
+
Authentication data is stored with namespaced keys (`auth_{tenantId}_{appId}_*`):
|
|
541
|
+
|
|
542
|
+
- `*_access_token` - Current access token
|
|
543
|
+
- `*_refresh_token` - Refresh token
|
|
544
|
+
- `*_expires_at` - Token expiration timestamp
|
|
545
|
+
- `*_id_token` - ID token (if provided)
|
|
546
|
+
- `*_tenant_id` - Resolved tenant ID
|
|
547
|
+
- `*_tenant_key` - Tenant code/key
|
|
548
|
+
- `*_code_verifier` - PKCE code verifier (temporary)
|
|
549
|
+
- `*_state` - OAuth state parameter (temporary)
|
|
550
|
+
|
|
551
|
+
## TypeScript Types
|
|
552
|
+
|
|
553
|
+
All types are exported for use in your application:
|
|
554
|
+
|
|
555
|
+
```tsx
|
|
556
|
+
import type {
|
|
557
|
+
TenantConfig,
|
|
558
|
+
TokenResponse,
|
|
559
|
+
AuthState,
|
|
560
|
+
AuthContextValue,
|
|
561
|
+
EnvConfig,
|
|
562
|
+
AuthTokens,
|
|
563
|
+
StorageAdapter,
|
|
564
|
+
AuthEngine,
|
|
565
|
+
AuthEngineState,
|
|
566
|
+
SDKConfig,
|
|
567
|
+
RuntimeConfigOverrides,
|
|
568
|
+
} from '@tenneo/auth-plugin';
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Security
|
|
572
|
+
|
|
573
|
+
- PKCE (Proof Key for Code Exchange) prevents authorization code interception
|
|
574
|
+
- Tokens stored in sessionStorage (cleared on tab close)
|
|
575
|
+
- Automatic HTTPS enforcement in production
|
|
576
|
+
- State parameter validation prevents CSRF attacks
|
|
577
|
+
- Secure cookie options for cookie-based storage
|
|
578
|
+
|
|
579
|
+
npm run clean # Remove dist/
|
|
580
|
+
npm run build # Build with tsup
|
|
581
|
+
npm run dev # Watch mode
|
|
582
|
+
npm run type-check # TypeScript check
|
|
583
|
+
npm run release:beta # Publish beta version (restricted)
|
|
584
|
+
npm run release:minor # Publish minor version (restricted)
|
|
585
|
+
npm run release:major # Publish major version (restricted)
|
|
586
|
+
|
|
587
|
+
Publishing
|
|
588
|
+
npm login
|
|
589
|
+
npm run release:beta # First beta release
|
|
590
|
+
|
|
591
|
+
Consumers install via:
|
|
592
|
+
npm install @tenneo/auth-plugin@beta
|
|
593
|
+
|
|
594
|
+
## License
|
|
595
|
+
|
|
596
|
+
MIT
|