camel-accounts-react
v0.2.1
Published
React widget for "Sign in with Camel Accounts" — popup-based OAuth login button
Readme
camel-accounts
React widget for "Sign in with Camel Accounts" — drop-in popup-based OAuth login button.
Install
npm install camel-accountsSetup
1. Register your client
Your app needs a client_id registered in Camel Accounts with https://accounts.camelcreatives.com/widget-callback in its redirect_uris:
INSERT INTO oauth_clients (id, name, is_public, redirect_uris, allowed_scopes)
VALUES (
'your-app-web',
'Your App',
true,
ARRAY['https://yourapp.com/callback', 'https://accounts.camelcreatives.com/widget-callback'],
ARRAY['openid', 'profile', 'email']
);2. Wrap your app in CamelAuthProvider
import { CamelAuthProvider } from "camel-accounts";
function App() {
return (
<CamelAuthProvider
issuer="https://accounts.camelcreatives.com"
clientId="your-app-web"
scopes={["openid", "profile", "email"]}
>
<YourRoutes />
</CamelAuthProvider>
);
}3. Add the login button
import { CamelLoginButton, useCamelAuth } from "camel-accounts";
function LoginSection() {
const { user, login, logout, loading, authenticated } = useCamelAuth();
if (loading) return <span>Loading...</span>;
if (authenticated) {
return (
<div>
<span>Signed in as {user?.name ?? user?.email}</span>
<button onClick={logout}>Sign out</button>
</div>
);
}
return <CamelLoginButton onClick={login} />;
}Config
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| issuer | string | (required) | Camel Accounts base URL |
| clientId | string | (required) | Your registered client_id |
| scopes | string[] | ["openid", "profile", "email"] | OAuth scopes to request |
| redirectPath | string | "/widget-callback" | Path on the issuer for the popup callback |
| storage | "memory" \| "localStorage" | "memory" | Where to persist tokens |
API
useCamelAuth()
| Property | Type | Description |
|----------|------|-------------|
| user | CamelAuthUser \| null | Current user info from /oauth/userinfo |
| tokens | CamelAuthTokens \| null | Access + refresh tokens |
| authenticated | boolean | Whether the user has valid tokens |
| loading | boolean | Whether initial token restoration is in progress |
| login | () => void | Opens the popup login flow |
| logout | () => void | Clears tokens and user state |
| getAccessToken | () => string \| null | Returns the current access token |
CamelLoginButton
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onClick | () => void | — | Called when clicked (use login from useCamelAuth) |
| disabled | boolean | false | Disable the button |
| label | string | "Sign in with Camel Accounts" | Button text |
| logo | string | — | URL of the logo image shown on the left (like Google's sign-in button). Falls back to the built-in camel mark if omitted |
Styling
Import the CSS for the default Google-clean button style:
import "camel-accounts/style.css";The button uses minimal CSS with BEM naming (.camel-login-btn). Override with your own styles as needed.
How it works
- User clicks the button →
login()generates a PKCE pair and opens a popup to/oauth/authorize - User logs in and consents in the popup (Camel Accounts cockpit)
- After consent, popup redirects to
/widget-callbackwhich posts the authorization code back to the parent window - The widget exchanges the code for tokens via
/oauth/token - Tokens and user info are available via
useCamelAuth()
Popup security
The callback uses postMessage because the callback page is hosted by Camel
Accounts while the opener is hosted by your application. The SDK accepts a
callback only when the message origin exactly matches the configured issuer,
the message came from the exact popup opened by the SDK, the returned OAuth
state matches the stored value, and the code exchange uses the matching PKCE
verifier.
Do not add another callback listener that accepts camel-auth-callback
messages without applying the same origin and source checks.
Token storage
"memory"(default): Tokens live in React state. Lost on page refresh. Best for SPAs that handle their own session management."localStorage": Tokens persist across refreshes. The widget storesaccess_token,refresh_token, and PKCE state undercamel_auth_*keys.
