🔧 Common Issues & Solutions
This guide covers the most common issues developers encounter when integrating PasskeyMe and provides step-by-step solutions.
Authentication Issues
Passkeys Not Working
Problem: Passkeys fail to register or authenticate
Common Causes:
- HTTP instead of HTTPS in production
- Incompatible device or browser
- User gesture not detected
- Domain mismatch
Solutions:
-
Verify HTTPS in Production
// Check protocol
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
console.error('Passkeys require HTTPS in production');
} -
Check Device Compatibility
// Check for WebAuthn support
if (!window.PublicKeyCredential) {
console.error('WebAuthn not supported');
}
// Check for platform authenticator
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
.then(available => {
console.log('Platform authenticator available:', available);
}); -
Verify Domain Configuration
// Ensure domain matches PasskeyMe configuration
console.log('Current domain:', window.location.hostname); -
Enable Debug Logging
const auth = new PasskeymeAuth({
appId: 'your-app-id',
debug: true // Shows detailed passkey logs
});
OAuth Authentication Failures
Problem: OAuth login redirects fail or return errors
Common Causes:
- Incorrect redirect URI configuration
- OAuth app credentials missing/invalid
- CORS issues
- State parameter mismatch
Solutions:
-
Verify Redirect URI Configuration
// Check configured vs actual redirect URI
console.log('Configured:', auth.config.redirectUri);
console.log('Current URL:', window.location.href);
// Common redirect URI patterns
const validRedirectUris = [
'http://localhost:3000/auth/callback', // Development
'https://yourapp.com/auth/callback', // Production
'https://staging.yourapp.com/auth/callback' // Staging
]; -
Check OAuth Provider Setup
- Verify client ID and secret in PasskeyMe dashboard
- Ensure OAuth app is approved/published
- Check authorized domains in OAuth provider settings
-
Debug OAuth Errors
// Check URL parameters for OAuth errors
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('error')) {
console.error('OAuth error:', {
error: urlParams.get('error'),
description: urlParams.get('error_description'),
state: urlParams.get('state')
});
}
Token Issues
Problem: Access tokens expired or invalid
Common Causes:
- Token expired naturally
- Clock drift between client/server
- Token storage issues
- Invalid token format
Solutions:
-
Check Token Expiration
try {
const token = await auth.getAccessToken();
console.log('Token obtained successfully');
} catch (error) {
if (error.code === 'TOKEN_EXPIRED') {
console.log('Token expired, redirecting to login');
auth.redirectToLogin();
}
} -
Verify Token Storage
// Check if tokens are being stored
const storedToken = localStorage.getItem('passkeyme_access_token');
console.log('Stored token:', storedToken ? 'Present' : 'Missing');
// Try different storage mechanisms
const auth = new PasskeymeAuth({
appId: 'your-app-id',
storage: 'sessionStorage' // or 'memory'
}); -
Manual Token Refresh
try {
const newToken = await auth.refreshAccessToken();
console.log('Token refreshed successfully');
} catch (error) {
console.error('Refresh failed:', error);
auth.redirectToLogin();
}
SDK Integration Issues
React Hook Errors
Problem: React hooks not working properly
Common Causes:
- Missing PasskeymeProvider
- Multiple React versions
- Hook called outside component
- Stale closures
Solutions:
-
Verify Provider Setup
// Ensure PasskeymeProvider wraps your app
function App() {
return (
<PasskeymeProvider config={{ appId: 'your-app-id' }}>
<YourApp />
</PasskeymeProvider>
);
} -
Check Hook Usage
// ✅ Correct usage
function MyComponent() {
const { user, isAuthenticated } = usePasskeyme();
return <div>{user?.email}</div>;
}
// ❌ Incorrect usage (outside component)
const { user } = usePasskeyme(); // This will fail
function MyComponent() {
return <div>{user?.email}</div>;
} -
Debug React Version Conflicts
npm ls react
# Ensure only one version of React
Next.js Issues
Problem: Next.js specific integration problems
Common Causes:
- SSR/SSG hydration mismatches
- Environment variables not loaded
- Window object accessed during SSR
Solutions:
-
Fix SSR Hydration Issues
// Use dynamic imports for client-only components
import dynamic from 'next/dynamic';
const AuthComponent = dynamic(
() => import('./AuthComponent'),
{ ssr: false }
); -
Proper Environment Variable Setup
// next.config.js
module.exports = {
env: {
NEXT_PUBLIC_PASSKEYME_APP_ID: process.env.NEXT_PUBLIC_PASSKEYME_APP_ID,
}
}; -
Client-Side Only Initialization
import { useEffect, useState } from 'react';
function AuthProvider({ children }) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) return <div>Loading...</div>;
return (
<PasskeymeProvider config={{ appId: process.env.NEXT_PUBLIC_PASSKEYME_APP_ID }}>
{children}
</PasskeymeProvider>
);
}
TypeScript Errors
Problem: TypeScript compilation errors
Common Causes:
- Missing type definitions
- Incorrect type usage
- Version mismatches
Solutions:
-
Install Type Definitions
npm install @types/node @types/react
-
Fix Common Type Issues
// ✅ Correct typing
const { user } = usePasskeyme();
const email: string | undefined = user?.email;
// ❌ Incorrect assumption
const email: string = user.email; // user might be null -
Use Type Guards
function isAuthenticated(user: User | null): user is User {
return user !== null;
}
if (isAuthenticated(user)) {
// TypeScript knows user is not null here
console.log(user.email);
}
Network & CORS Issues
CORS Errors
Problem: Cross-origin request blocked
Common Causes:
- Domain not configured in PasskeyMe dashboard
- Development vs production URL mismatch
- Subdomain issues
Solutions:
-
Configure Allowed Origins
- Add your domain to PasskeyMe dashboard
- Include both www and non-www versions
- Add development URLs (localhost:3000, etc.)
-
Check Current Origin
console.log('Current origin:', window.location.origin);
// Add this origin to PasskeyMe dashboard -
Development CORS Setup
// For development
const auth = new PasskeymeAuth({
appId: 'your-app-id',
baseUrl: 'http://localhost:3001', // Local development server
});
Network Timeouts
Problem: Requests timing out
Common Causes:
- Slow network connection
- Server overload
- Firewall blocking requests
Solutions:
-
Increase Timeout
const auth = new PasskeymeAuth({
appId: 'your-app-id',
timeout: 30000 // 30 seconds instead of default 10
}); -
Retry Logic
async function authenticateWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await auth.handleAuthCallback();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
Callback & Redirect Issues
Callback Not Working
Problem: Authentication callback fails
Common Causes:
- Callback URL misconfiguration
- Missing state parameter
- Page not handling callback properly
Solutions:
-
Debug Callback Parameters
// Check callback URL parameters
const urlParams = new URLSearchParams(window.location.search);
console.log('Callback parameters:', {
code: urlParams.get('code'),
state: urlParams.get('state'),
error: urlParams.get('error')
}); -
Proper Callback Page Setup
// Dedicated callback page
function CallbackPage() {
const { handleAuthCallback } = usePasskeyme();
const navigate = useNavigate();
useEffect(() => {
const processCallback = async () => {
try {
await handleAuthCallback();
navigate('/dashboard');
} catch (error) {
console.error('Callback failed:', error);
navigate('/login?error=callback_failed');
}
};
processCallback();
}, []);
return <div>Processing authentication...</div>;
} -
State Parameter Handling
// Include return URL in state
auth.redirectToLogin({
state: JSON.stringify({ returnTo: window.location.pathname })
});
// Handle state in callback
const result = await auth.handleAuthCallback();
if (result.state) {
const { returnTo } = JSON.parse(result.state);
navigate(returnTo || '/dashboard');
}
Infinite Redirect Loops
Problem: App gets stuck in redirect loop
Common Causes:
- Protected route redirecting authenticated users
- Callback page not handling success properly
- State management issues
Solutions:
-
Fix Route Protection Logic
function ProtectedRoute({ children }) {
const { isAuthenticated, loading } = usePasskeyme();
const location = useLocation();
if (loading) return <div>Loading...</div>;
if (!isAuthenticated) {
// Only redirect if not already on auth pages
if (!location.pathname.startsWith('/auth/')) {
return <Navigate to="/login" replace />;
}
}
return children;
} -
Prevent Double Authentication
function LoginPage() {
const { isAuthenticated } = usePasskeyme();
const navigate = useNavigate();
useEffect(() => {
if (isAuthenticated) {
navigate('/dashboard', { replace: true });
}
}, [isAuthenticated, navigate]);
return <LoginForm />;
}
Performance Issues
Slow Authentication
Problem: Authentication process is slow
Common Causes:
- Large bundle size
- Inefficient re-renders
- Network latency
Solutions:
-
Optimize Bundle Size
// Use dynamic imports for auth pages
const LoginPage = lazy(() => import('./pages/LoginPage'));
const CallbackPage = lazy(() => import('./pages/CallbackPage')); -
Memoize Components
const AuthButton = memo(function AuthButton() {
const { redirectToLogin, loading } = usePasskeyme();
return (
<button onClick={redirectToLogin} disabled={loading}>
Sign In
</button>
);
}); -
Reduce Re-renders
function App() {
const auth = usePasskeyme();
// Memoize to prevent unnecessary re-renders
const authContextValue = useMemo(() => auth, [
auth.user,
auth.isAuthenticated,
auth.loading
]);
return <AuthContext.Provider value={authContextValue} />;
}
Browser Compatibility
Safari Issues
Problem: Authentication not working in Safari
Common Causes:
- Strict cookie policies
- Webkit-specific bugs
- Third-party cookie blocking
Solutions:
-
Configure Cookie Settings
// Use sessionStorage for Safari compatibility
const auth = new PasskeymeAuth({
appId: 'your-app-id',
storage: 'sessionStorage'
}); -
Check Safari Version
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
if (isSafari) {
console.log('Safari detected, using compatible settings');
}
Mobile Browser Issues
Problem: Issues on mobile browsers
Common Causes:
- Viewport scaling
- Touch event handling
- iOS Safari specific issues
Solutions:
-
Mobile-Optimized Configuration
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-
Touch-Friendly UI
.auth-button {
min-height: 44px; /* iOS minimum touch target */
touch-action: manipulation;
}
Debugging Tools
Enable Debug Mode
const auth = new PasskeymeAuth({
appId: 'your-app-id',
debug: true // Enables detailed logging
});
// Manual debug toggle
auth.setDebugMode(true);
Browser Developer Tools
-
Network Tab
- Check for failed requests
- Verify correct headers
- Look for CORS errors
-
Console Tab
- Enable debug mode for detailed logs
- Check for JavaScript errors
- Monitor authentication events
-
Application Tab
- Check localStorage/sessionStorage
- Verify token storage
- Clear storage if needed
Testing Checklist
// Complete debugging checklist
function debugPasskeyMe() {
console.log('=== PasskeyMe Debug Info ===');
console.log('Current URL:', window.location.href);
console.log('Protocol:', window.location.protocol);
console.log('SDK Version:', PasskeymeAuth.version);
console.log('WebAuthn Support:', !!window.PublicKeyCredential);
console.log('Auth State:', auth.state);
console.log('Stored Tokens:', {
access: !!localStorage.getItem('passkeyme_access_token'),
refresh: !!localStorage.getItem('passkeyme_refresh_token')
});
console.log('========================');
}
Getting Help
Support Channels
- Documentation - Check relevant guides first
- Community Discord - Ask questions and get help
- GitHub Issues - Report bugs and feature requests
- Email Support - Direct support for enterprise customers
Bug Reports
When reporting issues, include:
// Debugging information to include
const debugInfo = {
sdk: '@passkeyme/auth',
version: PasskeymeAuth.version,
browser: navigator.userAgent,
url: window.location.href,
error: error.message,
steps: 'Steps to reproduce...'
};
Feature Requests
Use our GitHub repository to request new features or improvements.
Next Steps
- SDK Documentation - Detailed SDK guides
- API Reference - Direct API usage
- Configuration - Advanced configuration
- Community Support - Get help from the community