Skip to content

Commit

Permalink
Merge pull request #1426 from flanksource/1408-kratos-login-requires-…
Browse files Browse the repository at this point in the history
…login-twice

1408-kratos-login-requires-login-twice
  • Loading branch information
moshloop authored Sep 26, 2023
2 parents 43a0d14 + 9ce44fd commit 764bef2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 84 deletions.
40 changes: 16 additions & 24 deletions src/components/Authentication/Kratos/KratosAuthSessionChecker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,33 @@ export default function KratosAuthSessionChecker({
const { push } = useRouter();

useEffect(() => {
if (!isAuthEnabled()) {
return;
}
const getSession = async () => {
if (!isAuthEnabled()) {
return;
}

ory
.toSession()
.then(({ data }) => {
try {
const { data } = await ory.toSession();
setSession(data);
})
.catch((err: AxiosError) => {
// Due to the conflict between NextJS Routing and React Router, we can
// get the current URL from next router accurately, but we can rely on
// the window location to get the current URL accurately. This can be
// fixed in the future when we move to NextJS fully.
} catch (err) {
const url = window.location.pathname;
switch (err.response?.status) {
switch ((err as AxiosError).response?.status) {
case 403:
// This is a legacy error code thrown. See code 422 for
// more details.
push(`/login?aal=aal2&return_to=${url}`);
return;
break;
case 422:
// This status code is returned when we are trying to
// validate a session which has not yet completed
// it's second factor
push(`/login?aal=aal2&return_to=${url}`);
return;
break;
case 401:
push(`/login?return_to=${url}`);
return;
break;
default:
throw err;
}
}
};

// Something else happened!
return Promise.reject(err);
});
getSession();
}, [push]);

if (isAuthEnabled() && !session) {
Expand Down
106 changes: 48 additions & 58 deletions src/components/Authentication/Kratos/KratosLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { LoginFlow, UpdateLoginFlowBody } from "@ory/client";
import { AxiosError } from "axios";
import type { NextPage } from "next";
import Link from "next/link";
import { useRouter } from "next/router";
Expand Down Expand Up @@ -29,69 +28,60 @@ const Login: NextPage = () => {
const onLogout = useCreateLogoutHandler([aal, refresh]);

useEffect(() => {
// If the router is not ready yet, or we already have a flow, do nothing.
if (!router.isReady || flow) {
return;
}
const fetchFlow = async () => {
if (!router.isReady || flow) {
return;
}

// If ?flow=.. was in the URL, we fetch it
if (flowId) {
ory
.getLoginFlow({
id: String(flowId)
})
.then(({ data }) => {
if (flowId) {
try {
const { data } = await ory.getLoginFlow({ id: String(flowId) });
setFlow(data);
})
.catch(handleGetFlowError(router, "login", setFlow));
return;
}
} catch (err: any) {
await handleGetFlowError(router, "login", setFlow)(err);
}
return;
}

// Otherwise we initialize it
ory
.createBrowserLoginFlow({
returnTo: returnTo ? String(returnTo) : undefined,
refresh: Boolean(refresh),
aal: aal ? String(aal) : undefined
})
.then(({ data }) => {
try {
const { data } = await ory.createBrowserLoginFlow({
returnTo: returnTo ? String(returnTo) : undefined,
refresh: Boolean(refresh),
aal: aal ? String(aal) : undefined
});
setFlow(data);
})
.catch(handleFlowError(router, "login", setFlow));
}, [flowId, router, router.isReady, aal, refresh, returnTo, flow]);
} catch (err: any) {
await handleFlowError(router, "login", setFlow)(err);
}
};

const onSubmit = (values: UpdateLoginFlowBody) =>
router
// On submission, add the flow ID to the URL but do not navigate. This prevents the user loosing
// his data when she/he reloads the page.
.push(`/login?flow=${flow?.id}`, undefined, { shallow: true })
.then(() =>
ory
.updateLoginFlow({
flow: flow?.id!,
updateLoginFlowBody: values
})
// We logged in successfully! Let's bring the user home.
.then((res) => {
if (flow?.return_to) {
router.push(flow?.return_to);
return;
}
router.push("/");
})
.then(() => {})
.catch(handleFlowError(router, "login", setFlow))
.catch((err: AxiosError) => {
// If the previous handler did not catch the error it's most likely a form validation error
if (err.response?.status === 400) {
// Yup, it is!
setFlow((err.response as any).data);
return;
}
fetchFlow();
}, [flowId, router, router.isReady, aal, refresh, returnTo, flow]);

return Promise.reject(err);
})
);
const onSubmit = async (values: UpdateLoginFlowBody) => {
try {
await router.push(`/login?flow=${flow?.id}`, undefined, {
shallow: true
});
await ory.updateLoginFlow({
flow: flow?.id!,
updateLoginFlowBody: values
});
if (flow?.return_to) {
window.location.href = flow?.return_to;
} else {
await router.push("/");
}
} catch (err: any) {
console.error(err);
await handleFlowError(router, "login", setFlow)(err);
if (err.response?.status === 400) {
setFlow((err.response as any).data);
} else {
throw err;
}
}
};

return (
<div className="w-96">
Expand Down
4 changes: 2 additions & 2 deletions src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { Fragment } from "react";
import PropTypes from "prop-types";
import { Dialog, Transition } from "@headlessui/react";
import { XIcon } from "@heroicons/react/solid";
import clsx from "clsx";
import PropTypes from "prop-types";
import React, { Fragment } from "react";

type ModalSize = "small" | "slightly-small" | "medium" | "large" | "full";

Expand Down

0 comments on commit 764bef2

Please sign in to comment.