# React SPA with @auth0/auth0-react

## 1. Register the app

Create the application as a Single Page Application in the dashboard. Set:

- Allowed Callback URLs: your dev origin exactly, e.g. `YOUR_HOST:5173` style origin for Vite. Include the port. No trailing slash mismatch.
- Allowed Logout URLs: same origin.
- Allowed Web Origins: same origin (needed for silent auth).

## 2. Provider

```
import { Auth0Provider } from "@auth0/auth0-react";

// Wrap your app in Auth0Provider with these props:
 //  domain               import.meta.env.VITE_AUTH0_DOMAIN
 //  clientId             import.meta.env.VITE_AUTH0_CLIENT_ID
 //  authorizationParams  { redirect_uri: window.location.origin,
 //                         audience: "YOUR-API-IDENTIFIER" }
```

The `audience` is the API identifier you registered under APIs. Without it you get an opaque token that your own API cannot validate. This is the number one miss.

## 3. Login and logout

```
const { loginWithRedirect, logout, user, isAuthenticated } = useAuth0();
loginWithRedirect();
logout({ logoutParams: { returnTo: window.location.origin } });
```

## 4. Call your API

```
const { getAccessTokenSilently } = useAuth0();
const token = [your value] getAccessTokenSilently();
fetch("[your api url]", { headers: { Authorization: "Bearer " + token } });
```

## 5. Safari and silent auth

Silent renewal uses an iframe + cookie. Safari ITP blocks third-party cookies, which breaks it. Fixes in order of preference:

1. Use a custom domain so Auth0 cookies are first-party.
2. Use rotating refresh tokens with `useRefreshTokens` and `cacheLocation="localstorage"` as a fallback (local storage keeps tokens across reloads but is XSS-sensitive; weigh it).
3. Fall back to `loginWithRedirect` on `login_required` errors.

## Checklist

- SPA app type, PKCE is automatic with auth0-react (no client secret in the bundle, ever).
- audience set before first login; changing it later requires a fresh login.
- Every origin you deploy to is registered in all three URL fields.