@authhero/widget 0.2.2
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 +299 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 authhero
|
|
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,299 @@
|
|
|
1
|
+
# @authhero/widget
|
|
2
|
+
|
|
3
|
+
A Server-Driven UI widget for AuthHero authentication flows. Built with [StencilJS](https://stenciljs.com/) for framework-agnostic web components.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Auth0 Forms Compatible**: Uses Auth0's Forms API schema for universal login flows
|
|
8
|
+
- **Server-Driven UI (SDUI)**: The server controls what UI elements to render
|
|
9
|
+
- **Zero-Deploy Updates**: Update your auth flows without redeploying the widget
|
|
10
|
+
- **Event-Based Architecture**: Pure UI component that emits events for auth library integration
|
|
11
|
+
- **Framework Agnostic**: Works with React, Vue, Angular, or vanilla JS
|
|
12
|
+
- **Customizable**: Supports branding via CSS custom properties
|
|
13
|
+
- **SSR Support**: Includes hydrate scripts for server-side rendering
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @authhero/widget
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Browser (CDN)
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<script type="module" src="https://unpkg.com/@authhero/widget/dist/authhero-widget/authhero-widget.esm.js"></script>
|
|
27
|
+
|
|
28
|
+
<authhero-widget
|
|
29
|
+
api-url="/u/flow/screen"
|
|
30
|
+
auto-submit="false">
|
|
31
|
+
</authhero-widget>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### With a JavaScript Framework
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import '@authhero/widget';
|
|
38
|
+
|
|
39
|
+
// Or with the loader for lazy-loading
|
|
40
|
+
import { defineCustomElements } from '@authhero/widget/loader';
|
|
41
|
+
defineCustomElements();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<authhero-widget
|
|
46
|
+
api-url="/u/flow/screen"
|
|
47
|
+
auto-submit="false">
|
|
48
|
+
</authhero-widget>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Server-Side Rendering (Hono)
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { renderToString } from '@authhero/widget/hydrate';
|
|
55
|
+
|
|
56
|
+
const html = await renderToString(`
|
|
57
|
+
<authhero-widget screen='${JSON.stringify(screenConfig)}'></authhero-widget>
|
|
58
|
+
`);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## UI Schema (Auth0 Forms API)
|
|
62
|
+
|
|
63
|
+
The widget renders UI based on Auth0's Forms API schema for universal login flows.
|
|
64
|
+
|
|
65
|
+
### Component Types
|
|
66
|
+
|
|
67
|
+
The widget supports [27+ Auth0 component types](https://auth0.com/docs/authenticate/login/auth0-universal-login/new-experience/universal-login-page-templates):
|
|
68
|
+
|
|
69
|
+
| Component | Description |
|
|
70
|
+
|-----------|-------------|
|
|
71
|
+
| `heading` | Page headings and titles |
|
|
72
|
+
| `description` | Descriptive text |
|
|
73
|
+
| `text-input` | Text, email, phone inputs |
|
|
74
|
+
| `password-input` | Password field with show/hide toggle |
|
|
75
|
+
| `checkbox-input` | Checkboxes |
|
|
76
|
+
| `select-input` | Dropdown selects |
|
|
77
|
+
| `submit-button` | Primary action buttons |
|
|
78
|
+
| `button` | Secondary action buttons |
|
|
79
|
+
| `social-button-group` | Social login buttons |
|
|
80
|
+
| `anchor` | Links and navigation |
|
|
81
|
+
| `separator` | Visual dividers |
|
|
82
|
+
| `image` | Logos and images |
|
|
83
|
+
| And more... | Phone input, captcha, MFA, etc. |
|
|
84
|
+
|
|
85
|
+
### Screen Configuration
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
interface UIScreen {
|
|
89
|
+
title?: string; // Screen title
|
|
90
|
+
description?: string; // Screen description
|
|
91
|
+
components: UIComponent[]; // UI components to render
|
|
92
|
+
branding?: {
|
|
93
|
+
logoUrl?: string;
|
|
94
|
+
primaryColor?: string;
|
|
95
|
+
backgroundColor?: string;
|
|
96
|
+
};
|
|
97
|
+
theme?: string; // Theme configuration JSON
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface UIComponent {
|
|
101
|
+
component: string; // Component type (e.g., 'text-input', 'submit-button')
|
|
102
|
+
id: string; // Component identifier
|
|
103
|
+
label?: string; // Display label
|
|
104
|
+
[key: string]: any; // Component-specific props
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Example: Login Screen
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"title": "Sign in to your account",
|
|
113
|
+
"components": [
|
|
114
|
+
{
|
|
115
|
+
"component": "heading",
|
|
116
|
+
"id": "heading",
|
|
117
|
+
"content": "Welcome back"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"component": "text-input",
|
|
121
|
+
"id": "email",
|
|
122
|
+
"name": "email",
|
|
123
|
+
"label": "Email address",
|
|
124
|
+
"type": "email",
|
|
125
|
+
"required": true,
|
|
126
|
+
"autocomplete": "email"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"component": "password-input",
|
|
130
|
+
"id": "password",
|
|
131
|
+
"name": "password",
|
|
132
|
+
"label": "Password",
|
|
133
|
+
"required": true,
|
|
134
|
+
"autocomplete": "current-password"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"component": "submit-button",
|
|
138
|
+
"id": "submit",
|
|
139
|
+
"label": "Continue",
|
|
140
|
+
"action": "submit"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"component": "anchor",
|
|
144
|
+
"id": "forgot",
|
|
145
|
+
"content": "Forgot password?",
|
|
146
|
+
"href": "/forgot-password"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Social Login
|
|
153
|
+
|
|
154
|
+
Social buttons are configured using the `social-button-group` component:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"component": "social-button-group",
|
|
159
|
+
"id": "social",
|
|
160
|
+
"connections": [
|
|
161
|
+
{
|
|
162
|
+
"name": "google-oauth2",
|
|
163
|
+
"label": "Continue with Google"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "github",
|
|
167
|
+
"label": "Continue with GitHub"
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Props
|
|
174
|
+
|
|
175
|
+
| Prop | Type | Default | Description |
|
|
176
|
+
|------|------|---------|-------------|
|
|
177
|
+
| `screen` | `string \| UIScreen` | - | Screen configuration (JSON string or object) |
|
|
178
|
+
| `api-url` | `string` | - | API endpoint for screen fetching |
|
|
179
|
+
| `branding` | `string \| Branding` | - | Branding configuration |
|
|
180
|
+
| `theme` | `string` | - | Theme configuration JSON |
|
|
181
|
+
| `loading` | `boolean` | `false` | Loading state |
|
|
182
|
+
| `auto-submit` | `boolean` | `false` | Auto-submit forms (not recommended, use events instead) |
|
|
183
|
+
|
|
184
|
+
## Events
|
|
185
|
+
|
|
186
|
+
The widget is a **pure UI component** that emits events for your auth library to handle. It does not manage tokens, sessions, or HTTP requests.
|
|
187
|
+
|
|
188
|
+
| Event | Detail | Description |
|
|
189
|
+
|-------|--------|-------------|
|
|
190
|
+
| `formSubmit` | `{ data: FormData, screen: UIScreen }` | Form submitted by user |
|
|
191
|
+
| `buttonClick` | `{ id: string, action: string }` | Button clicked |
|
|
192
|
+
| `linkClick` | `{ href: string }` | Link clicked |
|
|
193
|
+
| `navigate` | `{ to: string }` | Navigation requested |
|
|
194
|
+
| `flowComplete` | `{ result: any }` | Auth flow completed successfully |
|
|
195
|
+
| `flowError` | `{ error: Error }` | Auth flow error occurred |
|
|
196
|
+
| `screenChange` | `UIScreen` | Screen changed |
|
|
197
|
+
|
|
198
|
+
### Event-Based Integration (Recommended)
|
|
199
|
+
|
|
200
|
+
The recommended approach is to handle events and let your auth library manage the flow:
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
const widget = document.querySelector('authhero-widget');
|
|
204
|
+
|
|
205
|
+
widget.addEventListener('formSubmit', async (e) => {
|
|
206
|
+
const { data, screen } = e.detail;
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
// Your auth library handles the HTTP request
|
|
210
|
+
const response = await fetch('/u/flow/screen', {
|
|
211
|
+
method: 'POST',
|
|
212
|
+
body: data,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const nextScreen = await response.json();
|
|
216
|
+
widget.screen = JSON.stringify(nextScreen);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
widget.dispatchEvent(new CustomEvent('flowError', { detail: { error } }));
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
widget.addEventListener('linkClick', (e) => {
|
|
223
|
+
// Handle navigation
|
|
224
|
+
window.location.href = e.detail.href;
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Auto-Submit Mode (Not Recommended)
|
|
229
|
+
|
|
230
|
+
For simple use cases, the widget can handle HTTP requests automatically:
|
|
231
|
+
|
|
232
|
+
```html
|
|
233
|
+
<authhero-widget
|
|
234
|
+
api-url="/u/flow/screen"
|
|
235
|
+
auto-submit="true">
|
|
236
|
+
</authhero-widget>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
⚠️ **Note**: Auto-submit mode is provided for convenience but is not recommended for production. Use the event-based approach for proper error handling, token management, and integration with auth libraries like Auth0 SPA SDK.
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Customization
|
|
243
|
+
|
|
244
|
+
### CSS Custom Properties
|
|
245
|
+
|
|
246
|
+
```css
|
|
247
|
+
authhero-widget {
|
|
248
|
+
--primary-color: #0066cc;
|
|
249
|
+
--background-color: #ffffff;
|
|
250
|
+
--text-color: #333333;
|
|
251
|
+
--border-radius: 8px;
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Server-Side Branding
|
|
256
|
+
|
|
257
|
+
Include branding in the screen configuration:
|
|
258
|
+
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"branding": {
|
|
262
|
+
"logoUrl": "https://example.com/logo.png",
|
|
263
|
+
"primaryColor": "#ff6600",
|
|
264
|
+
"backgroundColor": "#f5f5f5"
|
|
265
|
+
},
|
|
266
|
+
"components": [...]
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Integration Patterns
|
|
271
|
+
|
|
272
|
+
See [`packages/authhero/FLOWS.md`](../authhero/FLOWS.md) for detailed integration patterns including:
|
|
273
|
+
|
|
274
|
+
1. **Event-Based (Recommended)** - Full control with auth libraries like Auth0 SPA SDK
|
|
275
|
+
2. **Auto-Submit Mode** - Simple hosted page integration
|
|
276
|
+
3. **Auth0 SPA SDK Integration** - Using `loginWithRedirect()` and callback handling
|
|
277
|
+
4. **Custom Token Management** - Custom refresh token and session handling
|
|
278
|
+
5. **Generic Forms** - Non-auth form use cases
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Development
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# Install dependencies
|
|
285
|
+
pnpm install
|
|
286
|
+
|
|
287
|
+
# Start development server
|
|
288
|
+
pnpm dev
|
|
289
|
+
|
|
290
|
+
# Build for production
|
|
291
|
+
pnpm build
|
|
292
|
+
|
|
293
|
+
# Run tests
|
|
294
|
+
pnpm test
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@authhero/widget",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Server-Driven UI widget for AuthHero authentication flows",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/markusahlstrand/authhero",
|
|
8
|
+
"directory": "packages/ui-widget"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"hydrate/",
|
|
13
|
+
"loader/"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/index.cjs.js",
|
|
16
|
+
"module": "./dist/index.js",
|
|
17
|
+
"es2015": "./dist/esm/index.js",
|
|
18
|
+
"es2017": "./dist/esm/index.js",
|
|
19
|
+
"types": "./dist/types/index.d.ts",
|
|
20
|
+
"collection": "./dist/collection/collection-manifest.json",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": "./dist/index.js",
|
|
23
|
+
"./hydrate": "./hydrate/index.js",
|
|
24
|
+
"./loader": "./loader/index.js",
|
|
25
|
+
"./server": {
|
|
26
|
+
"import": "./dist/collection/server/index.js",
|
|
27
|
+
"types": "./dist/types/server/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./types": {
|
|
30
|
+
"import": "./dist/collection/types/components.js",
|
|
31
|
+
"types": "./dist/types/types/components.d.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@authhero/adapter-interfaces": "0.115.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@stencil/core": "^4.40.1",
|
|
39
|
+
"@types/jest": "^29.5.14",
|
|
40
|
+
"jest": "^29.7.0",
|
|
41
|
+
"jest-cli": "^29.7.0"
|
|
42
|
+
},
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "stencil build",
|
|
46
|
+
"dev": "stencil build --dev --watch --serve",
|
|
47
|
+
"test": "stencil test --spec",
|
|
48
|
+
"test:watch": "stencil test --spec --watchAll",
|
|
49
|
+
"generate": "stencil generate"
|
|
50
|
+
}
|
|
51
|
+
}
|