Skip to content

Commit a24de21

Browse files
committed
Fix no redirect to dashboard if user is already logged in and lands on login page (#4561)
Did not go the middleware route here because even if we properly check the logged in status in middleware and redirect - it's possible for user to get stuck in that case if for some reason the wallet never gets into "connecting" status and so the useLoggedInUser query never runs and never redirects the user to login page ( and even if it did - they would immediately get redirected to other page because they have a "valid" auth cookie ) so safest solution here is to let the user land on login page and once then redirect from there after wallet connection + sign in is done <!-- start pr-codex --> --- ## PR-Codex overview The focus of this PR is to refactor the login process in the dashboard app. ### Detailed summary - Removed unused imports and functions - Refactored `doLogin` function to handle redirect logic internally - Added `useDashboardRouter` hook to handle navigation - Improved error handling and redirect logic in the login process > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 2d2e6cb commit a24de21

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

apps/dashboard/src/app/login/auth-actions.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import "server-only";
33

44
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
55
import { cookies } from "next/headers";
6-
import { redirect } from "next/navigation";
76
import { getAddress } from "thirdweb";
87
import type {
98
GenerateLoginPayloadParams,
@@ -34,10 +33,7 @@ export async function getLoginPayload(
3433
return (await res.json()).payload;
3534
}
3635

37-
export async function doLogin(
38-
payload: VerifyLoginPayloadParams,
39-
nextPath?: string | null,
40-
) {
36+
export async function doLogin(payload: VerifyLoginPayloadParams) {
4137
// forward the request to the API server
4238
const res = await fetch(`${THIRDWEB_API_HOST}/v1/auth/login`, {
4339
method: "POST",
@@ -126,25 +122,6 @@ export async function doLogin(
126122
// 3 days
127123
maxAge: 3 * 24 * 60 * 60,
128124
});
129-
130-
// redirect to the nextPath (if set)
131-
if (nextPath && isValidRedirectPath(nextPath)) {
132-
return redirect(nextPath);
133-
}
134-
// if we do not have a next path, redirect to dashboard home
135-
return redirect("/dashboard");
136-
}
137-
function isValidRedirectPath(encodedPath: string): boolean {
138-
try {
139-
// Decode the URI component
140-
const decodedPath = decodeURIComponent(encodedPath);
141-
// ensure the path always starts with a _single_ slash
142-
// dobule slash could be interpreted as `//example.com` which is not allowed
143-
return decodedPath.startsWith("/") && !decodedPath.startsWith("//");
144-
} catch {
145-
// If decoding fails, return false
146-
return false;
147-
}
148125
}
149126

150127
export async function doLogout() {

apps/dashboard/src/app/login/page.tsx

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { ColorModeToggle } from "@/components/color-mode-toggle";
44
import { thirdwebClient } from "@/constants/client";
5+
import { useDashboardRouter } from "@/lib/DashboardRouter";
56
import { useTheme } from "next-themes";
67
import { useSearchParams } from "next/navigation";
78
import { Suspense, useEffect, useState } from "react";
@@ -38,14 +39,39 @@ export default function LoginPage() {
3839
function CustomConnectEmmbed() {
3940
const isLG = useMediaQuery("(min-width: 1024px)");
4041
const searchParams = useSearchParams();
42+
const router = useDashboardRouter();
4143
const { theme } = useTheme();
44+
const nextSearchParam = searchParams?.get("next");
45+
46+
function onLoginSuccessful() {
47+
if (nextSearchParam && isValidRedirectPath(nextSearchParam)) {
48+
router.replace(nextSearchParam);
49+
} else {
50+
router.replace("/dashboard");
51+
}
52+
}
53+
4254
return (
4355
<ConnectEmbed
4456
auth={{
4557
getLoginPayload,
46-
doLogin: (params) => doLogin(params, searchParams?.get("next")),
58+
doLogin: async (params) => {
59+
try {
60+
await doLogin(params);
61+
onLoginSuccessful();
62+
} catch (e) {
63+
console.error("Failed to login", e);
64+
throw e;
65+
}
66+
},
4767
doLogout,
48-
isLoggedIn,
68+
isLoggedIn: async (x) => {
69+
const isLoggedInResult = await isLoggedIn(x);
70+
if (isLoggedInResult) {
71+
onLoginSuccessful();
72+
}
73+
return isLoggedInResult;
74+
},
4975
}}
5076
client={thirdwebClient}
5177
modalSize={isLG ? "wide" : "compact"}
@@ -54,6 +80,19 @@ function CustomConnectEmmbed() {
5480
);
5581
}
5682

83+
function isValidRedirectPath(encodedPath: string): boolean {
84+
try {
85+
// Decode the URI component
86+
const decodedPath = decodeURIComponent(encodedPath);
87+
// ensure the path always starts with a _single_ slash
88+
// dobule slash could be interpreted as `//example.com` which is not allowed
89+
return decodedPath.startsWith("/") && !decodedPath.startsWith("//");
90+
} catch {
91+
// If decoding fails, return false
92+
return false;
93+
}
94+
}
95+
5796
function useMediaQuery(query: string) {
5897
const [matches, setMatches] = useState(() => {
5998
if (typeof window === "undefined") return false;

0 commit comments

Comments
 (0)