Skip to content

Commit

Permalink
fix: fix issue with return url
Browse files Browse the repository at this point in the history
chore: add notes
  • Loading branch information
mainawycliffe committed Nov 27, 2023
1 parent 6f93554 commit 10c8708
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 33 deletions.
45 changes: 21 additions & 24 deletions src/components/Authentication/Kratos/KratosLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@ import type { NextPage } from "next";
import Link from "next/link";
import Router, { useRouter } from "next/router";
import { useCallback, useEffect, useState } from "react";
import { Flow, HandleError, useCreateLogoutHandler } from "../../ory";
import { Flow, HandleError } from "../../ory";
import { SetUriFlow } from "../../ory/helpers";
import ory from "../../ory/sdk";

const Login: NextPage = () => {
const [returnTo, setReturnTo] = useState<string | undefined>();
const [flow, setFlow] = useState<LoginFlow>();

const { query, push, isReady } = useRouter();

const returnTo = String(query.return_to || "");
console.log("Return to: " + returnTo);
const returnToFromQuery = (query.return_to as string) || "";
const flowId = String(query.flow || "");

// If we have a return_to query parameter, we want to redirect the user to
// that URL after a successful login. if set, and return_to is empty, we don't
// overwrite it.
useEffect(() => {
if (returnToFromQuery && !returnTo) {
setReturnTo(returnToFromQuery);
}
}, [returnTo, returnToFromQuery]);

// Refresh means we want to refresh the session. This is needed, for example, when we want to update the password
// of a user.
const refresh = Boolean(query.refresh);
Expand Down Expand Up @@ -54,30 +63,26 @@ const Login: NextPage = () => {
})
.then(({ data }) => {
setFlow(data);
SetUriFlow(Router, data.id);
SetUriFlow(Router, data.id, returnTo);
})
.catch(handleError),
[handleError]
);

// This might be confusing, but we want to show the user an option
// to sign out if they are performing two-factor authentication!
const onLogout = useCreateLogoutHandler([aal, refresh]);

useEffect(() => {
if (!isReady) {
return;
}

if (flowId) {
getFlow(flowId).catch(() => {
createFlow(refresh, aal, returnTo);
createFlow(refresh, aal, returnTo ?? "/");
});
return;
}

// Otherwise we initialize it
createFlow(refresh, aal, returnTo);
createFlow(refresh, aal, returnTo ?? "/");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isReady]);

Expand Down Expand Up @@ -113,21 +118,13 @@ const Login: NextPage = () => {
<div className="mt-8 bg-white pt-4 pb-8 px-4 shadow sm:rounded-lg sm:px-10">
<Flow onSubmit={submitFlow} flow={flow} />
</div>
{aal || refresh ? (
<div>
<div data-testid="logout-link" onClick={onLogout}>
Log out
<div className="mt-2">
<Link href="/recovery" passHref>
<div className="cursor-pointer font-medium text-blue-600 hover:text-blue-500">
Reset password
</div>
</div>
) : (
<div className="mt-2">
<Link href="/recovery" passHref>
<div className="cursor-pointer font-medium text-blue-600 hover:text-blue-500">
Reset password
</div>
</Link>
</div>
)}
</Link>
</div>
</div>
</div>
);
Expand Down
7 changes: 6 additions & 1 deletion src/components/Authentication/Kratos/KratosLogoutButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { useLocation } from "react-router-dom";
import { useCreateLogoutHandler } from "../../ory";

export default function KratosLogoutButton() {
const { pathname, search } = useLocation();

const returnTo = pathname + search;

const onLogout = useCreateLogoutHandler([]);

return (
<button
type="button"
onClick={onLogout}
onClick={() => onLogout(returnTo)}
className="block w-full py-2 px-4 text-left text-sm text-gray-700 hover:bg-gray-50 hover:text-gray-900 border-0 border-b border-gray-200"
>
Sign out
Expand Down
17 changes: 15 additions & 2 deletions src/components/ory/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@

import { NextRouter } from "next/router";

export const SetUriFlow = (router: NextRouter, id: string) => {
export const SetUriFlow = (
router: NextRouter,
id: string,
returnTo?: string
) => {
// Check that current query flow id does not match requested one - pushing will trigger useEffect if router bound
if (router.query.flow === id) {
return;
}

router.push(`${router.pathname}?flow=${id}`, undefined, { shallow: true });
router.push(
`${router.pathname}`,
{
query: {
return_to: returnTo ? decodeURI(returnTo) : undefined,
flow: id
}
},
{ shallow: true }
);
};
22 changes: 16 additions & 6 deletions src/components/ory/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AxiosError } from "axios";
import Router, { useRouter } from "next/router";
import Router from "next/router";
import { DependencyList, useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import ory from "./sdk";

export const HandleError = (
Expand Down Expand Up @@ -171,7 +172,6 @@ export const HandleError = (
export function useCreateLogoutHandler(deps?: DependencyList) {
const [logoutToken, setLogoutToken] = useState<string>("");
const handleError = HandleError();
const { push } = useRouter();

useEffect(() => {
ory
Expand All @@ -183,16 +183,26 @@ export function useCreateLogoutHandler(deps?: DependencyList) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);

return () => {
return (returnTo: string) => {
if (logoutToken) {
ory
.updateLogoutFlow({
token: logoutToken
token: logoutToken,
returnTo: returnTo
})
.then(() => {
console.warn("Logout successful");
// this a workaround, react router and next router are not compatible
// and seem to be conflicting with each other, instead we do a full
// page reload, which is not ideal, but works for now
window.location.href = "/login?return_to=" + returnTo;
})
.then(() => push("/"))
.catch((error) => {
console.error("Logout error:", error.message);
push("/");
// this a workaround, react router and next router are not compatible
// and seem to be conflicting with each other, instead we do a full
// page reload, which is not ideal, but works for now
window.location.href = "/login?return_to=" + returnTo;
});
}
};
Expand Down

0 comments on commit 10c8708

Please sign in to comment.