Overview
The useAuth hook provides access to the current user’s authentication state and authentication methods. It also supports middleware for route protection and automatic redirects.
Installation
npm install @ouim/logto-authkit
Basic Usage
import { useAuth } from '@ouim/logto-authkit'
function MyComponent () {
const { user , isLoadingUser , signIn , signOut } = useAuth ()
if ( isLoadingUser ) {
return < div > Loading... </ div >
}
if ( user ) {
return (
< div >
< p > Welcome, { user . name } ! </ p >
< button onClick = { () => signOut () } > Sign Out </ button >
</ div >
)
}
return < button onClick = { () => signIn () } > Sign In </ button >
}
Parameters
The hook accepts an optional options object:
Configuration object for authentication behavior and route protection. Show AuthOptions properties
middleware
'auth' | 'guest' | undefined
Route protection middleware type:
'auth': Requires authentication (redirects unauthenticated users)
'guest': Guest-only route (redirects authenticated users)
undefined: No protection
const { user } = useAuth ({ middleware: 'auth' })
URL to redirect to when middleware: 'auth' and user is not authenticated. const { user } = useAuth ({
middleware: 'auth' ,
redirectTo: '/login'
})
URL to redirect to when middleware: 'guest' and user is authenticated. const { user } = useAuth ({
middleware: 'guest' ,
redirectIfAuthenticated: '/dashboard'
})
Options for navigation behavior. Show NavigationOptions properties
Use replaceState instead of pushState
Force navigation even if already on the same page
const { user } = useAuth ({
middleware: 'auth' ,
redirectTo: '/login' ,
navigationOptions: { replace: true }
})
Return Value
The hook returns an AuthContextType object:
interface AuthContextType {
user : LogtoUser | null
isLoadingUser : boolean
signIn : ( callbackUrl ?: string , usePopup ?: boolean ) => Promise < void >
signOut : ( options ?: { callbackUrl ?: string ; global ?: boolean }) => Promise < void >
refreshAuth : () => Promise < void >
enablePopupSignIn ?: boolean
}
Current authenticated user object, or null if not authenticated. type LogtoUser = {
id : string
name ?: string
email ?: string
avatar ?: string
[ key : string ] : any
}
Loading state indicator. true while fetching user data, false when complete.
signIn
(callbackUrl?: string, usePopup?: boolean) => Promise<void>
Function to initiate sign-in flow. - callbackUrl: Optional URL to redirect to after authentication - usePopup: Override the
enablePopupSignIn setting from AuthProvider tsx // Default sign-in await signIn() // With custom callback URL await signIn('/dashboard') // Force popup mode await signIn('/callback', true) // Force redirect mode await signIn('/callback', false)
signOut
(options?: { callbackUrl?: string; global?: boolean }) => Promise<void>
Function to sign out the current user.
callbackUrl: Optional URL to redirect to after sign-out
global: Whether to perform global sign-out (default: true)
// Default global sign-out
await signOut ()
// With custom redirect
await signOut ({ callbackUrl: '/goodbye' })
// Local sign-out only
await signOut ({ global: false })
// Local sign-out with redirect
await signOut ({ callbackUrl: '/login' , global: false })
Function to manually refresh the authentication state. tsx // Refresh user data await refreshAuth()
Whether popup sign-in is enabled (from AuthProvider configuration).
Examples
import { useAuth } from '@ouim/logto-authkit'
function UserProfile () {
const { user , isLoadingUser } = useAuth ()
if ( isLoadingUser ) {
return < div > Loading user... </ div >
}
if ( ! user ) {
return < div > Please sign in </ div >
}
return (
< div >
< img src = { user . avatar } alt = { user . name } />
< h2 > { user . name } </ h2 >
< p > { user . email } </ p >
< p > User ID: { user . id } </ p >
</ div >
)
}
Protected Page
import { useAuth } from '@ouim/logto-authkit'
export default function DashboardPage () {
const { user } = useAuth ({
middleware: 'auth' ,
redirectTo: '/login' ,
})
// No need to check if user exists - middleware handles it
return (
< div >
< h1 > Dashboard </ h1 >
< p > Welcome, { user ?. name } ! </ p >
</ div >
)
}
Guest-Only Page
import { useAuth } from '@ouim/logto-authkit'
export default function LoginPage () {
const { signIn } = useAuth ({
middleware: 'guest' ,
redirectIfAuthenticated: '/dashboard' ,
})
return (
< div >
< h1 > Sign In </ h1 >
< button onClick = { () => signIn () } > Sign in with Logto </ button >
</ div >
)
}
import { useAuth } from '@ouim/logto-authkit'
function SignInButton () {
const { signIn , isLoadingUser } = useAuth ()
return (
< button
onClick = { () => signIn ( '/dashboard' , true ) } // Use popup
disabled = { isLoadingUser }
>
{ isLoadingUser ? 'Loading...' : 'Sign In' }
</ button >
)
}
Sign-Out with Confirmation
import { useAuth } from '@ouim/logto-authkit'
function SignOutButton () {
const { signOut } = useAuth ()
const handleSignOut = async () => {
if ( confirm ( 'Are you sure you want to sign out?' )) {
await signOut ({ callbackUrl: '/' })
}
}
return < button onClick = { handleSignOut } > Sign Out </ button >
}
Conditional Rendering
import { useAuth } from '@ouim/logto-authkit'
function Navigation () {
const { user , signIn , signOut } = useAuth ()
return (
< nav >
< a href = "/" > Home </ a >
{ user ? (
<>
< a href = "/dashboard" > Dashboard </ a >
< a href = "/profile" > Profile </ a >
< button onClick = { () => signOut () } > Sign Out </ button >
</>
) : (
< button onClick = { () => signIn () } > Sign In </ button >
) }
</ nav >
)
}
Manual Auth Refresh
import { useAuth } from '@ouim/logto-authkit'
function ProfilePage () {
const { user , refreshAuth } = useAuth ({ middleware: 'auth' })
const handleProfileUpdate = async () => {
// Update profile via API
await updateProfile ({ name: 'New Name' })
// Refresh auth state to get updated user data
await refreshAuth ()
}
return (
< div >
< h1 > { user ?. name } </ h1 >
< button onClick = { handleProfileUpdate } > Update Profile </ button >
</ div >
)
}
With Loading State
import { useAuth } from '@ouim/logto-authkit'
function App () {
const { user , isLoadingUser , signIn , signOut } = useAuth ()
return (
< div >
{ isLoadingUser ? (
< div className = "flex items-center justify-center min-h-screen" >
< div className = "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500" />
</ div >
) : user ? (
< Dashboard user = { user } onSignOut = { signOut } />
) : (
< LandingPage onSignIn = { signIn } />
) }
</ div >
)
}
Middleware Behavior
middleware: 'auth'
Protects routes that require authentication:
const { user } = useAuth ({
middleware: 'auth' ,
redirectTo: '/login' ,
})
// If user is NOT authenticated → redirects to '/login'
// If user IS authenticated → renders normally
middleware: 'guest'
Protects routes that should only be accessible to unauthenticated users:
const { user } = useAuth ({
middleware: 'guest' ,
redirectIfAuthenticated: '/dashboard' ,
})
// If user IS authenticated → redirects to '/dashboard'
// If user is NOT authenticated → renders normally
No Middleware
const { user } = useAuth ()
// No automatic redirects
// Manually check user state and handle accordingly
SSR Considerations
The hook waits for client-side mounting and isLoadingUser to be false before performing middleware redirects, preventing hydration
mismatches.
useEffect (() => {
if ( isLoadingUser ) return // Wait for loading to complete
// Perform middleware checks and redirects
}, [ user , isLoadingUser , memoizedOptions ])
Best Practices
Use middleware for route protection
Instead of manually checking user and redirecting, use the built-in middleware option for cleaner code.
Always check loading state
Always handle the isLoadingUser state to prevent UI flashing and provide better UX.
The hook internally memoizes options, but you can also wrap your options in useMemo if they depend on other state.
Wrap signOut calls in try-catch blocks to handle potential errors gracefully.
TypeScript Support
The hook is fully typed:
import { useAuth , type AuthOptions , type AuthContextType } from '@ouim/logto-authkit'
const options : AuthOptions = {
middleware: 'auth' ,
redirectTo: '/login' ,
}
const auth : AuthContextType = useAuth ( options )
Troubleshooting
”useAuthContext must be used within an AuthProvider” : Ensure your component is wrapped with AuthProvider.
Infinite redirect loop : Check that redirectTo and redirectIfAuthenticated point to different routes and don’t conflict.
The hook automatically refreshes auth state when: - Window regains focus - Storage events occur (cross-tab sync) - Custom
auth-state-changed events are dispatched
AuthProvider Configure authentication provider
Route Protection Advanced route protection patterns
UserCenter Pre-built user menu component
CallbackPage Handle authentication callbacks