@ouim/simple-logto v0.1.2
@ouim/simple-logto
A simpler way to use @logto/react with prebuilt UI components and hooks for fast authentication setup in React apps.
Features
Frontend Components & Hooks
- AuthProvider: Easy context provider for Logto authentication
- UserCenter: Prebuilt user dropdown/avatar for your navbar
- CallbackPage: Handles OAuth callback and popup flows
- SignInPage: Standalone sign-in page component
- useAuth: React hook for accessing user and auth actions
- Custom navigation: Integrates with React Router, Next.js, etc.
- Popup sign-in: Support for popup-based authentication
- Guest mode: Built-in guest user support with fingerprinting
Backend Authentication
- JWT Verification: Manual JWT verification with JWKS caching
- Express.js Middleware: Ready-to-use Express middleware
- Next.js Support: API routes and middleware helpers
- Scope-based Authorization: Built-in scope validation
- Multiple Token Sources: Supports cookies and Authorization headers
- TypeScript Support: Full TypeScript definitions
Bundler Configuration
- Vite: Pre-configured Vite settings
- Webpack: Webpack configuration helpers
- Next.js: Next.js bundler configuration
Installation
npm install @ouim/simple-logtoQuick Start
Frontend Setup
Frontend Setup
1. AuthProvider
Wrap your app with AuthProvider and pass your Logto config:
import { AuthProvider } from '@ouim/simple-logto'
const config = {
endpoint: 'https://your-logto-endpoint.com',
appId: 'your-app-id',
}
function App() {
return (
<AuthProvider
config={config}
callbackUrl="http://localhost:3000/callback"
enablePopupSignIn={true} // Enable popup-based sign-in
// Optionally: customNavigate for SPA routing
// customNavigate={(url, options) => { ... }}
>
<YourApp />
</AuthProvider>
)
}2. UserCenter Component
Drop the UserCenter component into your navbar for a ready-to-use user menu:
import { UserCenter } from '@ouim/simple-logto'
function Navbar() {
return (
<nav className="flex items-center justify-between h-16 px-4 border-b">
<div className="font-bold">MyApp</div>
<UserCenter />
</nav>
)
}- Shows avatar, name, and sign out when authenticated.
- Shows sign in button when not authenticated.
- Accepts optional props:
classNamesignoutCallbackUrl(defaults to/)globalSignOut(defaults totrue)additionalPages- array of{ link: string; text: string; icon?: ReactNode }
Example adding custom pages:
<UserCenter additionalPages={[{ link: '/settings', text: 'Go to your settings' }]} />3. CallbackPage
Create a route (e.g. /callback) and render CallbackPage to handle OAuth redirects:
import { CallbackPage } from '@ouim/simple-logto'
export default function Callback() {
return <CallbackPage />
}- Handles both normal and popup sign-in flows.
- Optional props:
onSuccess,onError,loadingComponent,successComponent
4. SignInPage (Optional)
For a standalone sign-in page:
import { SignInPage } from '@ouim/simple-logto'
export default function SignIn() {
return <SignInPage />
}5. useAuth Hook
Access the current user and authentication actions anywhere in your app:
import { useAuth } from '@ouim/simple-logto'
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}!</p>
<button onClick={() => signOut()}>Sign out</button>
</div>
)
}5. useAuth Hook
Access the current user and authentication actions anywhere in your app:
import { useAuth } from '@ouim/simple-logto'
function Dashboard() {
const { user, isLoadingUser, signIn, signOut, refreshAuth } = useAuth()
if (isLoadingUser) return <div>Loading...</div>
if (!user) return <button onClick={() => signIn()}>Sign in</button>
return (
<div>
<p>Welcome, {user.name}!</p>
<button onClick={() => signOut()}>Sign out</button>
<button onClick={refreshAuth}>Refresh Auth</button>
</div>
)
}Route Protection Example
function ProtectedPage() {
const { user } = useAuth({
middleware: 'auth',
redirectTo: '/login', // Redirect if not authenticated
})
if (!user) return null // or loading indicator
return <div>Protected content</div>
}Guest Mode Example
function MixedContent() {
const { user } = useAuth({
middleware: 'guest', // Allow guest users
})
return <div>{user ? <p>Welcome back, {user.name}!</p> : <p>You're browsing as a guest</p>}</div>
}Backend Authentication
The library includes powerful backend authentication helpers for Node.js applications.
Installation
Backend features are included with the main package:
npm install @ouim/simple-logtoExpress.js Middleware
import { createExpressAuthMiddleware } from '@ouim/simple-logto/backend'
const authMiddleware = createExpressAuthMiddleware({
logtoUrl: 'https://your-logto-domain.com',
audience: 'your-api-resource-identifier',
cookieName: 'logto_authtoken', // optional, defaults to 'logto_authtoken'
requiredScope: 'some_scope', // optional
allowGuest: true, // optional, enables guest mode
})
// Use in your Express routes
app.get('/protected', authMiddleware, (req, res) => {
res.json({
message: 'Hello authenticated user!',
userId: req.auth.userId,
isAuthenticated: req.auth.isAuthenticated,
isGuest: req.auth.isGuest,
})
})Next.js API Routes
// app/api/protected/route.js
import { verifyNextAuth } from '@ouim/simple-logto/backend'
export async function GET(request) {
const authResult = await verifyNextAuth(request, {
logtoUrl: 'https://your-logto-domain.com',
audience: 'your-api-resource-identifier',
cookieName: 'logto_authtoken', // optional
requiredScope: 'some_scope', // optional
allowGuest: true, // optional
})
if (!authResult.success) {
return Response.json({ error: authResult.error }, { status: 401 })
}
return Response.json({
message: 'Hello authenticated user!',
userId: authResult.auth.userId,
payload: authResult.auth.payload,
})
}Next.js Middleware
// middleware.js
import { verifyNextAuth } from '@ouim/simple-logto/backend'
import { NextResponse } from 'next/server'
export async function middleware(request) {
if (request.nextUrl.pathname.startsWith('/api/protected')) {
const authResult = await verifyNextAuth(request, {
logtoUrl: process.env.LOGTO_URL,
audience: process.env.LOGTO_AUDIENCE,
})
if (!authResult.success) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Add auth info to headers for the API route
const response = NextResponse.next()
response.headers.set('x-user-id', authResult.auth.userId)
return response
}
}
export const config = {
matcher: '/api/protected/:path*',
}Generic Usage
import { verifyAuth } from '@ouim/simple-logto/backend'
// Verify with token string
try {
const auth = await verifyAuth('your-jwt-token', {
logtoUrl: 'https://your-logto-domain.com',
audience: 'your-api-resource-identifier',
})
console.log('User ID:', auth.userId)
} catch (error) {
console.error('Auth failed:', error.message)
}
// Verify with request object
try {
const auth = await verifyAuth(requestObject, {
logtoUrl: 'https://your-logto-domain.com',
audience: 'your-api-resource-identifier',
})
} catch (error) {
console.error('Auth failed:', error.message)
}Backend Configuration Options
logtoUrl: Your Logto server URL (required)audience: Your API resource identifier (required)cookieName: Custom cookie name (optional, defaults to 'logto_authtoken')requiredScope: Required scope for access (optional)allowGuest: Enable guest mode with fingerprinting (optional)
Auth Context
When authentication is successful, you'll get an AuthContext object:
interface AuthContext {
userId: string | null // User ID from token (null for guests)
isAuthenticated: boolean // true for authenticated users
isGuest: boolean // true for guest users
payload: AuthPayload | null // Full JWT payload (null for guests)
guestId?: string // Guest fingerprint ID (when allowGuest is true)
}Bundler Configuration
The library provides pre-configured bundler settings to resolve common issues with the jose library and other dependencies.
Vite
// vite.config.js
import { viteConfig } from '@ouim/simple-logto'
export default {
...viteConfig,
// your other config
}Webpack
// webpack.config.js
import { webpackConfig } from '@ouim/simple-logto'
module.exports = {
...webpackConfig,
// your other config
}Next.js
// next.config.js
import { nextjsConfig } from '@ouim/simple-logto'
module.exports = {
...nextjsConfig,
// your other config
}Custom Configuration
import { getBundlerConfig } from '@ouim/simple-logto'
// Get configuration for specific bundler
const config = getBundlerConfig('vite') // 'vite' | 'webpack' | 'nextjs'Utilities
The library also exports several utility functions:
import { cookieUtils, jwtCookieUtils } from '@ouim/simple-logto'
// Cookie utilities
cookieUtils.set('key', 'value')
cookieUtils.get('key')
cookieUtils.remove('key')
// JWT-specific cookie utilities
jwtCookieUtils.setToken('jwt-token')
jwtCookieUtils.getToken()
jwtCookieUtils.removeToken()TypeScript Support
The library is written in TypeScript and provides comprehensive type definitions:
import type { LogtoUser, AuthOptions, AuthMiddleware, CallbackPageProps, NavigationOptions, AdditionalPage } from '@ouim/simple-logto'
// Backend types
import type { AuthContext, AuthPayload, VerifyAuthOptions } from '@ouim/simple-logto/backend'