@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.
- package/LICENSE +21 -0
- package/README.md +526 -0
- package/build/.gitkeep +0 -0
- package/build/components/dispatcher/component.d.ts +3 -0
- package/build/components/dispatcher/component.d.ts.map +1 -0
- package/build/components/dispatcher/component.js +70 -0
- package/build/components/dispatcher/component.js.map +1 -0
- package/build/components/dispatcher/index.d.ts +3 -0
- package/build/components/dispatcher/index.d.ts.map +1 -0
- package/build/components/dispatcher/index.js +3 -0
- package/build/components/dispatcher/index.js.map +1 -0
- package/build/components/dispatcher/types.d.ts +21 -0
- package/build/components/dispatcher/types.d.ts.map +1 -0
- package/build/components/dispatcher/types.js +2 -0
- package/build/components/dispatcher/types.js.map +1 -0
- package/build/components/index.d.ts +2 -0
- package/build/components/index.d.ts.map +1 -0
- package/build/components/index.js +2 -0
- package/build/components/index.js.map +1 -0
- package/build/consts.d.ts +4 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +4 -0
- package/build/consts.js.map +1 -0
- package/build/helper.d.ts +4 -0
- package/build/helper.d.ts.map +1 -0
- package/build/helper.js +28 -0
- package/build/helper.js.map +1 -0
- package/build/index.d.ts +7 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +6 -0
- package/build/index.js.map +1 -0
- package/build/manager/components/authentication/component.d.ts +3 -0
- package/build/manager/components/authentication/component.d.ts.map +1 -0
- package/build/manager/components/authentication/component.js +28 -0
- package/build/manager/components/authentication/component.js.map +1 -0
- package/build/manager/components/authentication/consts.d.ts +2 -0
- package/build/manager/components/authentication/consts.d.ts.map +1 -0
- package/build/manager/components/authentication/consts.js +2 -0
- package/build/manager/components/authentication/consts.js.map +1 -0
- package/build/manager/components/authentication/control.d.ts +6 -0
- package/build/manager/components/authentication/control.d.ts.map +1 -0
- package/build/manager/components/authentication/control.js +146 -0
- package/build/manager/components/authentication/control.js.map +1 -0
- package/build/manager/components/authentication/index.d.ts +4 -0
- package/build/manager/components/authentication/index.d.ts.map +1 -0
- package/build/manager/components/authentication/index.js +4 -0
- package/build/manager/components/authentication/index.js.map +1 -0
- package/build/manager/components/authentication/types.d.ts +57 -0
- package/build/manager/components/authentication/types.d.ts.map +1 -0
- package/build/manager/components/authentication/types.js +2 -0
- package/build/manager/components/authentication/types.js.map +1 -0
- package/build/manager/components/index.d.ts +4 -0
- package/build/manager/components/index.d.ts.map +1 -0
- package/build/manager/components/index.js +3 -0
- package/build/manager/components/index.js.map +1 -0
- package/build/manager/components/tunnel-consumer.d.ts +4 -0
- package/build/manager/components/tunnel-consumer.d.ts.map +1 -0
- package/build/manager/components/tunnel-consumer.js +11 -0
- package/build/manager/components/tunnel-consumer.js.map +1 -0
- package/build/manager/components/types.d.ts +10 -0
- package/build/manager/components/types.d.ts.map +1 -0
- package/build/manager/components/types.js +2 -0
- package/build/manager/components/types.js.map +1 -0
- package/build/manager/errors.d.ts +6 -0
- package/build/manager/errors.d.ts.map +1 -0
- package/build/manager/errors.js +11 -0
- package/build/manager/errors.js.map +1 -0
- package/build/manager/index.d.ts +4 -0
- package/build/manager/index.d.ts.map +1 -0
- package/build/manager/index.js +4 -0
- package/build/manager/index.js.map +1 -0
- package/build/manager/modules.d.ts +2 -0
- package/build/manager/modules.d.ts.map +1 -0
- package/build/manager/modules.js +16 -0
- package/build/manager/modules.js.map +1 -0
- package/build/manager/plugins/basic-ed25519.d.ts +3 -0
- package/build/manager/plugins/basic-ed25519.d.ts.map +1 -0
- package/build/manager/plugins/basic-ed25519.js +33 -0
- package/build/manager/plugins/basic-ed25519.js.map +1 -0
- package/build/manager/plugins/exports.d.ts +6 -0
- package/build/manager/plugins/exports.d.ts.map +1 -0
- package/build/manager/plugins/exports.js +5 -0
- package/build/manager/plugins/exports.js.map +1 -0
- package/build/manager/plugins/index.d.ts +6 -0
- package/build/manager/plugins/index.d.ts.map +1 -0
- package/build/manager/plugins/index.js +9 -0
- package/build/manager/plugins/index.js.map +1 -0
- package/build/manager/plugins/re-captcha.d.ts +3 -0
- package/build/manager/plugins/re-captcha.d.ts.map +1 -0
- package/build/manager/plugins/re-captcha.js +26 -0
- package/build/manager/plugins/re-captcha.js.map +1 -0
- package/build/manager/plugins/tunnel/consts.d.ts +4 -0
- package/build/manager/plugins/tunnel/consts.d.ts.map +1 -0
- package/build/manager/plugins/tunnel/consts.js +9 -0
- package/build/manager/plugins/tunnel/consts.js.map +1 -0
- package/build/manager/plugins/tunnel/index.d.ts +4 -0
- package/build/manager/plugins/tunnel/index.d.ts.map +1 -0
- package/build/manager/plugins/tunnel/index.js +3 -0
- package/build/manager/plugins/tunnel/index.js.map +1 -0
- package/build/manager/plugins/tunnel/types.d.ts +13 -0
- package/build/manager/plugins/tunnel/types.d.ts.map +1 -0
- package/build/manager/plugins/tunnel/types.js +2 -0
- package/build/manager/plugins/tunnel/types.js.map +1 -0
- package/build/manager/plugins/tunnel/wallet.d.ts +4 -0
- package/build/manager/plugins/tunnel/wallet.d.ts.map +1 -0
- package/build/manager/plugins/tunnel/wallet.js +32 -0
- package/build/manager/plugins/tunnel/wallet.js.map +1 -0
- package/build/manager/plugins/tunnel-consumer.d.ts +3 -0
- package/build/manager/plugins/tunnel-consumer.d.ts.map +1 -0
- package/build/manager/plugins/tunnel-consumer.js +81 -0
- package/build/manager/plugins/tunnel-consumer.js.map +1 -0
- package/build/manager/plugins/types.d.ts +11 -0
- package/build/manager/plugins/types.d.ts.map +1 -0
- package/build/manager/plugins/types.js +2 -0
- package/build/manager/plugins/types.js.map +1 -0
- package/build/modules.d.ts +4 -0
- package/build/modules.d.ts.map +1 -0
- package/build/modules.js +9 -0
- package/build/modules.js.map +1 -0
- package/build/service.d.ts +6 -0
- package/build/service.d.ts.map +1 -0
- package/build/service.js +71 -0
- package/build/service.js.map +1 -0
- package/build/types.d.ts +13 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/package.json +79 -0
- package/src/components/dispatcher/component.tsx +84 -0
- package/src/components/dispatcher/index.ts +3 -0
- package/src/components/dispatcher/types.ts +24 -0
- package/src/components/index.ts +2 -0
- package/src/consts.ts +6 -0
- package/src/helper.ts +39 -0
- package/src/index.ts +7 -0
- package/src/manager/README.md +463 -0
- package/src/manager/components/authentication/component.tsx +34 -0
- package/src/manager/components/authentication/consts.ts +2 -0
- package/src/manager/components/authentication/control.ts +193 -0
- package/src/manager/components/authentication/index.ts +4 -0
- package/src/manager/components/authentication/types.ts +74 -0
- package/src/manager/components/index.ts +4 -0
- package/src/manager/components/tunnel-consumer.tsx +15 -0
- package/src/manager/components/types.ts +11 -0
- package/src/manager/errors.ts +14 -0
- package/src/manager/index.ts +4 -0
- package/src/manager/modules.ts +18 -0
- package/src/manager/plugins/basic-ed25519.tsx +42 -0
- package/src/manager/plugins/exports.ts +5 -0
- package/src/manager/plugins/index.ts +13 -0
- package/src/manager/plugins/re-captcha.tsx +31 -0
- package/src/manager/plugins/tunnel/consts.ts +12 -0
- package/src/manager/plugins/tunnel/index.ts +5 -0
- package/src/manager/plugins/tunnel/types.ts +15 -0
- package/src/manager/plugins/tunnel/wallet.ts +43 -0
- package/src/manager/plugins/tunnel-consumer.tsx +100 -0
- package/src/manager/plugins/types.ts +14 -0
- package/src/modules.ts +13 -0
- package/src/service.ts +106 -0
- package/src/types.ts +15 -0
- package/tsconfig.json +15 -0
- 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,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
|
+
}
|
package/src/consts.ts
ADDED
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,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
|
+
}
|