React SDK Guide
Step-by-step guide for developers using the React SDK with the useAuth hook.
Installation
npm install get401Step 1 - Wrap your app with Get401Provider
Import and wrap your application root component with Get401Provider.
import { Get401Provider } from 'get401'
function App() {
return (
<Get401Provider
appId="your-app-id"
debug={true}
onSuccess={(user) => console.log('User logged in:', user)}
onError={(error) => console.error('Auth error:', error)}
>
<YourApp />
</Get401Provider>
)
}Get401Provider props:
| Prop | Type | Description |
|---|---|---|
appId |
string |
Your application ID (or set via window.GET401_APP_ID) |
debug |
boolean |
Enable debug logging (default: false) |
onSuccess |
(user: User) => void |
Callback on successful authentication |
onError |
(error: string) => void |
Callback on error |
Step 2 - Use the useAuth hook
import { useState } from 'react'
import { useAuth } from 'get401'
function LoginPage() {
const { login, challengeOTP, user, status, nextStep, error, isLoading } = useAuth()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [otpCode, setOtpCode] = useState('')
// ... rest of component
}Step 3 - Handle login
Both email and password are sent together in a single request. If MFA is enabled, the response returns next: 'otp'.
const handleLogin = async (e) => {
e.preventDefault()
try {
const response = await login(email, password)
if (response.next === 'otp') {
// Show OTP input form
}
} catch (err) {
console.error('Login failed:', err)
}
}Step 4 - Handle OTP verification
const handleOTP = async (e) => {
e.preventDefault()
try {
await challengeOTP(otpCode)
} catch (err) {
console.error('OTP verification failed:', err)
}
}Step 5 - Check authentication status
if (status === 'authenticated') {
return <div>Welcome {user?.email}!</div>
}Step 6 - Show OTP form when required
if (nextStep === 'otp') {
return (
<form onSubmit={handleOTP}>
<input
type="text"
value={otpCode}
onChange={(e) => setOtpCode(e.target.value)}
placeholder="Enter OTP code"
/>
<button type="submit" disabled={isLoading}>
Verify OTP
</button>
{error && <div>{error}</div>}
</form>
)
}Step 7 - Login form
return (
<form onSubmit={handleLogin}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
/>
<button type="submit" disabled={isLoading}>
Login
</button>
{error && <div>{error}</div>}
</form>
)Authentication Flow
Login
- User submits email + password via
login(email, password)- sent in one request - Server responds with
{ next: 'otp' }if MFA is required, otherwise user is authenticated - If
nextStep === 'otp', callchallengeOTP(code) - On success,
userobject is available
Registration
- Call
register(email, password) - Response has
setup: 'email'orsetup: 'otp' - If
setup === 'email': callchallengeEmailSetup(code)with the verification code - If
setup === 'otp'(or after email verification): callgetOTPSetup()to get QR code, thenverifyOTPSetup(code)
API Reference
useAuth hook
const {
status, // 'idle' | 'loading' | 'authenticated' | 'unauthenticated'
user, // User | null
nextStep, // 'email' | 'otp' | null
error, // string | null
isLoading, // boolean
isAuthenticated, // boolean
login(email, password),
challengeOTP(code),
logout(),
getUser(),
register(email, password),
challengeEmailSetup(code),
getOTPSetup(),
verifyOTPSetup(code),
refreshToken(),
clearError(),
} = useAuth()Get401Provider
interface Get401ProviderProps {
appId?: string
onSuccess?: (user: User) => void
onError?: (error: string) => void
debug?: boolean
children: React.ReactNode
}TypeScript
The package is written in TypeScript and includes full type definitions. All exports are fully typed.