@ouim/simple-logto is a batteries-included auth toolkit for Logto-powered React apps.
It wraps @logto/react with the pieces most teams end up building anyway:
- a higher-level React provider and hook
- ready-made sign-in, callback, and account UI
- backend token verification for Node and Next.js
- bundler fixes for the
joseedge cases that usually slow setup down
If you want Logto without re-assembling the same frontend and backend auth plumbing from scratch, this package is the opinionated fast path.
AuthProviderfor wiring Logto into your app with less boilerplateuseAuthfor user state, auth actions, and route protection patternsUserCenterfor a production-ready account dropdownCallbackPagefor redirect and popup callback handlingSignInPagefor dedicated/signinroutesSignInButtonfor drop-in sign-in triggers- popup sign-in support
- guest mode support
- custom navigation support for SPA routers
- JWT verification against Logto JWKS
- Express middleware via
createExpressAuthMiddleware - Next.js request verification via
verifyNextAuth - generic
verifyAuthhelper for custom servers and handlers - optional scope checks
- cookie and bearer-token extraction
- guest-aware auth context support
- Vite config helpers
- Webpack config helpers
- Next.js config helpers
- a dedicated
bundler-configentrypoint for build-time imports
- Faster first integration: frontend and backend auth can be wired from one package.
- Better defaults: common auth screens and account UI are already handled.
- Less glue code: cookie syncing, callback handling, popup flows, and request verification are built in.
- Easier adoption: you still keep Logto underneath, so you are not boxed into a custom auth system.
npm install @ouim/simple-logto @logto/reactPeer dependencies:
reactreact-dom@logto/react
import { AuthProvider } from '@ouim/simple-logto'
const logtoConfig = {
endpoint: 'https://your-tenant.logto.app',
appId: 'your-app-id',
resources: ['https://your-api.example.com'],
}
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<AuthProvider config={logtoConfig} callbackUrl="http://localhost:3000/callback">
{children}
</AuthProvider>
)
}import { CallbackPage } from '@ouim/simple-logto'
export default function CallbackRoute() {
return <CallbackPage />
}import { SignInPage } from '@ouim/simple-logto'
export default function SignInRoute() {
return <SignInPage />
}import { useAuth } from '@ouim/simple-logto'
export function Dashboard() {
const { user, isLoadingUser, signIn, signOut } = useAuth()
if (isLoadingUser) return <div>Loading...</div>
if (!user) return <button onClick={() => signIn()}>Sign in</button>
return (
<div>
<p>Welcome, {user.name ?? user.id}</p>
<button onClick={() => signOut()}>Sign out</button>
</div>
)
}import { UserCenter } from '@ouim/simple-logto'
export function Navbar() {
return (
<nav className="flex items-center justify-between h-16 px-4 border-b">
<div className="font-bold">MyApp</div>
<UserCenter />
</nav>
)
}Main provider for the package. It wraps Logto, manages auth refresh, and keeps the browser cookie in sync for backend verification.
Props:
config: Logto config objectcallbackUrl?: default auth callback URLcustomNavigate?: custom navigation function for React Router, Next.js, or other SPA routersenablePopupSignIn?: enables popup-based sign-in flow
Example with custom router navigation:
<AuthProvider config={logtoConfig} callbackUrl="/callback" customNavigate={url => router.push(url)} enablePopupSignIn>
<App />
</AuthProvider>Returns:
userisLoadingUsersignInsignOutrefreshAuthenablePopupSignIn
You can also use it for lightweight route protection:
const { user } = useAuth({
middleware: 'auth',
redirectTo: '/signin',
})Guest-only route example:
const auth = useAuth({
middleware: 'guest',
redirectIfAuthenticated: '/dashboard',
})Prebuilt account dropdown for navbars and app shells.
Supports:
- signed-in and signed-out states
- local or global sign-out
- custom account links
- custom theme class names
<UserCenter
signoutCallbackUrl="/"
globalSignOut={false}
additionalPages={[
{ link: '/settings', text: 'Settings' },
{ link: '/billing', text: 'Billing' },
]}
/>Drop this onto your callback route to complete the Logto auth flow.
Optional props:
onSuccessonErrorloadingComponentsuccessComponentclassName
Use this when you want a dedicated /signin route that automatically initiates the auth flow. It also supports popup-based sign-in windows.
For cases where you want a reusable trigger instead of manually calling signIn().
import { SignInButton } from '@ouim/simple-logto'
;<SignInButton />Import backend helpers from the dedicated subpath:
import { createExpressAuthMiddleware, verifyAuth, verifyNextAuth } from '@ouim/simple-logto/backend'createExpressAuthMiddleware automatically parses cookies for you, so you do not need to add cookie-parser yourself.
import express from 'express'
import { createExpressAuthMiddleware } from '@ouim/simple-logto/backend'
const app = express()
const authMiddleware = createExpressAuthMiddleware({
logtoUrl: 'https://your-tenant.logto.app',
audience: 'https://your-api.example.com',
cookieName: 'logto_authtoken',
requiredScope: 'read:profile',
allowGuest: true,
})
app.get('/api/me', authMiddleware, (req, res) => {
res.json({
userId: req.auth?.userId,
isAuthenticated: req.auth?.isAuthenticated,
isGuest: req.auth?.isGuest,
})
})import { verifyNextAuth } from '@ouim/simple-logto/backend'
export async function GET(request: Request) {
const result = await verifyNextAuth(request, {
logtoUrl: process.env.LOGTO_URL!,
audience: process.env.LOGTO_AUDIENCE!,
allowGuest: false,
})
if (!result.success) {
return Response.json({ error: result.error }, { status: 401 })
}
return Response.json({
userId: result.auth.userId,
payload: result.auth.payload,
})
}import { verifyAuth } from '@ouim/simple-logto/backend'
const auth = await verifyAuth('your-jwt-token', {
logtoUrl: 'https://your-tenant.logto.app',
audience: 'https://your-api.example.com',
})logtoUrl: requiredaudience: requiredcookieName?: defaults tologto_authtokenrequiredScope?: rejects requests missing the given scopeallowGuest?: enables guest auth fallback
interface AuthContext {
userId: string | null
isAuthenticated: boolean
payload: AuthPayload | null
isGuest?: boolean
guestId?: string
}This package includes bundler helpers for the jose resolution issues that often show up during Logto integration.
For build-time scripts, prefer the dedicated subpath:
import { viteConfig, getBundlerConfig } from '@ouim/simple-logto/bundler-config'import { defineConfig } from 'vite'
import { viteConfig } from '@ouim/simple-logto/bundler-config'
export default defineConfig({
...viteConfig,
})import { webpackConfig } from '@ouim/simple-logto/bundler-config'
export default {
...webpackConfig,
}import { nextjsConfig } from '@ouim/simple-logto/bundler-config'
const nextConfig = {
...nextjsConfig,
}
export default nextConfigThe package ships typed frontend and backend exports.
import type { LogtoUser, AuthOptions, CallbackPageProps, AdditionalPage, SignInButtonProps } from '@ouim/simple-logto'
import type { AuthContext, AuthPayload, VerifyAuthOptions } from '@ouim/simple-logto/backend'@ouim/simple-logto is best thought of as the practical app-layer around Logto:
- Logto remains the identity platform
@logto/reactremains the core SDK- this package adds the missing productized layer most app teams want on day one
If your team eventually needs lower-level control, you can still drop down to the official Logto APIs without throwing your whole auth model away.
- frontend and backend helpers are published from the same package
- backend helpers are exposed from
@ouim/simple-logto/backend - bundler helpers are exposed from
@ouim/simple-logto/bundler-config
MIT

