@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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +299 -0
  3. 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
+ }