
# React SDK

`@keenauth/react` gives you embeddable sign-in, sign-up and account components and the hooks under them. It runs on the browser core [`@keenauth/js`](/docs/sdk/js), which does every network call, PKCE, DPoP and WebAuthn ceremony; the components never call `fetch` or WebCrypto themselves. The package is not published to npm yet.

For a redirect sign-in to the hosted login page, you do not need this package: see the [React quickstart](/docs/quickstarts/react), which uses `@keenauth/js` directly.

## Set up the provider

Create the core once and pass it to `KeenAuthProvider`. Pass the React package's error class to the core, so that the components recognise server problems:

```tsx
import { KeenAuth } from "@keenauth/js";
import { KeenAuthProblemError, KeenAuthProvider, SignIn } from "@keenauth/react";

const core = new KeenAuth({
  issuer: "https://acme.eu.keenauth.app",
  clientId: "app_01j9zzzzzzzzzzzzzzzzzzzz",
  redirectUri: "https://login.acme.example/callback",
  createProblemError: (problem) => new KeenAuthProblemError(problem),
});

export function App() {
  return (
    <KeenAuthProvider core={core} locale="en">
      <SignIn transaction={{ client_id: "app_01j9zzzzzzzzzzzzzzzzzzzz", redirect_uri: "https://login.acme.example/callback" }} />
    </KeenAuthProvider>
  );
}
```

`KeenAuthProvider` takes:

| Prop | Meaning |
|---|---|
| `core` | The `@keenauth/js` client (any object that implements the `KeenAuthCore` contract) |
| `locale` | UI language (BCP 47); default `en` |
| `appearance` | Optional theme overrides, see [Appearance](#appearance) |

The components call the front API (`/fapi/v1`) with your environment's cookies and a CSRF header. The server accepts these calls only from the environment's own login origin, and only for first-party applications.

## Components

| Component | What it does |
|---|---|
| `SignIn` | Identifier-first sign-in: password, passkey, email code or magic link, and second factors |
| `SignUp` | Sign-up with the environment's registration settings |
| `UserProfile` | The signed-in user's profile, emails (with code verification), passkeys and sessions |

`SignIn` and `SignUp` take `transaction`, the body that starts a sign-in transaction:

- in the redirect flow, `{ authorization_request: "azr_…" }` from the authorization request;
- without a redirect, `{ client_id, redirect_uri }` with a registered redirect URI.

`onComplete` is called when the core has finished the transaction in the page; in the redirect flow the page navigates away instead. A step that the components do not draw (for example a challenge or an organization choice) becomes a link to continue on the hosted login page.

`UserProfile` takes `sections`, a subset of `profile`, `emails`, `passkeys` and `sessions` (all four by default). A profile write that conflicts with a change made elsewhere shows an error and reloads the current values.

## Hooks

| Hook | Returns |
|---|---|
| `useKeenAuth()` | The provider value: `core`, `locale`, `appearance` |
| `useEnvironment()` | The environment's sign-in settings and a text lookup `t` for the active locale |
| `useTransaction()` | A transaction state machine over the core's `transactions` API |
| `useMe()` | The signed-in user's profile and the account API |

## Appearance

`appearance.variables` overrides theme tokens (for example `color.primary`); they are written as `--idp-*` custom properties on the component root through the CSSOM, so a strict Content Security Policy without `'unsafe-inline'` styles works. `appearance.elements` adds your class names to the components' elements. The package ships no stylesheet: style the `idp-*` classes in your own CSS.

```tsx
<KeenAuthProvider core={core} appearance={{ variables: { "color.primary": "#1f6feb" }, elements: { buttonPrimary: "acme-button" } }}>
```

## Languages and accessibility

- The components include texts in English, Turkish, French, German, Korean, Japanese, Italian and Spanish. Your environment's text overrides come first; another locale falls back to English, with the text direction of that locale.
- Every input has a label, the error summary takes focus, `autocomplete` values are set and paste is never blocked.

## Passkeys

The passkey button appears when the passkey's relying party ID covers the page's host (or the page's origin is a related origin of the environment); otherwise the component links to the hosted login page. Passkeys need a secure context (`https` or `localhost`).

## Current limits

- Social sign-in buttons are not drawn yet; an environment that offers social sign-in gets a link to the hosted login page.
- Phone numbers are not available yet: `UserProfile` has no phone section.
- Organization components (an organization switcher and profile) are not available yet.
