React + Better Auth
Build a React single-page application that uses Better Auth to handle the complete OAuth2/OIDC flow with Paylent. Better Auth manages sessions, user creation, and token exchange — you just configure it as an OAuth provider.
Better Auth gives you a complete auth layer without writing OAuth plumbing. It handles OIDC discovery, PKCE, token exchange, session storage, and user creation — all from a single configuration block. This is especially valuable for React SPAs, where managing auth state across client and server is notoriously tricky. Better Auth’s useSession() hook keeps your components reactive to auth changes without manual token management.
Using a library like Better Auth also means you get refresh token rotation, session revocation, and secure cookie handling out of the box. As your app grows, you can add features like multi-provider login (add Google or GitHub alongside Paylent), email/password fallback, or organization-based access control — all within the same Better Auth configuration. It’s the right choice when you want to ship fast without sacrificing security.
What you’ll build
Section titled “What you’ll build”- A React client (port 3000) with a login button and user profile display
- A Hono server (port 3001) that runs Better Auth and handles OAuth callbacks
Prerequisites
Section titled “Prerequisites”- Paylent running locally (
mix phx.server) - Example data loaded
- Node.js 18+ or Bun
Configure in the dashboard
Section titled “Configure in the dashboard”This example needs a confidential OAuth client with Better Auth’s callback URL pattern.
-
Open the dashboard
Go to
http://dashboard.localhost:4000and log in. Select the examples-dev environment. -
Register an OAuth client
Navigate to Clients in the sidebar, then click Register Application. Fill in:
- Name: My React App
- Client Type: Confidential
- Grant Types: Authorization Code, Refresh Token
- Redirect URIs:
http://localhost:3000/api/auth/oauth2/callback/paylent
The redirect URI follows Better Auth’s OAuth2 callback convention (
/api/auth/oauth2/callback/{providerId}).
-
Copy the client secret
After saving, copy the client secret — this is the only time it’s shown. Add the
client_idandclient_secretto the example’s.envfile.
Run the example
Section titled “Run the example”-
Install dependencies
Terminal window cd examples/react-better-authnpm install -
Start the app
Terminal window npm run devThis starts both the Hono server (port 3001) and the React dev server (port 3000).
-
Open the app
Go to
http://localhost:3000. You’ll see a “Log in with Paylent” button.
-
Log in
Click the button. You’ll be redirected to Paylent’s login page. Enter:
- Email:
[email protected] - Password:
password

- Email:
-
View your profile
After login, the app shows your profile with your name and email. Better Auth handles the session automatically.

How it works
Section titled “How it works”Server configuration
Section titled “Server configuration”The server configures Better Auth with Paylent as a generic OAuth provider:
import { betterAuth } from "better-auth";import { genericOAuth } from "better-auth/plugins";
const auth = betterAuth({ database: new Database(":memory:"), trustedOrigins: ["http://localhost:3000"], plugins: [ genericOAuth({ config: [ { providerId: "paylent", clientId: process.env.PAYLENT_CLIENT_ID!, clientSecret: process.env.PAYLENT_CLIENT_SECRET!, discoveryUrl: `${ISSUER}/.well-known/openid-configuration`, scopes: ["openid", "profile", "email"], pkce: true, }, ], }), ],});Better Auth uses OIDC Discovery (/.well-known/openid-configuration) to find Paylent’s endpoints automatically. It also enables PKCE for added security.
Client configuration
Section titled “Client configuration”The React client uses Better Auth’s client library:
import { createAuthClient } from "better-auth/react";import { genericOAuthClient } from "better-auth/client/plugins";
const authClient = createAuthClient({ baseURL: "http://localhost:3001", plugins: [genericOAuthClient()],});
// Trigger loginauthClient.signIn.oauth2({ providerId: "paylent", callbackURL: "/",});
// Check sessionconst { data: session } = authClient.useSession();What Better Auth handles for you
Section titled “What Better Auth handles for you”- OIDC Discovery and endpoint resolution
- Authorization Code + PKCE flow
- Token exchange and refresh
- Session management (stored in SQLite)
- User creation and profile mapping from OIDC claims
Next steps
Section titled “Next steps”- Hono OIDC — A simpler approach using OIDC middleware directly
- Client & API — Build a resource API that validates tokens
- Users & Roles guide — Add role-based access control