@authrobo/react 0.2.1 → 0.5.1
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/README.md +176 -35
- package/assets/hero.png +0 -0
- package/dist/index.cjs +349 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -15
- package/dist/index.d.ts +81 -15
- package/dist/index.js +357 -54
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,13 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://authrobo.com"><img src="https://cdn.jsdelivr.net/npm/@authrobo/react/assets/hero.png" alt="AuthRobo — drop-in React sign-in" width="100%"></a>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">@authrobo/react</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@authrobo/react"><img src="https://img.shields.io/npm/v/@authrobo/react?logo=npm&color=4f46e5&labelColor=0b1526" alt="npm version"></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/@authrobo/react"><img src="https://img.shields.io/npm/dm/@authrobo/react?color=4f46e5&labelColor=0b1526" alt="npm downloads"></a>
|
|
10
|
+
<img src="https://img.shields.io/bundlejs/size/@authrobo/react?label=min%2Bgzip&color=4f46e5&labelColor=0b1526" alt="min+gzip size">
|
|
11
|
+
<img src="https://img.shields.io/badge/types-included-4f46e5?labelColor=0b1526&logo=typescript&logoColor=white" alt="TypeScript types included">
|
|
12
|
+
<img src="https://img.shields.io/npm/l/@authrobo/react?color=4f46e5&labelColor=0b1526" alt="MIT license">
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<b>Drop-in React sign-in for <a href="https://authrobo.com">AuthRobo</a>.</b><br>
|
|
17
|
+
Renders exactly the methods you've enabled in your dashboard — social (Google, LinkedIn,
|
|
18
|
+
GitHub, Apple, Facebook) plus an email switcher (<b>Magic Link · Register · Login</b>) —
|
|
19
|
+
or compose your own UI from a single configurable button.
|
|
20
|
+
</p>
|
|
6
21
|
|
|
7
22
|
```bash
|
|
8
23
|
npm i @authrobo/react
|
|
9
24
|
```
|
|
10
25
|
|
|
26
|
+
## Contents
|
|
27
|
+
|
|
28
|
+
- [Quick start](#quick-start) — the whole box: `<AuthRoboAuth>`
|
|
29
|
+
- [Just one button](#just-one-button) — `<AuthRoboButton>`, single or mapped
|
|
30
|
+
- [Two ways to sign in](#two-ways-to-sign-in-direct-vs-proxied) — direct vs. `startPath`
|
|
31
|
+
- [The proxy server contract](#the-proxy-server-contract) — routes your app implements
|
|
32
|
+
- [Theming](#theming)
|
|
33
|
+
- [API](#api)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
11
37
|
## Quick start
|
|
12
38
|
|
|
13
39
|
Wrap your app once with your AuthRobo config:
|
|
@@ -18,7 +44,7 @@ import { AuthRoboProvider } from "@authrobo/react";
|
|
|
18
44
|
<AuthRoboProvider
|
|
19
45
|
config={{
|
|
20
46
|
issuerUrl: "https://authrobo.com",
|
|
21
|
-
clientId: process.env.NEXT_PUBLIC_AUTHROBO_CLIENT_ID!, // arc_...
|
|
47
|
+
clientId: process.env.NEXT_PUBLIC_AUTHROBO_CLIENT_ID!, // arc_... (public)
|
|
22
48
|
redirectUri: "https://yourapp.com/auth/callback",
|
|
23
49
|
}}
|
|
24
50
|
>
|
|
@@ -26,18 +52,8 @@ import { AuthRoboProvider } from "@authrobo/react";
|
|
|
26
52
|
</AuthRoboProvider>;
|
|
27
53
|
```
|
|
28
54
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { AuthRoboButton } from "@authrobo/react";
|
|
33
|
-
|
|
34
|
-
<AuthRoboButton provider="linkedin" />;
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### The auto-configured auth panel / modal
|
|
38
|
-
|
|
39
|
-
`<AuthRoboAuth>` calls AuthRobo's public `/api/v1/config` endpoint and renders a
|
|
40
|
-
button for every method you've turned on — no need to hard-code the list.
|
|
55
|
+
Then drop in the full widget. It calls AuthRobo's public `/api/v1/config` and
|
|
56
|
+
renders only what you've enabled:
|
|
41
57
|
|
|
42
58
|
```tsx
|
|
43
59
|
import { AuthRoboAuth } from "@authrobo/react";
|
|
@@ -51,26 +67,151 @@ const [open, setOpen] = useState(false);
|
|
|
51
67
|
<AuthRoboAuth mode="modal" open={open} onClose={() => setOpen(false)} />
|
|
52
68
|
```
|
|
53
69
|
|
|
54
|
-
|
|
70
|
+
**What the email switcher collects** (each tab shows exactly its flow's fields):
|
|
71
|
+
|
|
72
|
+
| Tab | Fields | Result |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| **Magic Link** | email | a one-time sign-in link is emailed |
|
|
75
|
+
| **Register** | name · email · password | creates the account |
|
|
76
|
+
| **Login** | email · password | signs in |
|
|
77
|
+
|
|
78
|
+
Magic Link is first; a tab only appears if its method is enabled (`magic_link`
|
|
79
|
+
for Magic Link, `password` for Register + Login).
|
|
80
|
+
|
|
81
|
+
## Just one button
|
|
82
|
+
|
|
83
|
+
Don't want the whole box? Use `<AuthRoboButton>` — it takes a `provider` and
|
|
84
|
+
renders that provider's branded button. Perfect for a single "Continue with
|
|
85
|
+
Google", or map an array to lay them out however your design wants:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { AuthRoboButton } from "@authrobo/react";
|
|
89
|
+
|
|
90
|
+
// one button
|
|
91
|
+
<AuthRoboButton provider="google" />
|
|
92
|
+
|
|
93
|
+
// your own set, your own layout
|
|
94
|
+
<div className="grid gap-2">
|
|
95
|
+
{["google", "linkedin", "github"].map((p) => (
|
|
96
|
+
<AuthRoboButton key={p} provider={p} />
|
|
97
|
+
))}
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
// custom label / classes
|
|
101
|
+
<AuthRoboButton provider="github" label="Sign in with GitHub" className="my-btn" />
|
|
102
|
+
```
|
|
55
103
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
`
|
|
59
|
-
|
|
60
|
-
|
|
104
|
+
`provider` is any enabled method (`"google" | "linkedin" | "github" | "apple" |
|
|
105
|
+
"facebook" | "password" | "magic_link"`). Clicking begins that flow via
|
|
106
|
+
`startSignIn` — pass `startPath` here too if you proxy (see below).
|
|
107
|
+
|
|
108
|
+
### Neutral or branded buttons
|
|
109
|
+
|
|
110
|
+
By default social buttons share one consistent, themeable chrome (`buttonStyle="neutral"`).
|
|
111
|
+
Switch to `buttonStyle="branded"` to give each button its provider's own colours —
|
|
112
|
+
LinkedIn blue, GitHub black, Google white with a Google-blue label, Facebook blue,
|
|
113
|
+
Apple black (monochrome glyphs flip to white for legibility):
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
<AuthRoboAuth buttonStyle="branded" />
|
|
117
|
+
<AuthRoboButton provider="linkedin" buttonStyle="branded" />
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Loading & the config cache
|
|
121
|
+
|
|
122
|
+
`<AuthRoboProvider>` **prefetches** your app's enabled methods the moment it
|
|
123
|
+
mounts — i.e. on app start — and caches them per `(issuer, clientId)`. So by the
|
|
124
|
+
time a login modal or page opens, the methods are already resolved: no
|
|
125
|
+
request-on-open, no flash. (Not using the provider? Call `prefetchAppConfig(config)`
|
|
126
|
+
yourself on app start.) While anything is loading, a theme-aware `<Spinner>` is
|
|
127
|
+
shown (it inherits `currentColor`, so it matches whatever you've themed).
|
|
128
|
+
|
|
129
|
+
## Two ways to sign in (direct vs. proxied)
|
|
130
|
+
|
|
131
|
+
The same components support two flows; pick with the `startPath` prop.
|
|
132
|
+
|
|
133
|
+
**Direct (default).** No backend beyond one callback. Social buttons redirect to
|
|
134
|
+
the provider; the Login/Register forms do a native cross-origin form POST to
|
|
135
|
+
AuthRobo's `authorize` endpoint; Magic Link posts to `magic/start`. AuthRobo
|
|
136
|
+
returns to your `redirectUri` with a one-time `code`; your server exchanges it
|
|
137
|
+
(with your `client_secret`) for tokens. Credentials go straight to AuthRobo —
|
|
138
|
+
never to your own server.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<AuthRoboAuth /> // uses config.redirectUri
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Proxied (`startPath`).** Best when you keep the session in **httpOnly
|
|
145
|
+
cookies**. Every action is proxied through your own server so the CSRF state
|
|
146
|
+
cookie and the token exchange stay first-party. Password login/register become a
|
|
147
|
+
same-origin JSON POST that sets your cookies with **no page redirect**, so
|
|
148
|
+
`onSuccess` fires and you can close your modal in place:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<AuthRoboAuth
|
|
152
|
+
startPath="/api/auth"
|
|
153
|
+
onSuccess={() => { refreshSession(); close(); }}
|
|
154
|
+
/>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
> **Note:** in direct mode the password field lives in your app's DOM (submitted
|
|
158
|
+
> to AuthRobo). If you require the credential entry to be isolated on AuthRobo's
|
|
159
|
+
> origin, use `<AuthRoboButton provider="password" />`, which redirects to the
|
|
160
|
+
> hosted page instead.
|
|
161
|
+
|
|
162
|
+
## The proxy server contract
|
|
163
|
+
|
|
164
|
+
When you pass `startPath`, the components call these routes on **your** server
|
|
165
|
+
(shown for `startPath="/api/auth"`). Each one forwards to AuthRobo and manages
|
|
166
|
+
your session cookies:
|
|
167
|
+
|
|
168
|
+
| Trigger | Request | Your route should |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| Social button | `GET /api/auth/{provider}/start` | set a CSRF state cookie, redirect to AuthRobo's provider start with your callback as `redirect_uri` |
|
|
171
|
+
| Login | `POST /api/auth/login` `{ email, password }` | password-grant to AuthRobo, set httpOnly cookies, `2xx` |
|
|
172
|
+
| Register | `POST /api/auth/register` `{ name?, email, password }` | create + set cookies, `2xx` |
|
|
173
|
+
| Magic Link | `POST /api/auth/magic` `{ email }` | call AuthRobo `magic/start`, `2xx` |
|
|
174
|
+
| Callback | `GET /api/auth/{method}/callback?code=…` | exchange the code (+ `client_secret`) for tokens, set cookies |
|
|
175
|
+
|
|
176
|
+
On a non-`2xx`, return `{ "error": "message" }` — the widget shows it inline.
|
|
177
|
+
(See AuthRobo's docs for a copy-pasteable Next.js implementation of these routes.)
|
|
178
|
+
|
|
179
|
+
## Theming
|
|
180
|
+
|
|
181
|
+
Styling is self-contained and theme-aware (light/dark via `prefers-color-scheme`
|
|
182
|
+
or a `data-theme` attribute). Override any CSS variable on an ancestor to brand
|
|
183
|
+
it — e.g. `--authrobo-accent` / `--authrobo-accent-fg` recolour the active tab
|
|
184
|
+
and the primary button:
|
|
185
|
+
|
|
186
|
+
```css
|
|
187
|
+
.my-auth .authrobo-stack,
|
|
188
|
+
.my-auth .authrobo-btn {
|
|
189
|
+
--authrobo-accent: #f5b81d;
|
|
190
|
+
--authrobo-accent-fg: #1c1400;
|
|
191
|
+
--authrobo-input-bg: #070f1d;
|
|
192
|
+
--authrobo-btn-bg: #070f1d;
|
|
193
|
+
--authrobo-tabs-bg: #070f1d;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Other tokens: `--authrobo-btn-*`, `--authrobo-input-fg`, `--authrobo-title-fg`,
|
|
198
|
+
`--authrobo-muted`, `--authrobo-divider-*`, `--authrobo-focus`, `--authrobo-error`.
|
|
61
199
|
|
|
62
200
|
## API
|
|
63
201
|
|
|
64
|
-
- `AuthRoboProvider({ config, children })` — supplies config via context
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
- `
|
|
202
|
+
- `AuthRoboProvider({ config, children })` — supplies config via context **and
|
|
203
|
+
prefetches** the app config on mount.
|
|
204
|
+
- `AuthRoboButton({ provider, config?, label?, className?, style?, onClick?, startPath?, lastUsed?, buttonStyle? })` —
|
|
205
|
+
one button. `provider` is any enabled `Method`; `buttonStyle` is `"neutral" | "branded"`.
|
|
206
|
+
- `AuthRoboAuth({ config?, mode?, open?, onClose?, onSuccess?, title?, showHeader?, methods?, startPath?, buttonStyle? })` —
|
|
207
|
+
the full widget: social buttons + the email switcher. `methods` restricts/reorders;
|
|
208
|
+
`showHeader={false}` hides the logo/title row when you supply your own heading.
|
|
209
|
+
- `useAppConfig(config?)` → `{ data, loading, error }` — branding + enabled methods (cached).
|
|
210
|
+
- `prefetchAppConfig(config)` → `Promise<void>` — warm the cache on app start.
|
|
211
|
+
- `useLastMethod(clientId)` → `Method | null` — the method last used on this client.
|
|
212
|
+
- `startSignIn(config, method, opts?)` — imperatively begin a flow. `opts`:
|
|
213
|
+
`{ state?, loginHint?, screen?: "login" | "register" | "magic", startPath? }`.
|
|
214
|
+
- `Spinner({ style?, className? })` — the theme-aware loading spinner.
|
|
215
|
+
- `PROVIDER_META` / `BRAND_STYLE` — `{ label, icon }` and the branded palette per method.
|
|
72
216
|
|
|
73
217
|
`config` can come from `<AuthRoboProvider>` or be passed per-component.
|
|
74
|
-
|
|
75
|
-
Styling is self-contained (no CSS import needed); pass `className`/`style` to
|
|
76
|
-
override, or restyle the `.authrobo-*` classes.
|
package/assets/hero.png
ADDED
|
Binary file
|