@owlmeans/web-oidc-rp 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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +515 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/auth/plugins/index.d.ts +4 -0
  5. package/build/auth/plugins/index.d.ts.map +1 -0
  6. package/build/auth/plugins/index.js +6 -0
  7. package/build/auth/plugins/index.js.map +1 -0
  8. package/build/auth/plugins/oidc-client.d.ts +3 -0
  9. package/build/auth/plugins/oidc-client.d.ts.map +1 -0
  10. package/build/auth/plugins/oidc-client.js +97 -0
  11. package/build/auth/plugins/oidc-client.js.map +1 -0
  12. package/build/components/dispatcher.d.ts +2 -0
  13. package/build/components/dispatcher.d.ts.map +1 -0
  14. package/build/components/dispatcher.js +58 -0
  15. package/build/components/dispatcher.js.map +1 -0
  16. package/build/components/index.d.ts +2 -0
  17. package/build/components/index.d.ts.map +1 -0
  18. package/build/components/index.js +2 -0
  19. package/build/components/index.js.map +1 -0
  20. package/build/consts.d.ts +7 -0
  21. package/build/consts.d.ts.map +1 -0
  22. package/build/consts.js +8 -0
  23. package/build/consts.js.map +1 -0
  24. package/build/guard.d.ts +6 -0
  25. package/build/guard.d.ts.map +1 -0
  26. package/build/guard.js +18 -0
  27. package/build/guard.js.map +1 -0
  28. package/build/index.d.ts +6 -0
  29. package/build/index.d.ts.map +1 -0
  30. package/build/index.js +5 -0
  31. package/build/index.js.map +1 -0
  32. package/build/service.d.ts +3 -0
  33. package/build/service.d.ts.map +1 -0
  34. package/build/service.js +112 -0
  35. package/build/service.js.map +1 -0
  36. package/build/types.d.ts +25 -0
  37. package/build/types.d.ts.map +1 -0
  38. package/build/types.js +2 -0
  39. package/build/types.js.map +1 -0
  40. package/package.json +60 -0
  41. package/src/auth/plugins/index.ts +8 -0
  42. package/src/auth/plugins/oidc-client.tsx +114 -0
  43. package/src/components/dispatcher.tsx +61 -0
  44. package/src/components/index.ts +2 -0
  45. package/src/consts.ts +8 -0
  46. package/src/guard.ts +31 -0
  47. package/src/index.ts +6 -0
  48. package/src/service.ts +147 -0
  49. package/src/types.ts +32 -0
  50. package/tsconfig.json +16 -0
  51. package/tsconfig.tsbuildinfo +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,515 @@
