@owlmeans/client-auth 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 (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +526 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/components/dispatcher/component.d.ts +3 -0
  5. package/build/components/dispatcher/component.d.ts.map +1 -0
  6. package/build/components/dispatcher/component.js +70 -0
  7. package/build/components/dispatcher/component.js.map +1 -0
  8. package/build/components/dispatcher/index.d.ts +3 -0
  9. package/build/components/dispatcher/index.d.ts.map +1 -0
  10. package/build/components/dispatcher/index.js +3 -0
  11. package/build/components/dispatcher/index.js.map +1 -0
  12. package/build/components/dispatcher/types.d.ts +21 -0
  13. package/build/components/dispatcher/types.d.ts.map +1 -0
  14. package/build/components/dispatcher/types.js +2 -0
  15. package/build/components/dispatcher/types.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 +4 -0
  21. package/build/consts.d.ts.map +1 -0
  22. package/build/consts.js +4 -0
  23. package/build/consts.js.map +1 -0
  24. package/build/helper.d.ts +4 -0
  25. package/build/helper.d.ts.map +1 -0
  26. package/build/helper.js +28 -0
  27. package/build/helper.js.map +1 -0
  28. package/build/index.d.ts +7 -0
  29. package/build/index.d.ts.map +1 -0
  30. package/build/index.js +6 -0
  31. package/build/index.js.map +1 -0
  32. package/build/manager/components/authentication/component.d.ts +3 -0
  33. package/build/manager/components/authentication/component.d.ts.map +1 -0
  34. package/build/manager/components/authentication/component.js +28 -0
  35. package/build/manager/components/authentication/component.js.map +1 -0
  36. package/build/manager/components/authentication/consts.d.ts +2 -0
  37. package/build/manager/components/authentication/consts.d.ts.map +1 -0
  38. package/build/manager/components/authentication/consts.js +2 -0
  39. package/build/manager/components/authentication/consts.js.map +1 -0
  40. package/build/manager/components/authentication/control.d.ts +6 -0
  41. package/build/manager/components/authentication/control.d.ts.map +1 -0
  42. package/build/manager/components/authentication/control.js +146 -0
  43. package/build/manager/components/authentication/control.js.map +1 -0
  44. package/build/manager/components/authentication/index.d.ts +4 -0
  45. package/build/manager/components/authentication/index.d.ts.map +1 -0
  46. package/build/manager/components/authentication/index.js +4 -0
  47. package/build/manager/components/authentication/index.js.map +1 -0
  48. package/build/manager/components/authentication/types.d.ts +57 -0
  49. package/build/manager/components/authentication/types.d.ts.map +1 -0
  50. package/build/manager/components/authentication/types.js +2 -0
  51. package/build/manager/components/authentication/types.js.map +1 -0
  52. package/build/manager/components/index.d.ts +4 -0
  53. package/build/manager/components/index.d.ts.map +1 -0
  54. package/build/manager/components/index.js +3 -0
  55. package/build/manager/components/index.js.map +1 -0
  56. package/build/manager/components/tunnel-consumer.d.ts +4 -0
  57. package/build/manager/components/tunnel-consumer.d.ts.map +1 -0
  58. package/build/manager/components/tunnel-consumer.js +11 -0
  59. package/build/manager/components/tunnel-consumer.js.map +1 -0
  60. package/build/manager/components/types.d.ts +10 -0
  61. package/build/manager/components/types.d.ts.map +1 -0
  62. package/build/manager/components/types.js +2 -0
  63. package/build/manager/components/types.js.map +1 -0
  64. package/build/manager/errors.d.ts +6 -0
  65. package/build/manager/errors.d.ts.map +1 -0
  66. package/build/manager/errors.js +11 -0
  67. package/build/manager/errors.js.map +1 -0
  68. package/build/manager/index.d.ts +4 -0
  69. package/build/manager/index.d.ts.map +1 -0
  70. package/build/manager/index.js +4 -0
  71. package/build/manager/index.js.map +1 -0
  72. package/build/manager/modules.d.ts +2 -0
  73. package/build/manager/modules.d.ts.map +1 -0
  74. package/build/manager/modules.js +16 -0
  75. package/build/manager/modules.js.map +1 -0
  76. package/build/manager/plugins/basic-ed25519.d.ts +3 -0
  77. package/build/manager/plugins/basic-ed25519.d.ts.map +1 -0
  78. package/build/manager/plugins/basic-ed25519.js +33 -0
  79. package/build/manager/plugins/basic-ed25519.js.map +1 -0
  80. package/build/manager/plugins/exports.d.ts +6 -0
  81. package/build/manager/plugins/exports.d.ts.map +1 -0
  82. package/build/manager/plugins/exports.js +5 -0
  83. package/build/manager/plugins/exports.js.map +1 -0
  84. package/build/manager/plugins/index.d.ts +6 -0
  85. package/build/manager/plugins/index.d.ts.map +1 -0
  86. package/build/manager/plugins/index.js +9 -0
  87. package/build/manager/plugins/index.js.map +1 -0
  88. package/build/manager/plugins/re-captcha.d.ts +3 -0
  89. package/build/manager/plugins/re-captcha.d.ts.map +1 -0
  90. package/build/manager/plugins/re-captcha.js +26 -0
  91. package/build/manager/plugins/re-captcha.js.map +1 -0
  92. package/build/manager/plugins/tunnel/consts.d.ts +4 -0
  93. package/build/manager/plugins/tunnel/consts.d.ts.map +1 -0
  94. package/build/manager/plugins/tunnel/consts.js +9 -0
  95. package/build/manager/plugins/tunnel/consts.js.map +1 -0
  96. package/build/manager/plugins/tunnel/index.d.ts +4 -0
  97. package/build/manager/plugins/tunnel/index.d.ts.map +1 -0
  98. package/build/manager/plugins/tunnel/index.js +3 -0
  99. package/build/manager/plugins/tunnel/index.js.map +1 -0
  100. package/build/manager/plugins/tunnel/types.d.ts +13 -0
  101. package/build/manager/plugins/tunnel/types.d.ts.map +1 -0
  102. package/build/manager/plugins/tunnel/types.js +2 -0
  103. package/build/manager/plugins/tunnel/types.js.map +1 -0
  104. package/build/manager/plugins/tunnel/wallet.d.ts +4 -0
  105. package/build/manager/plugins/tunnel/wallet.d.ts.map +1 -0
  106. package/build/manager/plugins/tunnel/wallet.js +32 -0
  107. package/build/manager/plugins/tunnel/wallet.js.map +1 -0
  108. package/build/manager/plugins/tunnel-consumer.d.ts +3 -0
  109. package/build/manager/plugins/tunnel-consumer.d.ts.map +1 -0
  110. package/build/manager/plugins/tunnel-consumer.js +81 -0
  111. package/build/manager/plugins/tunnel-consumer.js.map +1 -0
  112. package/build/manager/plugins/types.d.ts +11 -0
  113. package/build/manager/plugins/types.d.ts.map +1 -0
  114. package/build/manager/plugins/types.js +2 -0
  115. package/build/manager/plugins/types.js.map +1 -0
  116. package/build/modules.d.ts +4 -0
  117. package/build/modules.d.ts.map +1 -0
  118. package/build/modules.js +9 -0
  119. package/build/modules.js.map +1 -0
  120. package/build/service.d.ts +6 -0
  121. package/build/service.d.ts.map +1 -0
  122. package/build/service.js +71 -0
  123. package/build/service.js.map +1 -0
  124. package/build/types.d.ts +13 -0
  125. package/build/types.d.ts.map +1 -0
  126. package/build/types.js +2 -0
  127. package/build/types.js.map +1 -0
  128. package/package.json +79 -0
  129. package/src/components/dispatcher/component.tsx +84 -0
  130. package/src/components/dispatcher/index.ts +3 -0
  131. package/src/components/dispatcher/types.ts +24 -0
  132. package/src/components/index.ts +2 -0
  133. package/src/consts.ts +6 -0
  134. package/src/helper.ts +39 -0
  135. package/src/index.ts +7 -0
  136. package/src/manager/README.md +463 -0
  137. package/src/manager/components/authentication/component.tsx +34 -0
  138. package/src/manager/components/authentication/consts.ts +2 -0
  139. package/src/manager/components/authentication/control.ts +193 -0
  140. package/src/manager/components/authentication/index.ts +4 -0
  141. package/src/manager/components/authentication/types.ts +74 -0
  142. package/src/manager/components/index.ts +4 -0
  143. package/src/manager/components/tunnel-consumer.tsx +15 -0
  144. package/src/manager/components/types.ts +11 -0
  145. package/src/manager/errors.ts +14 -0
  146. package/src/manager/index.ts +4 -0
  147. package/src/manager/modules.ts +18 -0
  148. package/src/manager/plugins/basic-ed25519.tsx +42 -0
  149. package/src/manager/plugins/exports.ts +5 -0
  150. package/src/manager/plugins/index.ts +13 -0
  151. package/src/manager/plugins/re-captcha.tsx +31 -0
  152. package/src/manager/plugins/tunnel/consts.ts +12 -0
  153. package/src/manager/plugins/tunnel/index.ts +5 -0
  154. package/src/manager/plugins/tunnel/types.ts +15 -0
  155. package/src/manager/plugins/tunnel/wallet.ts +43 -0
  156. package/src/manager/plugins/tunnel-consumer.tsx +100 -0
  157. package/src/manager/plugins/types.ts +14 -0
  158. package/src/modules.ts +13 -0
  159. package/src/service.ts +106 -0
  160. package/src/types.ts +15 -0
  161. package/tsconfig.json +15 -0
  162. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,84 @@
1
+ import { useCallback, useEffect, useState } from 'react'
2
+ import type { DispatcherRendererProps, TDispatcherHOC } from './types.js'
3
+ import type { AuthToken } from '@owlmeans/auth'
4
+ import { AUTH_QUERY, DISPATCHER } from '@owlmeans/auth'
5
+ import type { ClientModule } from '@owlmeans/client-module'
6
+ import { HOME } from '@owlmeans/context'
7
+ import { DEFAULT_ALIAS } from '../../consts.js'
8
+ import type { AuthService } from '@owlmeans/auth-common'
9
+ import { useNavigate } from '@owlmeans/client'
10
+ import type { AbstractRequest } from '@owlmeans/module'
11
+ import type { FlowService } from '@owlmeans/client-flow'
12
+ import { DEFAULT_ALIAS as FLOW_SERVICE } from '@owlmeans/client-flow'
13
+ import { STD_OIDC_FLOW } from '@owlmeans/flow'
14
+ import { SERVICE_PARAM } from '@owlmeans/web-flow'
15
+
16
+ export const DispatcherHOC: TDispatcherHOC = Renderer => ({ context, params, alias, query }) => {
17
+ const [forwarding, setForwarding] = useState<StateToken | undefined>()
18
+
19
+ const navigator = useNavigate()
20
+ const navigate = useCallback(async () => {
21
+ alias = alias == null || alias === DISPATCHER ? HOME : alias
22
+ const module = context.module<ClientModule<string>>(alias)
23
+ if (alias === HOME) {
24
+ params = {}
25
+ query = {}
26
+ } else {
27
+ query = { ...forwarding?.query, ...query }
28
+ if (query != null && AUTH_QUERY in query) {
29
+ delete query[AUTH_QUERY]
30
+ }
31
+ }
32
+ await navigator.navigate(module, { params, query })
33
+ }, [forwarding])
34
+
35
+ useEffect(() => {
36
+ if (forwarding?.token != null) {
37
+ if (forwarding.token.token === '') {
38
+ const flow = context.service<FlowService>(FLOW_SERVICE)
39
+ // @TODO: Make sure that the provided flow is compatible with OIDC flow or provide custom from step
40
+ flow.ready().then(async () => {
41
+ // We do nothing if we are in the middle of a flow
42
+ if (await flow.supplied) {
43
+ const state = await flow.state()
44
+ // If the flow we are in already has a targe, it means this is some flow
45
+ // that is really happening and we do not need to override it with our own.
46
+ // It's MAY BE required on the auth manager service side, cause this
47
+ // component is actually reused by both service and identity providers of OwlMeans.
48
+ if (state?.state().service !== '') {
49
+ return
50
+ }
51
+ }
52
+ const cfg = context.cfg.security?.auth
53
+ const model = await flow.begin(cfg?.flow ?? STD_OIDC_FLOW, cfg?.enter)
54
+ const target = (
55
+ SERVICE_PARAM in params ? params[SERVICE_PARAM] : context.cfg.shortAlias
56
+ ) as string | undefined
57
+ if (target != null) {
58
+ model.target(target)
59
+ }
60
+ await flow.proceed()
61
+ })
62
+ } else {
63
+ const auth = context.service<AuthService>(DEFAULT_ALIAS)
64
+ auth.authenticate(forwarding.token).then(async () => {
65
+ return await navigate()
66
+ }).catch((e: Error) => {
67
+ // @TODO Show error on the component
68
+ console.error(e)
69
+ })
70
+ }
71
+ }
72
+ }, [forwarding?.token])
73
+
74
+ const provideToken = useCallback<DispatcherRendererProps["provideToken"]>((token, query) => {
75
+ setForwarding({ token, query })
76
+ }, [])
77
+
78
+ return <Renderer provideToken={provideToken} navigate={navigate} />
79
+ }
80
+
81
+ interface StateToken {
82
+ token: AuthToken
83
+ query?: AbstractRequest['params']
84
+ }
@@ -0,0 +1,3 @@
1
+
2
+ export * from './component.js'
3
+ export * from './types.js'
@@ -0,0 +1,24 @@
1
+ import type { FC, PropsWithChildren } from 'react'
2
+ import type { RoutedComponent } from '@owlmeans/client'
3
+ import type { AuthToken } from '@owlmeans/auth'
4
+ import type { ClientContext, ClientConfig } from '@owlmeans/client-context'
5
+ import type { AbstractRequest } from '@owlmeans/module'
6
+
7
+ export interface DispatcherProps {
8
+ alias: string
9
+ params: AbstractRequest['params']
10
+ query?: AbstractRequest['query']
11
+ context: ClientContext<ClientConfig>
12
+ }
13
+
14
+ export interface TDispatcherHOC {
15
+ (Renderer: DispatcherRenderer): RoutedComponent<DispatcherProps>
16
+ }
17
+
18
+ export interface DispatcherRenderer extends FC<DispatcherRendererProps> {
19
+ }
20
+
21
+ export interface DispatcherRendererProps extends PropsWithChildren {
22
+ provideToken: (token: AuthToken, query?: AbstractRequest['params']) => void
23
+ navigate: () => Promise<void>
24
+ }
@@ -0,0 +1,2 @@
1
+
2
+ export * from './dispatcher/index.js'
package/src/consts.ts ADDED
@@ -0,0 +1,6 @@
1
+
2
+ export const DEFAULT_ALIAS = 'auth'
3
+
4
+ export const AUTH_RESOURCE = 'auth'
5
+
6
+ export const USER_ID = 'user'
package/src/helper.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { useContext } from '@owlmeans/client'
2
+ import type { ClientModule } from '@owlmeans/client-module'
3
+ import { provideRequest } from '@owlmeans/client-module'
4
+ import { useWs as useWebSocket } from '@owlmeans/client-socket'
5
+ import type { AbstractRequest } from '@owlmeans/module'
6
+ import type { AuthServiceAppend } from './types.js'
7
+ import { useMemo } from 'react'
8
+ import type { ClientContext } from '@owlmeans/client-context'
9
+ import { AUTH_QUERY } from '@owlmeans/auth'
10
+
11
+ export const useWs = (
12
+ module: string | ClientModule<any>, _request?: Partial<AbstractRequest<any>>
13
+ ) => {
14
+ const ctx = useContext() as unknown as AuthServiceAppend & ClientContext
15
+
16
+ const mod = useMemo(
17
+ () => typeof module === 'string' ? ctx.module<ClientModule>(module) : module, [module]
18
+ )
19
+
20
+ const request = useMemo(() => {
21
+ if (_request == null) {
22
+ _request = provideRequest(mod.getAlias(), mod.getPath())
23
+ }
24
+ try {
25
+ if (_request?.query?.[AUTH_QUERY] == null) {
26
+ if (_request.query == null) {
27
+ _request.query = {}
28
+ }
29
+ _request.query[AUTH_QUERY] = ctx.auth().token
30
+ }
31
+ } catch (e) {
32
+ console.error(e)
33
+ }
34
+
35
+ return _request
36
+ }, [_request])
37
+
38
+ return useWebSocket(module, request)
39
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+
2
+ export * from './components/index.js'
3
+ export type * from './types.js'
4
+ export * from './service.js'
5
+ export * from './consts.js'
6
+ export * from './modules.js'
7
+ export * from './helper.js'
@@ -0,0 +1,463 @@
1
+ # OwlMeans Client Auth Manager
2
+
3
+ The **OwlMeans Client Auth Manager** is a comprehensive React-based authentication management system for client-side applications within the OwlMeans Common Libraries ecosystem. This manager provides React components, hooks, and utilities for handling authentication flows, credential management, and secure communication with authentication services.
4
+
5
+ ## Purpose
6
+
7
+ This manager provides client-side authentication capabilities designed for:
8
+
9
+ - **React Authentication Components**: Pre-built UI components for authentication flows
10
+ - **Authentication State Management**: Centralized authentication state handling
11
+ - **Credential Security**: Secure credential management and validation
12
+ - **Authentication HOCs**: Higher-Order Components for protected routes and features
13
+ - **WebSocket Tunneling**: Real-time authentication tunnel management
14
+ - **Multi-Authentication Types**: Support for various authentication methods (password, wallet, etc.)
15
+
16
+ ## Key Concepts
17
+
18
+ ### Authentication Components
19
+ React components that handle various authentication scenarios:
20
+ - **Authentication HOC**: Higher-Order Component that wraps other components with authentication
21
+ - **Tunnel Consumer**: Component for handling WebSocket authentication tunnels
22
+ - **Credential Management**: Secure handling of user credentials
23
+
24
+ ### Module Integration
25
+ The manager integrates with the OwlMeans module system to provide:
26
+ - **Elevated Modules**: Enhanced modules with client-specific authentication handling
27
+ - **Route Protection**: Automatic authentication requirements for protected routes
28
+ - **API Integration**: Seamless integration with authentication APIs
29
+
30
+ ### Error Management
31
+ Comprehensive error handling for authentication scenarios:
32
+ - **Credential Errors**: Specialized error types for credential validation
33
+ - **Resilient Error System**: Integration with OwlMeans error management
34
+
35
+ ## Installation
36
+
37
+ This manager is part of the `@owlmeans/client-auth` package:
38
+
39
+ ```bash
40
+ npm install @owlmeans/client-auth
41
+ ```
42
+
43
+ ## API Reference
44
+
45
+ ### Types
46
+
47
+ #### `TunnelAuthenticationProps`
48
+ Props interface for tunnel authentication components.
49
+
50
+ ```typescript
51
+ interface TunnelAuthenticationProps {
52
+ type: AuthenticationType
53
+ onAuthenticated?: (auth: Auth) => void
54
+ onError?: (error: Error) => void
55
+ // Additional authentication props
56
+ }
57
+ ```
58
+
59
+ ### Components
60
+
61
+ #### `AuthenticationHOC(component?, type?)`
62
+ Higher-Order Component that adds authentication capabilities to wrapped components.
63
+
64
+ ```typescript
65
+ function AuthenticationHOC(
66
+ component?: ComponentType,
67
+ type?: AuthenticationType
68
+ ): ComponentType<AuthenticationProps>
69
+ ```
70
+
71
+ **Parameters:**
72
+ - `component`: Optional base component to wrap
73
+ - `type`: Authentication type to use
74
+
75
+ **Returns:** Enhanced component with authentication capabilities
76
+
77
+ ```typescript
78
+ import { AuthenticationHOC } from '@owlmeans/client-auth/manager'
79
+
80
+ // Create an authentication-protected component
81
+ const ProtectedComponent = AuthenticationHOC(MyComponent)
82
+
83
+ // Or with specific authentication type
84
+ const WalletAuthComponent = AuthenticationHOC(
85
+ MyComponent,
86
+ AuthenticationType.WalletDid
87
+ )
88
+ ```
89
+
90
+ #### `TunnelConsumer`
91
+ React component for handling WebSocket authentication tunnels.
92
+
93
+ ```typescript
94
+ const TunnelConsumer: FC<Partial<TunnelAuthenticationProps>>
95
+ ```
96
+
97
+ Provides a consumer interface for authentication tunnels with automatic WebSocket connection management.
98
+
99
+ ```typescript
100
+ import { TunnelConsumer } from '@owlmeans/client-auth/manager'
101
+
102
+ function App() {
103
+ return (
104
+ <TunnelConsumer
105
+ onAuthenticated={(auth) => console.log('Authenticated:', auth)}
106
+ onError={(error) => console.error('Auth error:', error)}
107
+ />
108
+ )
109
+ }
110
+ ```
111
+
112
+ ### Error Classes
113
+
114
+ #### `AuthenCredError`
115
+ Specialized error class for credential-related authentication failures.
116
+
117
+ ```typescript
118
+ class AuthenCredError extends AuthManagerError {
119
+ static typeName: string
120
+ constructor(message?: string)
121
+ }
122
+ ```
123
+
124
+ **Usage:**
125
+ ```typescript
126
+ import { AuthenCredError } from '@owlmeans/client-auth/manager'
127
+
128
+ try {
129
+ await authenticateCredentials(credentials)
130
+ } catch (error) {
131
+ if (error instanceof AuthenCredError) {
132
+ console.error('Credential error:', error.message)
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### Modules
138
+
139
+ #### `modules`
140
+ Pre-configured authentication modules for client applications.
141
+
142
+ ```typescript
143
+ const modules: CommonModule[]
144
+ ```
145
+
146
+ Contains elevated modules for:
147
+ - `AUTHEN` - Base authentication module
148
+ - `AUTHEN_INIT` - Authentication initialization
149
+ - `AUTHEN_AUTHEN` - User authentication
150
+ - `AUTHEN_RELY` - Authentication relay
151
+ - `CAUTHEN` - Client authentication
152
+ - `CAUTHEN_AUTHEN` - Client authentication handler
153
+ - `CAUTHEN_AUTHEN_DEFAULT` - Default authentication component
154
+ - `CAUTHEN_AUTHEN_TYPED` - Typed authentication component
155
+ - `DISPATCHER` - Authentication dispatcher
156
+
157
+ ## Usage Examples
158
+
159
+ ### Basic Authentication Setup
160
+
161
+ ```typescript
162
+ import { modules } from '@owlmeans/client-auth/manager'
163
+ import { makeClientContext } from '@owlmeans/client-context'
164
+
165
+ // Register authentication modules with context
166
+ const context = makeClientContext(config)
167
+ context.registerModules(modules)
168
+
169
+ await context.configure().init()
170
+ ```
171
+
172
+ ### Authentication HOC Usage
173
+
174
+ ```typescript
175
+ import React from 'react'
176
+ import { AuthenticationHOC } from '@owlmeans/client-auth/manager'
177
+ import { AuthenticationType } from '@owlmeans/auth'
178
+
179
+ // Protected dashboard component
180
+ const Dashboard = () => (
181
+ <div>
182
+ <h1>Protected Dashboard</h1>
183
+ <p>This content requires authentication</p>
184
+ </div>
185
+ )
186
+
187
+ // Wrap with authentication
188
+ const ProtectedDashboard = AuthenticationHOC(Dashboard, AuthenticationType.PasswordLogin)
189
+
190
+ // Use in your app
191
+ function App() {
192
+ return (
193
+ <div>
194
+ <ProtectedDashboard />
195
+ </div>
196
+ )
197
+ }
198
+ ```
199
+
200
+ ### Wallet Authentication Component
201
+
202
+ ```typescript
203
+ import { AuthenticationHOC } from '@owlmeans/client-auth/manager'
204
+ import { AuthenticationType } from '@owlmeans/auth'
205
+
206
+ const WalletComponent = () => (
207
+ <div>
208
+ <h2>Wallet Connected</h2>
209
+ <p>Decentralized identity verified</p>
210
+ </div>
211
+ )
212
+
213
+ const WalletAuth = AuthenticationHOC(
214
+ WalletComponent,
215
+ AuthenticationType.WalletDid
216
+ )
217
+
218
+ function WalletApp() {
219
+ return (
220
+ <div>
221
+ <h1>DeFi Application</h1>
222
+ <WalletAuth />
223
+ </div>
224
+ )
225
+ }
226
+ ```
227
+
228
+ ### Tunnel Consumer for Real-time Auth
229
+
230
+ ```typescript
231
+ import { TunnelConsumer } from '@owlmeans/client-auth/manager'
232
+ import { useState } from 'react'
233
+
234
+ function RealtimeApp() {
235
+ const [authStatus, setAuthStatus] = useState('pending')
236
+
237
+ return (
238
+ <div>
239
+ <h1>Real-time Application</h1>
240
+ <p>Auth Status: {authStatus}</p>
241
+
242
+ <TunnelConsumer
243
+ onAuthenticated={(auth) => {
244
+ setAuthStatus('authenticated')
245
+ console.log('User authenticated via tunnel:', auth)
246
+ }}
247
+ onError={(error) => {
248
+ setAuthStatus('error')
249
+ console.error('Tunnel authentication failed:', error)
250
+ }}
251
+ />
252
+ </div>
253
+ )
254
+ }
255
+ ```
256
+
257
+ ### Custom Authentication Flow
258
+
259
+ ```typescript
260
+ import { modules, AuthenCredError } from '@owlmeans/client-auth/manager'
261
+ import { useModule } from '@owlmeans/client'
262
+
263
+ function CustomAuthFlow() {
264
+ const authModule = useModule('auth')
265
+
266
+ const handleLogin = async (credentials) => {
267
+ try {
268
+ const initResponse = await authModule.init({
269
+ type: AuthenticationType.PasswordLogin
270
+ })
271
+
272
+ const authResponse = await authModule.authenticate({
273
+ ...credentials,
274
+ challenge: initResponse.challenge
275
+ })
276
+
277
+ console.log('Authentication successful:', authResponse)
278
+ } catch (error) {
279
+ if (error instanceof AuthenCredError) {
280
+ console.error('Invalid credentials:', error.message)
281
+ } else {
282
+ console.error('Authentication failed:', error)
283
+ }
284
+ }
285
+ }
286
+
287
+ return (
288
+ <form onSubmit={(e) => {
289
+ e.preventDefault()
290
+ const formData = new FormData(e.target)
291
+ handleLogin({
292
+ username: formData.get('username'),
293
+ password: formData.get('password')
294
+ })
295
+ }}>
296
+ <input name="username" placeholder="Username" required />
297
+ <input name="password" type="password" placeholder="Password" required />
298
+ <button type="submit">Login</button>
299
+ </form>
300
+ )
301
+ }
302
+ ```
303
+
304
+ ### Error Handling
305
+
306
+ ```typescript
307
+ import { AuthenCredError } from '@owlmeans/client-auth/manager'
308
+ import { ResilientError } from '@owlmeans/error'
309
+
310
+ function AuthErrorHandler({ children }) {
311
+ const handleError = (error) => {
312
+ if (error instanceof AuthenCredError) {
313
+ // Handle credential-specific errors
314
+ toast.error(`Credential error: ${error.message}`)
315
+ } else if (error instanceof ResilientError) {
316
+ // Handle other resilient errors
317
+ toast.error(`Authentication error: ${error.message}`)
318
+ } else {
319
+ // Handle unexpected errors
320
+ toast.error('An unexpected error occurred')
321
+ }
322
+ }
323
+
324
+ return (
325
+ <ErrorBoundary onError={handleError}>
326
+ {children}
327
+ </ErrorBoundary>
328
+ )
329
+ }
330
+ ```
331
+
332
+ ## Integration Patterns
333
+
334
+ ### React Router Integration
335
+
336
+ ```typescript
337
+ import { AuthenticationHOC } from '@owlmeans/client-auth/manager'
338
+ import { BrowserRouter, Routes, Route } from 'react-router-dom'
339
+
340
+ const ProtectedRoute = AuthenticationHOC(({ children }) => children)
341
+
342
+ function App() {
343
+ return (
344
+ <BrowserRouter>
345
+ <Routes>
346
+ <Route path="/public" element={<PublicPage />} />
347
+ <Route path="/protected" element={
348
+ <ProtectedRoute>
349
+ <ProtectedPage />
350
+ </ProtectedRoute>
351
+ } />
352
+ </Routes>
353
+ </BrowserRouter>
354
+ )
355
+ }
356
+ ```
357
+
358
+ ### State Management Integration
359
+
360
+ ```typescript
361
+ import { AuthenticationHOC } from '@owlmeans/client-auth/manager'
362
+ import { useDispatch } from 'react-redux'
363
+
364
+ const AuthenticatedApp = AuthenticationHOC(() => {
365
+ const dispatch = useDispatch()
366
+
367
+ useEffect(() => {
368
+ // Update Redux store with authentication state
369
+ dispatch(setAuthenticationStatus('authenticated'))
370
+ }, [dispatch])
371
+
372
+ return <MainApp />
373
+ })
374
+ ```
375
+
376
+ ### Context Provider Pattern
377
+
378
+ ```typescript
379
+ import { createContext, useContext } from 'react'
380
+ import { TunnelConsumer } from '@owlmeans/client-auth/manager'
381
+
382
+ const AuthContext = createContext(null)
383
+
384
+ function AuthProvider({ children }) {
385
+ const [auth, setAuth] = useState(null)
386
+
387
+ return (
388
+ <AuthContext.Provider value={auth}>
389
+ <TunnelConsumer onAuthenticated={setAuth} />
390
+ {children}
391
+ </AuthContext.Provider>
392
+ )
393
+ }
394
+
395
+ // Custom hook for using auth context
396
+ function useAuth() {
397
+ const auth = useContext(AuthContext)
398
+ if (!auth) throw new Error('useAuth must be used within AuthProvider')
399
+ return auth
400
+ }
401
+ ```
402
+
403
+ ## Authentication Types Supported
404
+
405
+ The manager supports various authentication types:
406
+
407
+ ### Password-based Authentication
408
+ ```typescript
409
+ AuthenticationType.PasswordLogin
410
+ ```
411
+ Traditional username/password authentication.
412
+
413
+ ### Wallet-based Authentication
414
+ ```typescript
415
+ AuthenticationType.WalletDid
416
+ AuthenticationType.WalletConsumer
417
+ ```
418
+ Decentralized identity authentication using blockchain wallets.
419
+
420
+ ### Token-based Authentication
421
+ ```typescript
422
+ AuthenticationType.OneTimeToken
423
+ ```
424
+ Single-use token authentication for enhanced security.
425
+
426
+ ## Best Practices
427
+
428
+ 1. **Component Wrapping**: Use AuthenticationHOC for protecting entire component trees
429
+ 2. **Error Boundaries**: Implement proper error boundaries around authentication components
430
+ 3. **State Management**: Integrate authentication state with your app's state management solution
431
+ 4. **Type Safety**: Leverage TypeScript for type-safe authentication handling
432
+ 5. **Graceful Fallbacks**: Provide fallback UI for authentication failures
433
+ 6. **Security**: Never store sensitive credentials in local storage
434
+
435
+ ## Module Elevation
436
+
437
+ The manager uses module elevation to enhance base authentication modules:
438
+
439
+ ```typescript
440
+ // Base modules are elevated with client-specific handlers
441
+ elevate(list, AUTHEN_INIT, true) // API call elevation
442
+ elevate(list, AUTHEN_AUTHEN, true) // Authentication elevation
443
+ elevate(list, CAUTHEN_AUTHEN_DEFAULT, handler(AuthenticationHOC())) // Component handler
444
+ ```
445
+
446
+ This provides seamless integration between the module system and React components.
447
+
448
+ ## Dependencies
449
+
450
+ This manager depends on:
451
+ - `@owlmeans/auth` - Core authentication functionality
452
+ - `@owlmeans/auth-common` - Shared authentication components
453
+ - `@owlmeans/client` - Client-side framework functionality
454
+ - `@owlmeans/client-module` - Client module system
455
+ - `@owlmeans/error` - Error management system
456
+ - `react` - React framework for UI components
457
+
458
+ ## Related Packages
459
+
460
+ - [`@owlmeans/client-auth`](../../../README.md) - Parent client authentication package
461
+ - [`@owlmeans/server-auth/manager`](../../../server-auth/src/manager/README.md) - Server-side authentication manager
462
+ - [`@owlmeans/auth`](../../../auth/README.md) - Core authentication library
463
+ - [`@owlmeans/client`](../../../client/README.md) - Client-side framework
@@ -0,0 +1,34 @@
1
+ import type { AuthenticationControl, TAuthenticationHOC } from './types.js'
2
+ import type { AuthUIParams } from '@owlmeans/auth-common'
3
+ import { plugins } from '../../plugins/index.js'
4
+ import { AuthenticationStage, AuthenticationType } from '@owlmeans/auth'
5
+ import { useMemo, useState, useRef } from 'react'
6
+ import { makeControl } from './control.js'
7
+ import { useContext } from '@owlmeans/client'
8
+
9
+ export const AuthenticationHOC: TAuthenticationHOC = (Renderer, rendererType) => ({ type, params, callback, source }) => {
10
+ const context = useContext()
11
+ const _params: AuthUIParams = params
12
+ type = type ?? _params.type ?? rendererType ?? AuthenticationType.BasicEd25519
13
+
14
+ const Implementation = useMemo(() => {
15
+ const Com = plugins[type]?.Implementation(Renderer)
16
+ if (Com == null) {
17
+ throw new SyntaxError(`Implementation for ${type} is not defined in AuthenticationHOC`)
18
+ }
19
+ return Com
20
+ }, [type])
21
+
22
+ const [stage, setStage] = useState<AuthenticationStage>(AuthenticationStage.Init)
23
+
24
+ const { current: control } = useRef<AuthenticationControl>((() => {
25
+ const control = makeControl(context, callback)
26
+ control.type = type
27
+ control.setStage = setStage
28
+ control.source = source
29
+
30
+ return control
31
+ })())
32
+
33
+ return <Implementation type={type} stage={stage} control={control} params={params} />
34
+ }
@@ -0,0 +1,2 @@
1
+
2
+ export const CONTROL_STATE_ID = 'auth-control-state'