tenneo-auth-gateway-plugin 1.0.7
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 +422 -0
- package/dist/index.d.mts +626 -0
- package/dist/index.d.ts +626 -0
- package/dist/index.js +3585 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3520 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# tenneo-auth-plugin
|
|
2
|
+
|
|
3
|
+
Production-ready React authentication plugin with OAuth 2.0 PKCE support for enterprise applications.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/tenneo-auth-plugin)
|
|
6
|
+
[](https://www.npmjs.com/package/tenneo-auth-plugin)
|
|
7
|
+
[](https://www.npmjs.com/package/tenneo-auth-plugin)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
tenneo-auth-plugin is a comprehensive authentication solution designed for modern React applications. It implements the OAuth 2.0 Authorization Code flow with PKCE (Proof Key for Code Exchange), providing secure authentication without exposing client secrets in browser-based applications.
|
|
12
|
+
|
|
13
|
+
The plugin features a robust multi-tenant architecture that automatically resolves tenant configuration based on tenant codes. This makes it ideal for SaaS platforms and enterprise applications where multiple tenants share the same codebase but require isolated authentication contexts.
|
|
14
|
+
|
|
15
|
+
Built with TypeScript and following clean architecture principles, the plugin handles the complete token lifecycle including automatic refresh, secure storage, and session management. The React Context API integration provides a seamless developer experience with hooks-based access to authentication state and methods.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install tenneo-auth-plugin
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Requirements
|
|
24
|
+
|
|
25
|
+
- React 18 or higher
|
|
26
|
+
- React DOM 18 or higher
|
|
27
|
+
- React Router (recommended for callback handling)
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### 1. Wrap your application with AuthProvider
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { AuthProvider } from 'tenneo-auth-plugin';
|
|
35
|
+
|
|
36
|
+
function App() {
|
|
37
|
+
return (
|
|
38
|
+
<AuthProvider tenantCode="your-tenant-code">
|
|
39
|
+
<YourApplication />
|
|
40
|
+
</AuthProvider>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Access authentication state with useAuth
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { useAuth } from 'tenneo-auth-plugin';
|
|
49
|
+
|
|
50
|
+
function Dashboard() {
|
|
51
|
+
const { isAuthenticated, isLoading, accessToken, logout } = useAuth();
|
|
52
|
+
|
|
53
|
+
if (isLoading) {
|
|
54
|
+
return <div>Loading...</div>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!isAuthenticated) {
|
|
58
|
+
return <div>Please log in to continue.</div>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div>
|
|
63
|
+
<h1>Welcome to Dashboard</h1>
|
|
64
|
+
<button onClick={logout}>Sign Out</button>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. Handle OAuth callback
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { AuthCallback } from 'tenneo-auth-plugin';
|
|
74
|
+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
75
|
+
|
|
76
|
+
function App() {
|
|
77
|
+
return (
|
|
78
|
+
<AuthProvider tenantCode="your-tenant-code">
|
|
79
|
+
<BrowserRouter>
|
|
80
|
+
<Routes>
|
|
81
|
+
<Route
|
|
82
|
+
path="/callback"
|
|
83
|
+
element={
|
|
84
|
+
<AuthCallback
|
|
85
|
+
successPath="/dashboard"
|
|
86
|
+
loginPath="/login"
|
|
87
|
+
/>
|
|
88
|
+
}
|
|
89
|
+
/>
|
|
90
|
+
<Route path="/dashboard" element={<Dashboard />} />
|
|
91
|
+
</Routes>
|
|
92
|
+
</BrowserRouter>
|
|
93
|
+
</AuthProvider>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 4. Protect routes
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import { ProtectedRoute } from 'tenneo-auth-plugin';
|
|
102
|
+
|
|
103
|
+
function App() {
|
|
104
|
+
return (
|
|
105
|
+
<AuthProvider tenantCode="your-tenant-code">
|
|
106
|
+
<BrowserRouter>
|
|
107
|
+
<Routes>
|
|
108
|
+
<Route path="/callback" element={<AuthCallback />} />
|
|
109
|
+
<Route
|
|
110
|
+
path="/dashboard"
|
|
111
|
+
element={
|
|
112
|
+
<ProtectedRoute fallback={<div>Authenticating...</div>}>
|
|
113
|
+
<Dashboard />
|
|
114
|
+
</ProtectedRoute>
|
|
115
|
+
}
|
|
116
|
+
/>
|
|
117
|
+
</Routes>
|
|
118
|
+
</BrowserRouter>
|
|
119
|
+
</AuthProvider>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Features
|
|
125
|
+
|
|
126
|
+
- OAuth 2.0 PKCE flow for secure browser-based authentication
|
|
127
|
+
- Automatic token refresh before expiration
|
|
128
|
+
- Multi-tenant support with automatic tenant resolution
|
|
129
|
+
- Pluggable storage adapters (session, cookie, memory)
|
|
130
|
+
- Authentication event system for observability
|
|
131
|
+
- Strict TypeScript definitions throughout
|
|
132
|
+
- Host-driven configuration (props / `setConfig()`)
|
|
133
|
+
- Clean layered architecture
|
|
134
|
+
- Tree-shakeable ESM and CJS builds
|
|
135
|
+
- React 18+ compatibility
|
|
136
|
+
|
|
137
|
+
## AuthProvider Props
|
|
138
|
+
|
|
139
|
+
| Prop | Type | Required | Default | Description |
|
|
140
|
+
|------|------|----------|---------|-------------|
|
|
141
|
+
| `config` | `SDKConfig` | No | - | Pass all configuration as a single object (alternative to individual props) |
|
|
142
|
+
| `tenantCode` | `string` | No | - | Tenant code for configuration resolution |
|
|
143
|
+
| `apiBaseUrl` | `string` | Yes | - | Tenant resolution service base URL |
|
|
144
|
+
| `authServerUrl` | `string` | Yes | - | Authorization server base URL (OIDC authorize) |
|
|
145
|
+
| `callbackUrl` | `string` | Yes | - | Full callback/redirect URL |
|
|
146
|
+
| `appId` | `string` | No | `''` | Application identifier for storage namespacing |
|
|
147
|
+
| `autoInit` | `boolean` | No | `true` | Automatically initialize authentication on mount |
|
|
148
|
+
| `storageAdapter` | `StorageAdapter` | No | `null` | Custom storage adapter instance |
|
|
149
|
+
|
|
150
|
+
## Hooks API
|
|
151
|
+
|
|
152
|
+
### useAuth()
|
|
153
|
+
|
|
154
|
+
Primary hook for accessing authentication state and methods.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { useAuth } from 'tenneo-auth-plugin';
|
|
158
|
+
|
|
159
|
+
function Component() {
|
|
160
|
+
const {
|
|
161
|
+
isAuthenticated, // boolean - Current authentication status
|
|
162
|
+
accessToken, // string | null - Current access token
|
|
163
|
+
isLoading, // boolean - Loading state during auth operations
|
|
164
|
+
error, // string | null - Error message if any
|
|
165
|
+
login, // () => Promise<void> - Trigger login flow
|
|
166
|
+
logout, // () => Promise<void> - Sign out and clear session
|
|
167
|
+
refreshToken, // () => Promise<string> - Manually refresh token
|
|
168
|
+
getAccessToken, // () => Promise<string> - Get valid token (auto-refresh)
|
|
169
|
+
} = useAuth();
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### useAuthInit()
|
|
174
|
+
|
|
175
|
+
Hook for manual authentication initialization.
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { useAuthInit } from 'tenneo-auth-plugin';
|
|
179
|
+
|
|
180
|
+
function Component() {
|
|
181
|
+
const {
|
|
182
|
+
isLoading, // boolean - Initialization in progress
|
|
183
|
+
error, // string | null - Initialization error
|
|
184
|
+
init, // () => Promise<void> - Trigger initialization
|
|
185
|
+
} = useAuthInit();
|
|
186
|
+
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
init();
|
|
189
|
+
}, [init]);
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Components
|
|
194
|
+
|
|
195
|
+
### AuthCallback
|
|
196
|
+
|
|
197
|
+
Handles OAuth authorization callback and token exchange.
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import { AuthCallback } from 'tenneo-auth-plugin';
|
|
201
|
+
|
|
202
|
+
<AuthCallback
|
|
203
|
+
loginPath="/login" // Redirect on error (default: '/login')
|
|
204
|
+
successPath="/dashboard" // Redirect on success (default: '/dashboard')
|
|
205
|
+
homePath="/" // Fallback path (default: '/')
|
|
206
|
+
/>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### ProtectedRoute
|
|
210
|
+
|
|
211
|
+
Wrapper component that ensures authentication before rendering children.
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { ProtectedRoute } from 'tenneo-auth-plugin';
|
|
215
|
+
|
|
216
|
+
<ProtectedRoute
|
|
217
|
+
fallback={<LoadingSpinner />} // Shown while checking auth
|
|
218
|
+
autoLogin={true} // Auto-redirect to login (default: true)
|
|
219
|
+
>
|
|
220
|
+
<ProtectedContent />
|
|
221
|
+
</ProtectedRoute>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Core API
|
|
225
|
+
|
|
226
|
+
### bootstrap()
|
|
227
|
+
|
|
228
|
+
Initializes the authentication flow. Called automatically by AuthProvider when `autoInit` is true.
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
import { bootstrap } from 'tenneo-auth-plugin';
|
|
232
|
+
|
|
233
|
+
await bootstrap();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### getAccessToken()
|
|
237
|
+
|
|
238
|
+
Retrieves a valid access token, automatically refreshing if expired.
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
import { getAccessToken } from 'tenneo-auth-plugin';
|
|
242
|
+
|
|
243
|
+
const token = await getAccessToken();
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### logout()
|
|
247
|
+
|
|
248
|
+
Signs out the user and clears all authentication data.
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { logout } from 'tenneo-auth-plugin';
|
|
252
|
+
|
|
253
|
+
await logout();
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### createAuthEngine()
|
|
257
|
+
|
|
258
|
+
Creates an authentication engine instance for advanced use cases.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
import { createAuthEngine } from 'tenneo-auth-plugin';
|
|
262
|
+
|
|
263
|
+
const engine = createAuthEngine(runtime);
|
|
264
|
+
|
|
265
|
+
// Subscribe to state changes
|
|
266
|
+
const unsubscribe = engine.subscribe((state) => {
|
|
267
|
+
console.log('Status:', state.status);
|
|
268
|
+
console.log('Token:', state.accessToken);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Initialize
|
|
272
|
+
await engine.init();
|
|
273
|
+
|
|
274
|
+
// Operations
|
|
275
|
+
await engine.login();
|
|
276
|
+
await engine.logout();
|
|
277
|
+
const token = await engine.getAccessToken();
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Configuration
|
|
281
|
+
|
|
282
|
+
### Host app configuration (required)
|
|
283
|
+
|
|
284
|
+
This SDK does **not** read `.env` or `window.__AUTH_CONFIG__`. Provide configuration from your host app:
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
import { AuthProvider } from 'tenneo-auth-plugin';
|
|
288
|
+
|
|
289
|
+
<AuthProvider
|
|
290
|
+
tenantCode="your-tenant-code"
|
|
291
|
+
apiBaseUrl="https://tenant-service.example.com"
|
|
292
|
+
authServerUrl="https://auth.example.com"
|
|
293
|
+
callbackUrl="https://app.example.com/callback"
|
|
294
|
+
appId="myapp"
|
|
295
|
+
>
|
|
296
|
+
<App />
|
|
297
|
+
</AuthProvider>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Programmatic Configuration
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
import { setConfig, Config } from 'tenneo-auth-plugin';
|
|
304
|
+
|
|
305
|
+
// Override configuration (host-driven)
|
|
306
|
+
setConfig({
|
|
307
|
+
tenantCode: 'your-tenant-code',
|
|
308
|
+
apiBaseUrl: 'https://tenant-service.example.com',
|
|
309
|
+
authServerUrl: 'https://auth.example.com',
|
|
310
|
+
callbackUrl: 'https://app.example.com/callback',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Access resolved configuration
|
|
314
|
+
const authServerUrl = Config.getAuthServerUrl();
|
|
315
|
+
const allConfig = Config.getAll();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
## Security
|
|
320
|
+
|
|
321
|
+
### PKCE Protection
|
|
322
|
+
|
|
323
|
+
The plugin implements PKCE (Proof Key for Code Exchange) to prevent authorization code interception attacks. A cryptographically random code verifier is generated for each authentication request and never transmitted to the authorization server.
|
|
324
|
+
|
|
325
|
+
### CSRF Protection
|
|
326
|
+
|
|
327
|
+
OAuth state parameter validation prevents cross-site request forgery attacks. Each authentication request includes a unique state value that is verified during the callback.
|
|
328
|
+
|
|
329
|
+
### Token Isolation
|
|
330
|
+
|
|
331
|
+
Authentication tokens are stored with tenant-specific namespacing, ensuring complete isolation between different tenants in multi-tenant deployments.
|
|
332
|
+
|
|
333
|
+
### HTTPS Enforcement
|
|
334
|
+
|
|
335
|
+
Production environments automatically enforce HTTPS for all authentication-related requests and redirects.
|
|
336
|
+
|
|
337
|
+
### Session Security
|
|
338
|
+
|
|
339
|
+
Tokens are stored in sessionStorage by default, ensuring they are cleared when the browser tab is closed. For enhanced security requirements, custom storage adapters can be configured.
|
|
340
|
+
|
|
341
|
+
## Storage Adapters
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
import {
|
|
345
|
+
createSecureSessionStorageAdapter,
|
|
346
|
+
createCookieStorageAdapter,
|
|
347
|
+
createMemoryStorageAdapter,
|
|
348
|
+
} from 'tenneo-auth-plugin';
|
|
349
|
+
|
|
350
|
+
// Session storage (default, cleared on tab close)
|
|
351
|
+
const sessionAdapter = createSecureSessionStorageAdapter({
|
|
352
|
+
tenantId: 'tenant-123',
|
|
353
|
+
appId: 'my-app'
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Cookie storage (persistent)
|
|
357
|
+
const cookieAdapter = createCookieStorageAdapter({
|
|
358
|
+
tenantId: 'tenant-123',
|
|
359
|
+
appId: 'my-app'
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// Memory storage (testing)
|
|
363
|
+
const memoryAdapter = createMemoryStorageAdapter({
|
|
364
|
+
tenantId: 'tenant-123',
|
|
365
|
+
appId: 'my-app'
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// Use custom adapter
|
|
369
|
+
<AuthProvider tenantCode="abc" storageAdapter={sessionAdapter}>
|
|
370
|
+
<App />
|
|
371
|
+
</AuthProvider>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Events
|
|
375
|
+
|
|
376
|
+
Subscribe to authentication events for logging, analytics, or custom behavior.
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
import { subscribeAuthEvent, AuthEventNames } from 'tenneo-auth-plugin';
|
|
380
|
+
|
|
381
|
+
// Subscribe to login events
|
|
382
|
+
const unsubscribe = subscribeAuthEvent(AuthEventNames.LOGIN, (payload) => {
|
|
383
|
+
console.log('User authenticated');
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Available events
|
|
387
|
+
AuthEventNames.LOGIN // User successfully authenticated
|
|
388
|
+
AuthEventNames.LOGOUT // User signed out
|
|
389
|
+
AuthEventNames.REFRESH // Token refreshed
|
|
390
|
+
AuthEventNames.ERROR // Authentication error occurred
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## TypeScript Support
|
|
394
|
+
|
|
395
|
+
All types are exported for use in TypeScript applications.
|
|
396
|
+
|
|
397
|
+
```tsx
|
|
398
|
+
import type {
|
|
399
|
+
TenantConfig,
|
|
400
|
+
TokenResponse,
|
|
401
|
+
AuthState,
|
|
402
|
+
AuthContextValue,
|
|
403
|
+
AuthTokens,
|
|
404
|
+
StorageAdapter,
|
|
405
|
+
AuthEngine,
|
|
406
|
+
AuthEngineState,
|
|
407
|
+
SDKConfig,
|
|
408
|
+
} from 'tenneo-auth-plugin';
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
## Versioning
|
|
412
|
+
|
|
413
|
+
This package follows Semantic Versioning (SemVer):
|
|
414
|
+
|
|
415
|
+
- **Major versions** contain breaking changes
|
|
416
|
+
- **Minor versions** add backward-compatible features
|
|
417
|
+
- **Patch versions** include backward-compatible bug fixes
|
|
418
|
+
- **Beta versions** are pre-release versions for testing
|
|
419
|
+
|
|
420
|
+
## License
|
|
421
|
+
|
|
422
|
+
MIT
|