1
+ # @owlmeans/web-oidc-rp
2
+
3
+ The **@owlmeans/web-oidc-rp** package provides web client-side OpenID Connect Relying Party (RP) functionality for OwlMeans Common Libraries, enabling secure authentication and authorization through OIDC protocols in React-based frontend applications.
4
+
5
+ ## Purpose
6
+
7
+ This package serves as a comprehensive OIDC client implementation for web applications, specifically designed for:
8
+
9
+ - **Frontend OIDC Authentication**: Handle OIDC authentication flows in React applications
10
+ - **Flow Integration**: Integrate with OwlMeans flow system for complex authentication workflows
11
+ - **Automatic Token Management**: Handle OIDC authentication callbacks and token processing
12
+ - **React Components**: Provide ready-to-use React components for OIDC integration
13
+ - **Server Communication**: Coordinate with server-side OIDC relying party implementation
14
+ - **Authentication State Management**: Manage authentication state across the application
15
+
16
+ ## Key Concepts
17
+
18
+ ### Web-based OIDC Relying Party
19
+ This package implements the client-side portion of OIDC authentication, handling redirects, callbacks, and token management in web browsers.
20
+
21
+ ### Flow-based Authentication
22
+ Integrates with the OwlMeans flow system to support complex authentication workflows that may involve multiple steps and decision points.
23
+
24
+ ### Server-Client Coordination
25
+ Works in tandem with `@owlmeans/server-oidc-rp` to provide a complete OIDC solution where the server handles sensitive operations and the client manages user interactions.
26
+
27
+ ### Authentication Dispatcher
28
+ Provides a dispatcher component that automatically handles OIDC callbacks and coordinates authentication state.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ npm install @owlmeans/web-oidc-rp
34
+ ```
35
+
36
+ ## API Reference
37
+
38
+ ### Types
39
+
40
+ #### `OidcAuthService`
41
+ Main service interface for web-based OIDC operations.
42
+
43
+ ```typescript
44
+ interface OidcAuthService extends InitializedService {
45
+ dispatch(params: Record<string, string>): Promise<boolean>
46
+ authenticate(flow: FlowModel, params: OIDCAuthInitParams): Promise<string | null>
47
+ proceedToRedirectUrl(extras: OidcAuthRedirectExtras): Promise<string>
48
+ dispatchClientOnly(): Promise<void>
49
+ }
50
+ ```
51
+
52
+ #### `OidcAuthRedirectExtras`
53
+ Configuration for OIDC redirect operations.
54
+
55
+ ```typescript
56
+ interface OidcAuthRedirectExtras extends FlowPayload {
57
+ purpose: OidcAuthPurposes
58
+ uid?: string
59
+ alias?: string
60
+ }
61
+ ```
62
+
63
+ #### `OidcInteraction`
64
+ Resource record for storing OIDC interaction data.
65
+
66
+ ```typescript
67
+ interface OidcInteraction extends ResourceRecord {
68
+ authUrl: string
69
+ }
70
+ ```
71
+
72
+ #### `Config`
73
+ Configuration interface extending AppConfig.
74
+
75
+ ```typescript
76
+ interface Config extends AppConfig, WithSharedConfig { }
77
+ ```
78
+
79
+ #### `Context`
80
+ Context interface for web applications.
81
+
82
+ ```typescript
83
+ interface Context<C extends Config = Config> extends AppContext<C> { }
84
+ ```
85
+
86
+ ### Enums
87
+
88
+ #### `OidcAuthPurposes`
89
+ Enumeration of OIDC authentication purposes.
90
+
91
+ ```typescript
92
+ enum OidcAuthPurposes {
93
+ Unknown = 'unknown',
94
+ Subscribe = 'subscribe',
95
+ Login = 'login'
96
+ }
97
+ ```
98
+
99
+ ### Factory Functions
100
+
101
+ #### `makeOidcAuthService(alias?: string): OidcAuthService`
102
+
103
+ Creates an OIDC authentication service instance for web applications.
104
+
105
+ **Parameters:**
106
+ - `alias`: Service alias (defaults to 'oidc-rp')
107
+
108
+ **Returns:** OidcAuthService instance
109
+
110
+ ```typescript
111
+ import { makeOidcAuthService } from '@owlmeans/web-oidc-rp'
112
+
113
+ const oidcService = makeOidcAuthService('web-oidc-auth')
114
+ ```
115
+
116
+ ### React Components
117
+
118
+ #### `Dispatcher`
119
+ Higher-order component that handles OIDC authentication callbacks and token processing.
120
+
121
+ ```typescript
122
+ const Dispatcher = DispatcherHOC(({ provideToken, navigate }) => {
123
+ // Component implementation handles OIDC callback processing
124
+ })
125
+ ```
126
+
127
+ **Props:**
128
+ - `provideToken`: Function to provide authentication tokens
129
+ - `navigate`: Function to handle navigation after authentication
130
+
131
+ ### Constants
132
+
133
+ #### Service Configuration
134
+ ```typescript
135
+ const DEFAULT_ALIAS = 'oidc-rp'
136
+ ```
137
+
138
+ ## Usage Examples
139
+
140
+ ### Basic Setup
141
+
142
+ ```typescript
143
+ import { makeOidcAuthService } from '@owlmeans/web-oidc-rp'
144
+ import { makeAppContext, makeAppConfig } from '@owlmeans/web-client'
145
+
146
+ // Create app context with OIDC configuration
147
+ const config = makeAppConfig('web-app', {
148
+ oidc: {
149
+ // OIDC configuration shared with server
150
+ }
151
+ })
152
+
153
+ const context = makeAppContext(config)
154
+
155
+ // Create and register OIDC service
156
+ const oidcService = makeOidcAuthService()
157
+ context.registerService(oidcService)
158
+
159
+ // Initialize context
160
+ await context.configure().init()
161
+ ```
162
+
163
+ ### React Application Integration
164
+
165
+ ```typescript
166
+ import React from 'react'
167
+ import { BrowserRouter, Routes, Route } from 'react-router-dom'
168
+ import { Dispatcher } from '@owlmeans/web-oidc-rp'
169
+
170
+ function App() {
171
+ return (
172
+ <BrowserRouter>
173
+ <Routes>
174
+ <Route path="/auth/callback" element={<Dispatcher />} />
175
+ <Route path="/login" element={<LoginPage />} />
176
+ <Route path="/dashboard" element={<Dashboard />} />
177
+ </Routes>
178
+ </BrowserRouter>
179
+ )
180
+ }
181
+
182
+ function LoginPage() {
183
+ const context = useContext()
184
+ const oidcService = context.service<OidcAuthService>('oidc-rp')
185
+
186
+ const handleOidcLogin = async () => {
187
+ const flow = await context.service<FlowService>('flow').createFlow('oidc-auth')
188
+ const redirectUrl = await oidcService.authenticate(flow, {
189
+ entity: 'my-organization',
190
+ profile: 'user-profile'
191
+ })
192
+
193
+ if (redirectUrl) {
194
+ window.location.href = redirectUrl
195
+ }
196
+ }
197
+
198
+ return (
199
+ <div>
200
+ <button onClick={handleOidcLogin}>
201
+ Login with OIDC
202
+ </button>
203
+ </div>
204
+ )
205
+ }
206
+ ```
207
+
208
+ ### OIDC Authentication Flow
209
+
210
+ ```typescript
211
+ import { useFlow } from '@owlmeans/web-flow'
212
+ import { useContext } from '@owlmeans/web-client'
213
+ import { OidcAuthService } from '@owlmeans/web-oidc-rp'
214
+
215
+ function useOidcAuth() {
216
+ const context = useContext()
217
+ const flowClient = useFlow()
218
+ const oidcService = context.service<OidcAuthService>('oidc-rp')
219
+
220
+ const initiateAuth = async (entityId: string, profileId?: string) => {
221
+ if (!flowClient) return null
222
+
223
+ const flow = flowClient.flow()
224
+ const redirectUrl = await oidcService.authenticate(flow, {
225
+ entity: entityId,
226
+ profile: profileId
227
+ })
228
+
229
+ return redirectUrl
230
+ }
231
+
232
+ const handleCallback = async (urlParams: URLSearchParams) => {
233
+ const params: Record<string, string> = {}
234
+ urlParams.forEach((value, key) => {
235
+ params[key] = value
236
+ })
237
+
238
+ return await oidcService.dispatch(params)
239
+ }
240
+
241
+ return { initiateAuth, handleCallback }
242
+ }
243
+ ```
244
+
245
+ ### Custom Dispatcher Implementation
246
+
247
+ ```typescript
248
+ import { useSearchParams } from 'react-router-dom'
249
+ import { useEffect, useState } from 'react'
250
+ import { useContext } from '@owlmeans/web-client'
251
+ import { OidcAuthService } from '@owlmeans/web-oidc-rp'
252
+
253
+ function CustomOidcDispatcher() {
254
+ const [searchParams] = useSearchParams()
255
+ const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading')
256
+ const context = useContext()
257
+
258
+ useEffect(() => {
259
+ const processCallback = async () => {
260
+ try {
261
+ const oidcService = context.service<OidcAuthService>('oidc-rp')
262
+
263
+ const params: Record<string, string> = {}
264
+ searchParams.forEach((value, key) => {
265
+ params[key] = value
266
+ })
267
+
268
+ const success = await oidcService.dispatch(params)
269
+
270
+ if (success) {
271
+ setStatus('success')
272
+ // Redirect to intended destination
273
+ window.location.href = '/dashboard'
274
+ } else {
275
+ setStatus('error')
276
+ }
277
+ } catch (error) {
278
+ console.error('OIDC callback processing failed:', error)
279
+ setStatus('error')
280
+ }
281
+ }
282
+
283
+ processCallback()
284
+ }, [searchParams])
285
+
286
+ return (
287
+ <div>
288
+ {status === 'loading' && <div>Processing authentication...</div>}
289
+ {status === 'success' && <div>Authentication successful, redirecting...</div>}
290
+ {status === 'error' && <div>Authentication failed. Please try again.</div>}
291
+ </div>
292
+ )
293
+ }
294
+ ```
295
+
296
+ ### Flow-based Authentication
297
+
298
+ ```typescript
299
+ import { FlowModel } from '@owlmeans/flow'
300
+ import { OIDCAuthInitParams } from '@owlmeans/oidc'
301
+
302
+ function FlowBasedAuth() {
303
+ const context = useContext()
304
+ const oidcService = context.service<OidcAuthService>('oidc-rp')
305
+
306
+ const startAuthFlow = async () => {
307
+ // Create or get current flow
308
+ const flowService = context.service<FlowService>('flow')
309
+ const flow = await flowService.createFlow('oidc-authentication')
310
+
311
+ // Configure OIDC parameters
312
+ const params: OIDCAuthInitParams = {
313
+ entity: 'my-organization',
314
+ profile: 'default',
315
+ purpose: 'login'
316
+ }
317
+
318
+ // Start authentication
319
+ const redirectUrl = await oidcService.authenticate(flow, params)
320
+
321
+ if (redirectUrl) {
322
+ // Store flow state before redirect
323
+ await flowService.persistFlow()
324
+
325
+ // Redirect to OIDC provider
326
+ window.location.href = redirectUrl
327
+ }
328
+ }
329
+
330
+ return (
331
+ <button onClick={startAuthFlow}>
332
+ Start Secure Login Flow
333
+ </button>
334
+ )
335
+ }
336
+ ```
337
+
338
+ ### Advanced Redirect Handling
339
+
340
+ ```typescript
341
+ import { OidcAuthRedirectExtras, OidcAuthPurposes } from '@owlmeans/web-oidc-rp'
342
+
343
+ async function handleComplexRedirect(
344
+ oidcService: OidcAuthService,
345
+ purpose: OidcAuthPurposes,
346
+ userId?: string
347
+ ) {
348
+ const extras: OidcAuthRedirectExtras = {
349
+ purpose,
350
+ uid: userId,
351
+ alias: 'dashboard'
352
+ }
353
+
354
+ try {
355
+ const finalUrl = await oidcService.proceedToRedirectUrl(extras)
356
+ window.location.href = finalUrl
357
+ } catch (error) {
358
+ console.error('Redirect processing failed:', error)
359
+ // Handle error appropriately
360
+ }
361
+ }
362
+ ```
363
+
364
+ ### Integration with Authentication Guards
365
+
366
+ ```typescript
367
+ import { useAuth } from '@owlmeans/client-auth'
368
+ import { Navigate } from 'react-router-dom'
369
+
370
+ function ProtectedRoute({ children }: { children: React.ReactNode }) {
371
+ const auth = useAuth()
372
+ const context = useContext()
373
+ const oidcService = context.service<OidcAuthService>('oidc-rp')
374
+
375
+ useEffect(() => {
376
+ const checkAuth = async () => {
377
+ const token = await auth.authenticated()
378
+ if (!token) {
379
+ // Initiate OIDC authentication
380
+ const flow = await context.service<FlowService>('flow').createFlow('auth')
381
+ const redirectUrl = await oidcService.authenticate(flow, {
382
+ entity: 'default'
383
+ })
384
+
385
+ if (redirectUrl) {
386
+ window.location.href = redirectUrl
387
+ }
388
+ }
389
+ }
390
+
391
+ checkAuth()
392
+ }, [])
393
+
394
+ const isAuthenticated = auth.isAuthenticated()
395
+
396
+ if (!isAuthenticated) {
397
+ return <Navigate to="/login" replace />
398
+ }
399
+
400
+ return <>{children}</>
401
+ }
402
+ ```
403
+
404
+ ## Error Handling
405
+
406
+ ```typescript
407
+ import { useEffect, useState } from 'react'
408
+ import { OidcAuthService } from '@owlmeans/web-oidc-rp'
409
+
410
+ function useOidcErrorHandling() {
411
+ const [error, setError] = useState<string | null>(null)
412
+ const context = useContext()
413
+
414
+ const handleOidcOperation = async (operation: () => Promise<any>) => {
415
+ try {
416
+ setError(null)
417
+ return await operation()
418
+ } catch (err) {
419
+ const errorMessage = err instanceof Error ? err.message : 'OIDC operation failed'
420
+ setError(errorMessage)
421
+
422
+ // Log error for debugging
423
+ console.error('OIDC Error:', err)
424
+
425
+ // Could also send to error reporting service
426
+ return null
427
+ }
428
+ }
429
+
430
+ return { error, handleOidcOperation }
431
+ }
432
+ ```
433
+
434
+ ## Integration Patterns
435
+
436
+ ### Routing Integration
437
+
438
+ ```typescript
439
+ import { Routes, Route } from 'react-router-dom'
440
+ import { Dispatcher } from '@owlmeans/web-oidc-rp'
441
+
442
+ function AppRoutes() {
443
+ return (
444
+ <Routes>
445
+ {/* OIDC callback route */}
446
+ <Route path="/auth/oidc/callback" element={<Dispatcher />} />
447
+
448
+ {/* Other application routes */}
449
+ <Route path="/" element={<HomePage />} />
450
+ <Route path="/dashboard" element={<ProtectedDashboard />} />
451
+ </Routes>
452
+ )
453
+ }
454
+ ```
455
+
456
+ ### State Management Integration
457
+
458
+ ```typescript
459
+ import { createContext, useContext as useReactContext } from 'react'
460
+ import { OidcAuthService } from '@owlmeans/web-oidc-rp'
461
+
462
+ const OidcContext = createContext<OidcAuthService | null>(null)
463
+
464
+ export function OidcProvider({ children }: { children: React.ReactNode }) {
465
+ const context = useContext()
466
+ const oidcService = context.service<OidcAuthService>('oidc-rp')
467
+
468
+ return (
469
+ <OidcContext.Provider value={oidcService}>
470
+ {children}
471
+ </OidcContext.Provider>
472
+ )
473
+ }
474
+
475
+ export function useOidc() {
476
+ const oidcService = useReactContext(OidcContext)
477
+ if (!oidcService) {
478
+ throw new Error('useOidc must be used within OidcProvider')
479
+ }
480
+ return oidcService
481
+ }
482
+ ```
483
+
484
+ ## Best Practices
485
+
486
+ 1. **Secure Redirects**: Always validate redirect URLs and use HTTPS in production
487
+ 2. **State Management**: Properly manage authentication state across page reloads
488
+ 3. **Error Handling**: Implement comprehensive error handling for network and authentication failures
489
+ 4. **Flow Integration**: Use flows for complex authentication scenarios
490
+ 5. **Token Security**: Never expose sensitive tokens in client-side storage
491
+ 6. **PKCE Support**: Use PKCE (Proof Key for Code Exchange) for enhanced security
492
+ 7. **Callback Validation**: Always validate OIDC callback parameters before processing
493
+
494
+ ## Dependencies
495
+
496
+ This package depends on:
497
+ - `@owlmeans/auth` - Authentication framework
498
+ - `@owlmeans/client` - Client framework
499
+ - `@owlmeans/client-auth` - Client authentication
500
+ - `@owlmeans/client-flow` - Client flow management
501
+ - `@owlmeans/flow` - Flow system
502
+ - `@owlmeans/oidc` - Core OIDC functionality
503
+ - `@owlmeans/web-client` - Web client framework
504
+ - `@owlmeans/web-flow` - Web flow integration
505
+ - `oidc-client-ts` - TypeScript OIDC client library
506
+ - `react` - React framework
507
+ - `react-router-dom` - React routing
508
+
509
+ ## Related Packages
510
+
511
+ - [`@owlmeans/server-oidc-rp`](../server-oidc-rp) - Server-side OIDC Relying Party
512
+ - [`@owlmeans/oidc`](../oidc) - Core OIDC functionality
513
+ - [`@owlmeans/client-auth`](../client-auth) - Client authentication framework
514
+ - [`@owlmeans/web-client`](../web-client) - Web client framework
515
+ - [`@owlmeans/web-flow`](../web-flow) - Web flow management
package/build/.gitkeep ADDED
File without changes
@@ -0,0 +1,4 @@
1
+ export declare const plugins: {
2
+ [type: string]: import("@owlmeans/client-auth/manager/plugins").AuthenticationPlugin;
3
+ };
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO;;CAAc,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { plugins as authPlugins } from '@owlmeans/client-auth/manager';
2
+ import { OIDC_CLIENT_AUTH } from '@owlmeans/oidc';
3
+ import { oidcClientPlugin } from './oidc-client.js';
4
+ authPlugins[OIDC_CLIENT_AUTH] = oidcClientPlugin;
5
+ export const plugins = authPlugins;
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/plugins/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAEnD,WAAW,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAA;AAEhD,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { AuthenticationPlugin } from '@owlmeans/client-auth/manager/plugins';
2
+ export declare const oidcClientPlugin: AuthenticationPlugin;
3
+ //# sourceMappingURL=oidc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-client.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/oidc-client.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAA;AAajF,eAAO,MAAM,gBAAgB,EAAE,oBAmG9B,CAAA"}
@@ -0,0 +1,97 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { AUTH_SCOPE, AuthenticationStage, AuthManagerError, AuthRole } from '@owlmeans/auth';
3
+ import { OIDC_CLIENT_AUTH } from '@owlmeans/oidc';
4
+ import { useEffect } from 'react';
5
+ import LinearProgress from '@mui/material/LinearProgress';
6
+ import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope';
7
+ import { useContext } from '@owlmeans/web-client';
8
+ import { DEFAULT_ALIAS, OidcAuthPurposes } from '../../consts.js';
9
+ import { OidcAuthStep, OidpAuthStep, UnknownFlowStep } from '@owlmeans/flow';
10
+ import { useModule } from '@owlmeans/client';
11
+ export const oidcClientPlugin = {
12
+ type: OIDC_CLIENT_AUTH,
13
+ Implementation: Renderer => ({ type, stage, control }) => {
14
+ const context = useContext();
15
+ Renderer = Renderer ?? oidcClientPlugin.Renderer;
16
+ const module = useModule();
17
+ useEffect(() => {
18
+ let canceled = false;
19
+ // @TODO extract somewhere else and make it more consequential
20
+ // This way it looks too messy
21
+ switch (control.stage) {
22
+ case AuthenticationStage.Init:
23
+ control.hasPersistentState().then(async (hasState) => {
24
+ if (canceled) {
25
+ return;
26
+ }
27
+ // 3. Properly process additional paramters on sequential rendering to restore control state
28
+ if (hasState) {
29
+ await control.restore();
30
+ await control.cleanUpState();
31
+ const flow = await control.flow();
32
+ if (flow != null) {
33
+ const state = await flow.state();
34
+ if ([OidcAuthStep.PostAuthen, OidpAuthStep.PostAuth].includes(state?.step().step)) {
35
+ const url = new URL(window.location.href);
36
+ const auth = {
37
+ ...control.allowance,
38
+ type,
39
+ challenge: control.allowance?.challenge ?? '',
40
+ credential: url.searchParams.toString(),
41
+ role: AuthRole.User,
42
+ userId: 'code',
43
+ scopes: [AUTH_SCOPE]
44
+ };
45
+ const tokenized = await control.authenticate(auth);
46
+ // @TODO Introduce some standard further flow in case this plugin/component
47
+ // is used without a callback
48
+ if (tokenized.token !== '') {
49
+ throw new AuthManagerError('callback');
50
+ }
51
+ return; // @TODO Will it work here?
52
+ }
53
+ }
54
+ // return
55
+ }
56
+ // 1. Initialize OIDC server side authentication
57
+ const oidc = context.service(DEFAULT_ALIAS);
58
+ // @TODO we need to provide an identity provider client as entityId here for flexibel usage
59
+ const _source = await oidc.proceedToRedirectUrl({
60
+ purpose: control.source ?? OidcAuthPurposes.Unknown,
61
+ uid: 'uid' in module.params ? `${module.params.uid}` : undefined,
62
+ alias: module.alias
63
+ });
64
+ const source = new URL(_source);
65
+ source.search = '';
66
+ await control.requestAllowence({ type, source: source.toString() });
67
+ });
68
+ case AuthenticationStage.Authenticate:
69
+ control.flow().then(async (flow) => {
70
+ if (canceled) {
71
+ return;
72
+ }
73
+ const flowState = await flow?.state();
74
+ if (flowState == null) {
75
+ throw new UnknownFlowStep(AuthenticationStage.Authenticate);
76
+ }
77
+ if (control.allowance?.challenge != null) {
78
+ const envelope = makeEnvelopeModel(control.allowance?.challenge, EnvelopeKind.Wrap);
79
+ const challenge = envelope.message(true);
80
+ const parts = challenge.split(':http');
81
+ const url = 'http' + parts[1];
82
+ // 2. Include additional parameters (control state with allowance to flow state)
83
+ await control.persist();
84
+ document.location.href = url;
85
+ }
86
+ });
87
+ }
88
+ return () => { canceled = true; };
89
+ }, [type, stage]);
90
+ if (Renderer == null) {
91
+ throw new SyntaxError('Renderer is not defined for OIDC plugin');
92
+ }
93
+ return _jsx(Renderer, { type: type, stage: stage, control: control, params: module.params });
94
+ },
95
+ Renderer: () => _jsx(LinearProgress, {})
96
+ };
97
+ //# sourceMappingURL=oidc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-client.js","sourceRoot":"","sources":["../../../src/auth/plugins/oidc-client.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const Dispatcher: import("@owlmeans/client").RoutedComponent<import("@owlmeans/client-auth").DispatcherProps>;
2
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/components/dispatcher.tsx"],"names":[],"mappings":"AAWA,eAAO,MAAM,UAAU,6FAiDrB,CAAA"}