@authrobo/react
v0.10.0
Published
React sign-in buttons and a configurable auth modal for AuthRobo — Google, LinkedIn, GitHub, Apple, Facebook, and email.
Downloads
118
Maintainers
Readme
npm i @authrobo/reactContents
- Quick start — the whole box:
<AuthRoboAuth> - Just one button —
<AuthRoboButton>, single or mapped - Two ways to sign in — direct vs.
startPath - The proxy server contract — routes your app implements
- Theming
- API
Quick start
Wrap your app once with your AuthRobo config:
import { AuthRoboProvider } from "@authrobo/react";
<AuthRoboProvider
config={{
issuerUrl: "https://authrobo.com",
clientId: process.env.NEXT_PUBLIC_AUTHROBO_CLIENT_ID!, // arc_... (public)
redirectUri: "https://yourapp.com/auth/callback",
}}
>
<App />
</AuthRoboProvider>;Then drop in the full widget. It calls AuthRobo's public /api/v1/config and
renders only what you've enabled:
import { AuthRoboAuth } from "@authrobo/react";
// Inline (renders in place)
<AuthRoboAuth />
// Modal
const [open, setOpen] = useState(false);
<button onClick={() => setOpen(true)}>Sign in</button>
<AuthRoboAuth mode="modal" open={open} onClose={() => setOpen(false)} />What the email switcher collects (each tab shows exactly its flow's fields):
| Tab | Fields | Result | | --- | --- | --- | | Magic Link | email | a one-time sign-in link is emailed | | Register | name · email · password | creates the account | | Login | email · password | signs in |
Magic Link is first; a tab only appears if its method is enabled (magic_link
for Magic Link, password for Register + Login).
Just one button
Don't want the whole box? Use <AuthRoboButton> — it takes a provider and
renders that provider's branded button. Perfect for a single "Continue with
Google", or map an array to lay them out however your design wants:
import { AuthRoboButton } from "@authrobo/react";
// one button
<AuthRoboButton provider="google" />
// your own set, your own layout
<div className="grid gap-2">
{["google", "linkedin", "github"].map((p) => (
<AuthRoboButton key={p} provider={p} />
))}
</div>
// custom label / classes
<AuthRoboButton provider="github" label="Sign in with GitHub" className="my-btn" />provider is any enabled method ("google" | "linkedin" | "github" | "apple" |
"facebook" | "password" | "magic_link"). Clicking begins that flow via
startSignIn — pass startPath here too if you proxy (see below).
Neutral or branded buttons
By default social buttons share one consistent, themeable chrome (buttonStyle="neutral").
Switch to buttonStyle="branded" to give each button its provider's own colours —
LinkedIn blue, GitHub black, Google white with a Google-blue label, Facebook blue,
Apple black (monochrome glyphs flip to white for legibility):
<AuthRoboAuth buttonStyle="branded" />
<AuthRoboButton provider="linkedin" buttonStyle="branded" />Loading & the config cache
<AuthRoboProvider> prefetches your app's enabled methods the moment it
mounts — i.e. on app start — and caches them per (issuer, clientId). So by the
time a login modal or page opens, the methods are already resolved: no
request-on-open, no flash. (Not using the provider? Call prefetchAppConfig(config)
yourself on app start.) While anything is loading, a theme-aware <Spinner> is
shown (it inherits currentColor, so it matches whatever you've themed).
Two ways to sign in (direct vs. proxied)
The same components support two flows; pick with the startPath prop.
Direct (default). No backend beyond one callback. Social buttons redirect to
the provider; the Login/Register forms do a native cross-origin form POST to
AuthRobo's authorize endpoint; Magic Link posts to magic/start. AuthRobo
returns to your redirectUri with a one-time code; your server exchanges it
(with your client_secret) for tokens. Credentials go straight to AuthRobo —
never to your own server.
<AuthRoboAuth /> // uses config.redirectUriProxied (startPath). Best when you keep the session in httpOnly
cookies. Every action is proxied through your own server so the CSRF state
cookie and the token exchange stay first-party. Password login/register become a
same-origin JSON POST that sets your cookies with no page redirect, so
onSuccess fires and you can close your modal in place:
<AuthRoboAuth
startPath="/api/auth"
onSuccess={() => { refreshSession(); close(); }}
/>Note: in direct mode the password field lives in your app's DOM (submitted to AuthRobo). If you require the credential entry to be isolated on AuthRobo's origin, use
<AuthRoboButton provider="password" />, which redirects to the hosted page instead.
The proxy server contract
When you pass startPath, the components call these routes on your server
(shown for startPath="/api/auth"). Each one forwards to AuthRobo and manages
your session cookies:
| Trigger | Request | Your route should |
| --- | --- | --- |
| Social button | GET /api/auth/{provider}/start | set a CSRF state cookie, redirect to AuthRobo's provider start with your callback as redirect_uri |
| Login | POST /api/auth/login { email, password } | password-grant to AuthRobo, set httpOnly cookies, 2xx |
| Register | POST /api/auth/register { name?, email, password } | create + set cookies, 2xx |
| Magic Link | POST /api/auth/magic { email } | call AuthRobo magic/start, 2xx |
| Callback | GET /api/auth/{method}/callback?code=… | exchange the code (+ client_secret) for tokens, set cookies |
On a non-2xx, return { "error": "message" } — the widget shows it inline.
(See AuthRobo's docs for a copy-pasteable Next.js implementation of these routes.)
Theming
The widget ships styled — a polished light/dark modal, not a blank slate.
It's theme-aware (light/dark via prefers-color-scheme or a data-theme
attribute) and defaults to AuthRobo's indigo accent.
Your brand colour — one prop
Recolour the accent (active tab, primary button, input focus) by passing your
colour to accent:
<AuthRoboAuth accent="#f8593c" /> // your brand
<AuthRoboAuth /> // styled indigo defaultThat's it — no CSS, no specificity fight. It's applied inline on the widget
root, so it always wins. accentForeground sets the text/icon colour on the
accent (defaults to white).
AuthRobo doesn't reach into your app to pick a colour — you pass it. If you keep a brand colour on your app in the dashboard and want to reuse it, read it and pass it yourself:
const { data } = useAppConfig(config);
<AuthRoboAuth accent={data?.brandColor ?? undefined} />Mobile presentation
In modal mode, choose how the modal appears on small screens:
<AuthRoboAuth mode="modal" mobileVariant="centered" /> // floating dialog (default)
<AuthRoboAuth mode="modal" mobileVariant="sheet" /> // slide-up bottom sheetFull control
For anything beyond the accent, set the CSS custom-property tokens on the
.authrobo-* elements — or pass unstyled to inject no CSS at all and own the
look entirely (the class names remain as styling hooks). Tokens include
--authrobo-btn-*, --authrobo-input-*, --authrobo-title-fg,
--authrobo-muted, --authrobo-divider-*, --authrobo-focus,
--authrobo-error, --authrobo-card-bg, --authrobo-overlay.
One gotcha if you go the CSS route: the widget's own theme rules are
[data-theme="…"] .authrobo-*(specificity0,2,0), injected after your stylesheet. A selector that only ties (e.g..my-auth .authrobo-stack) loses. Out-specify it —html[data-theme] .authrobo-stackis0,2,1— or just use theaccentprop, which sidesteps the cascade entirely.
API
AuthRoboProvider({ config, children })— supplies config via context, prefetches the app config on mount, and publishes your dashboard brand colour as--authrobo-brand(see Theming).AuthRoboButton({ provider, config?, label?, className?, style?, onClick?, startPath?, lastUsed?, buttonStyle? })— one button.provideris any enabledMethod;buttonStyleis"neutral" | "branded".AuthRoboAuth({ config?, mode?, open?, onClose?, onSuccess?, title?, showHeader?, methods?, startPath?, buttonStyle?, accent?, accentForeground?, mobileVariant? })— the full widget: social buttons + the email switcher.methodsrestricts/reorders;showHeader={false}hides the logo/title row when you supply your own heading;accent/accentForegroundbrand it (see Theming);mobileVariantis"centered"(default) or"sheet"for the modal on small screens.useAppConfig(config?)→{ data, loading, error }— branding + enabled methods (cached).prefetchAppConfig(config)→Promise<void>— warm the cache on app start.useLastMethod(clientId)→Method | null— the method last used on this client.startSignIn(config, method, opts?)— imperatively begin a flow.opts:{ state?, loginHint?, screen?: "login" | "register" | "magic", startPath? }.Spinner({ style?, className? })— the theme-aware loading spinner.PROVIDER_META/BRAND_STYLE—{ label, icon }and the branded palette per method.
config can come from <AuthRoboProvider> or be passed per-component.
