Fix auth error handling and revert debug UI
This commit is contained in:
parent
730ed1a76a
commit
80917efa8f
@ -18,28 +18,35 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });
|
||||
}
|
||||
|
||||
let user;
|
||||
|
||||
// Handle Signup
|
||||
if (type === 'signup') {
|
||||
try {
|
||||
await workos.userManagement.createUser({
|
||||
const newUser = await workos.userManagement.createUser({
|
||||
email,
|
||||
password,
|
||||
firstName,
|
||||
lastName,
|
||||
emailVerified: false, // WorkOS sends verification email automatically if configured
|
||||
emailVerified: false,
|
||||
});
|
||||
|
||||
// Return early for signup to allow verification
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
pendingVerification: true,
|
||||
userId: newUser.id,
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
// Handle user already exists
|
||||
if (error.code === 'user_already_exists') {
|
||||
return NextResponse.json({ error: 'A user with this email already exists.' }, { status: 409 });
|
||||
if (error.code === 'user_already_exists' ||
|
||||
(error.code === 'user_creation_error' && error.errors?.some((e: any) => e.code === 'email_not_available'))) {
|
||||
return NextResponse.json({ error: 'A user with this email already exists. Please sign in.' }, { status: 409 });
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Authenticate (for both login and after signup)
|
||||
// Authenticate (Login)
|
||||
try {
|
||||
const response = await workos.userManagement.authenticateWithPassword({
|
||||
email,
|
||||
@ -47,10 +54,7 @@ export async function POST(request: NextRequest) {
|
||||
clientId,
|
||||
});
|
||||
|
||||
user = response.user;
|
||||
|
||||
// extensive logging to debug structure if needed
|
||||
// console.log('Auth response:', JSON.stringify(response, null, 2));
|
||||
const user = response.user;
|
||||
|
||||
// Create session
|
||||
await setSession({
|
||||
|
||||
69
src/app/api/auth/verify/route.ts
Normal file
69
src/app/api/auth/verify/route.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { workos, clientId } from '@/lib/workos';
|
||||
import { setSession } from '@/lib/session';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json() as {
|
||||
userId?: string;
|
||||
code?: string;
|
||||
email?: string;
|
||||
password?: string;
|
||||
stayLoggedIn?: boolean;
|
||||
};
|
||||
const { userId, code, email, password, stayLoggedIn } = body;
|
||||
|
||||
if (!userId || !code || !email || !password) {
|
||||
return NextResponse.json({ error: 'Missing verification details' }, { status: 400 });
|
||||
}
|
||||
|
||||
// 1. Verify the email with the code
|
||||
try {
|
||||
await workos.userManagement.verifyEmail({
|
||||
code,
|
||||
userId,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Verification error:', error);
|
||||
return NextResponse.json({
|
||||
error: error.message || 'Invalid verification code'
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
// 2. If verification successful, authenticate the user to create a session
|
||||
try {
|
||||
const response = await workos.userManagement.authenticateWithPassword({
|
||||
email,
|
||||
password,
|
||||
clientId,
|
||||
});
|
||||
|
||||
const user = response.user;
|
||||
|
||||
await setSession({
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
profilePictureUrl: user.profilePictureUrl,
|
||||
},
|
||||
accessToken: response.accessToken,
|
||||
refreshToken: response.refreshToken,
|
||||
stayLoggedIn: !!stayLoggedIn,
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, user });
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('Post-verification auth error:', error);
|
||||
return NextResponse.json({
|
||||
error: 'Verification successful, but login failed. Please try logging in.'
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('Verify API error:', error);
|
||||
return NextResponse.json({ error: 'An internal error occurred.' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,10 @@ export function UnifiedLogin({ onSuccess }: UnifiedLoginProps) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [stayLoggedIn, setStayLoggedIn] = useState(false);
|
||||
|
||||
const [pendingVerification, setPendingVerification] = useState(false);
|
||||
const [verificationCode, setVerificationCode] = useState('');
|
||||
const [userId, setUserId] = useState<string | null>(null);
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
email: '',
|
||||
password: '',
|
||||
@ -33,6 +37,34 @@ export function UnifiedLogin({ onSuccess }: UnifiedLoginProps) {
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// If we are pending verification, submit the code
|
||||
if (pendingVerification) {
|
||||
const res = await fetch('/api/auth/verify', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
userId,
|
||||
code: verificationCode,
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
stayLoggedIn,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json() as { error?: string };
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(data.error || 'Verification failed');
|
||||
}
|
||||
|
||||
// Success
|
||||
if (onSuccess) onSuccess();
|
||||
router.push('/home');
|
||||
router.refresh();
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal login / signup initiation
|
||||
const res = await fetch('/api/auth/email', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@ -43,13 +75,21 @@ export function UnifiedLogin({ onSuccess }: UnifiedLoginProps) {
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json() as { error?: string };
|
||||
const data = await res.json() as { error?: string, success?: boolean, pendingVerification?: boolean, userId?: string };
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(data.error || 'Authentication failed');
|
||||
}
|
||||
|
||||
// Success
|
||||
// Check if we need verification
|
||||
if (data.pendingVerification) {
|
||||
setPendingVerification(true);
|
||||
setUserId(data.userId || null);
|
||||
setLoading(false); // Stop loading so user can enter code
|
||||
return;
|
||||
}
|
||||
|
||||
// Success (Direct login)
|
||||
if (onSuccess) onSuccess();
|
||||
router.push('/home');
|
||||
router.refresh();
|
||||
@ -235,7 +275,7 @@ export function UnifiedLogin({ onSuccess }: UnifiedLoginProps) {
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
{!isSignup && (
|
||||
{!isSignup && !pendingVerification && (
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
@ -258,11 +298,32 @@ export function UnifiedLogin({ onSuccess }: UnifiedLoginProps) {
|
||||
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
||||
required
|
||||
minLength={8}
|
||||
disabled={pendingVerification}
|
||||
className="pl-10 bg-slate-50 dark:bg-slate-800/50"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{pendingVerification && (
|
||||
<div className="space-y-2 animate-in fade-in slide-in-from-top-2 duration-300">
|
||||
<Label htmlFor="verificationCode" className="text-primary font-bold">Verification Code</Label>
|
||||
<Input
|
||||
id="verificationCode"
|
||||
placeholder="Enter the code sent to your email"
|
||||
value={verificationCode}
|
||||
onChange={(e) => setVerificationCode(e.target.value)}
|
||||
required
|
||||
className="bg-primary/5 border-primary/20 text-lg tracking-widest text-center font-mono placeholder:font-sans placeholder:text-sm placeholder:tracking-normal"
|
||||
/>
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400 font-medium flex items-start gap-1.5 p-2 bg-amber-50 dark:bg-amber-900/20 rounded-lg border border-amber-100 dark:border-amber-800/50">
|
||||
<AlertCircle className="w-3.5 h-3.5 mt-0.5 shrink-0" />
|
||||
<span>
|
||||
Please check your spam/junk folder if you don't see the email in your inbox.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<StayLoggedInCheckbox />
|
||||
|
||||
<Button
|
||||
@ -277,7 +338,7 @@ export function UnifiedLogin({ onSuccess }: UnifiedLoginProps) {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{isSignup ? 'Create Account' : 'Sign In'}
|
||||
{pendingVerification ? 'Verify & Sign In' : (isSignup ? 'Create Account' : 'Sign In')}
|
||||
<ArrowRight className="ml-2 h-4 w-4 group-hover:translate-x-1 transition-transform" />
|
||||
</>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user