fixed issue with login that keeps returning.

This commit is contained in:
bobbert committed 2025-03-14 23:37:25 +00:00
1 parent ea38775a82
commit 11fc5c8b3d
5 files changed
+392 -142

No files matched your search

+42 -25
View File
@@ -1,8 +1,7 @@
"use client";
import { useState } from "react";
import { signIn } from "next-auth/react";
import { useRouter } from "next/navigation";
"use client"; // Mark as a Client Component
import { useState, useEffect } from "react";
import { signIn, useSession } from "next-auth/react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
export default function Login() {
@@ -10,39 +9,57 @@ export default function Login() {
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [isLoading, setIsLoading] = useState(false);
const router = useRouter();
const { data: session, status } = useSession();
const searchParams = useSearchParams();
// Redirect if already authenticated
useEffect(() => {
if (status === "authenticated") {
const callbackUrl = searchParams.get("callbackUrl") || "/team-selection";
router.push(callbackUrl);
}
// Check for error param
const errorParam = searchParams.get("error");
if (errorParam) {
if (errorParam === "AuthError") {
setError("Session expired. Please log in again.");
} else {
setError("Authentication failed. Please try again.");
}
}
}, [status, router, searchParams]);
const handleLogin = async (e) => {
e.preventDefault();
if (!username || !password) {
setError("Username and password are required");
return;
}
setIsLoading(true);
setError("");
try {
console.log("Attempting to sign in with:", username);
const result = await signIn("credentials", {
redirect: false,
username,
password,
callbackUrl: `${window.location.origin}/team-selection`,
callbackUrl: searchParams.get("callbackUrl") || "/team-selection",
});
console.log("Sign in result:", result);
if (result?.error) {
throw new Error(result.error);
}
if (result?.ok) {
console.log("Sign in successful, redirecting...");
// Use router.push with { replace: true } to avoid history issues
router.push("/team-selection", { replace: true });
return;
setError(result.error || "Login failed");
setIsLoading(false);
} else if (result?.url) {
router.push(result.url);
}
} catch (error) {
console.error("Login error:", error);
setError(error.message || "Failed to login. Please try again.");
} finally {
setError("Connection error. Please try again.");
setIsLoading(false);
}
};
@@ -79,7 +96,7 @@ export default function Login() {
</button>
</form>
{/* Add separate div for register button with margin-top */}
{/* Reduced margin in the container */}
<div className="register-button-container">
<Link href="/register">
<button className="auth-button register-button">Register</button>
@@ -88,7 +105,7 @@ export default function Login() {
</div>
</div>
{/* Update styles to include spacing between buttons */}
{/* Update styles to reduce gap */}
<style jsx>{`
.auth-card {
background-color: #fff;
@@ -100,13 +117,13 @@ export default function Login() {
display: flex;
flex-direction: column;
width: 100%;
margin-bottom: 8px; /* Reduced margin below the form (was 15px) */
margin-bottom: 2px; /* Reduced space after form */
}
.input-container {
margin-bottom: 10px; /* Add consistent spacing between input fields */
margin-bottom: 10px;
}
.register-button-container {
margin-top: 5px; /* Reduced margin above register button (was 10px) */
margin-top: 2px; /* Reduced space before register button */
}
.auth-button {
padding: 10px;
+23 -23
View File
@@ -13,50 +13,50 @@ export default function Register() {
const handleRegister = async (e) => {
e.preventDefault();
// Basic validation
if (!username || !password) {
setError("Username and password are required");
return;
}
setIsLoading(true);
setError("");
try {
// First register the user
const response = await fetch("/api/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
});
const result = await response.json();
if (!response.ok) {
const result = await response.json();
setError(result.error || "Failed to register");
setIsLoading(false);
return;
}
const result = await response.json();
// Then try to sign in
const signInResult = await signIn("credentials", {
redirect: false,
username,
password,
callbackUrl: "/team-selection",
});
if (result.error) {
setError(result.error);
if (signInResult?.error) {
setError(`Login failed: ${signInResult.error}`);
setIsLoading(false);
} else {
// Automatically log in the user after successful registration
const signInResult = await signIn("credentials", {
redirect: false,
username,
password,
});
if (signInResult?.error) {
setError("Registration successful, but failed to log in");
setIsLoading(false);
} else {
router.push("/team-selection");
}
// Successful login
router.push(signInResult?.url || "/team-selection");
}
} catch (err) {
if (err instanceof SyntaxError) {
setError("Unexpected response from server");
} else {
setError("An unexpected error occurred");
}
console.error(err);
console.error("Registration/login error:", err);
setError("An unexpected error occurred. Please try again.");
setIsLoading(false);
}
};
+23 -49
View File
@@ -1,16 +1,15 @@
import NextAuth from "next-auth"; // <-- Changed from "next-auth/next"
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { validateCredentials } from "@/actions/auth";
import jwt from "jsonwebtoken";
import { cookies } from "next/headers";
// Use a consistent secret for JWT signing and verification
const JWT_SECRET = process.env.NEXTAUTH_SECRET || "banana";
console.log("Using NextAuth Secret:", JWT_SECRET);
const JWT_SECRET =
process.env.NEXTAUTH_SECRET ||
"your-fallback-secret-should-be-at-least-32-chars";
export const authOptions = {
providers: [
// Correct syntax: no function call, just reference the imported object
{
id: "credentials",
name: "Credentials",
@@ -25,18 +24,14 @@ export const authOptions = {
console.log("Missing credentials");
return null;
}
// Validate credentials against our database
const user = await validateCredentials(
credentials.username,
credentials.password
);
if (user) {
console.log("User authenticated:", user.username);
return user;
}
console.log("Invalid credentials for:", credentials.username);
return null;
} catch (error) {
@@ -46,27 +41,10 @@ export const authOptions = {
},
},
],
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60, // 30 days
maxAge: 30 * 24 * 60 * 60,
},
jwt: {
secret: JWT_SECRET,
encode: async ({ secret, token }) => {
return jwt.sign(token, secret);
},
decode: async ({ secret, token }) => {
try {
return jwt.verify(token, secret);
} catch (error) {
console.error("JWT decode error:", error);
return null;
}
},
},
callbacks: {
async jwt({ token, user }) {
if (user) {
@@ -77,7 +55,6 @@ export const authOptions = {
}
return token;
},
async session({ session, token }) {
if (token) {
session.user = session.user || {};
@@ -88,31 +65,28 @@ export const authOptions = {
}
return session;
},
async redirect({ baseUrl, session }) {
// Redirect admins to dashboard, users with a team to their team page,
// otherwise to team selection.
if (session?.user) {
if (session.user.role === "admin") {
return `${baseUrl}/admin/dashboard`;
}
if (session.user.teamId) {
return `${baseUrl}/team/${session.user.teamId}`;
}
}
return `${baseUrl}/team-selection`;
},
},
pages: {
signIn: "/login",
error: "/login?error=true",
},
// Add debugging to help identify issues with API responses
debug: process.env.NODE_ENV === "development",
// Add logger to catch issues
logger: {
error(code, metadata) {
console.error(`NextAuth error: ${code}`, metadata);
},
warn(code) {
console.warn(`NextAuth warning: ${code}`);
},
debug(code, metadata) {
console.log(`NextAuth debug: ${code}`, metadata);
},
},
secret: JWT_SECRET,
};
// Token helpers
export function createToken(payload) {
return jwt.sign(payload, JWT_SECRET, { expiresIn: "30d" });
}
@@ -126,9 +100,9 @@ export function verifyToken(token) {
}
}
// Set session runtime to nodejs (not edge for better compatibility)
export const runtime = "nodejs";
// Ensure that the NextAuth export is callable over interop
const NextAuthFn = NextAuth.default ? NextAuth.default : NextAuth;
const handler = NextAuthFn(authOptions);
// Create the handler with correct NextAuth instantiation
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
export const runtime = "nodejs";
+10 -1
View File
@@ -3,5 +3,14 @@
import { SessionProvider } from "next-auth/react";
export function NextAuthProvider({ children }) {
return <SessionProvider>{children}</SessionProvider>;
return (
<SessionProvider
// Options to make session more reliable
refetchInterval={5 * 60} // Refetch session every 5 minutes (in seconds)
refetchOnWindowFocus={true} // Refetch when window gets focus
refetchWhenOffline={false} // Don't try to refetch when offline
>
{children}
</SessionProvider>
);
}