From a400d2be61510f439cd2c1b0c63531bf0d0acab1 Mon Sep 17 00:00:00 2001 From: Pauline Date: Fri, 2 Aug 2024 15:14:30 +0100 Subject: [PATCH 1/5] Add initial hydra consent module --- package-lock.json | 120 ++++++++++++------ package.json | 2 +- pages/api/consent.ts | 80 ++++++++++++ pages/consent.tsx | 295 +++++++++++++++++-------------------------- pages/login.tsx | 4 +- styles/globals.css | 12 ++ 6 files changed, 290 insertions(+), 223 deletions(-) create mode 100644 pages/api/consent.ts diff --git a/package-lock.json b/package-lock.json index fd6fe31..475b492 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "@ory/integration-react", "version": "0.0.1", "dependencies": { - "@ory/client": "^0.0.0-next.f88d10559361", + "@ory/client": "1.6.2", "@ory/integrations": "0.2.8", "@ory/themes": "~0.0.101", "classnames": "^2.3.1", @@ -1104,20 +1104,11 @@ } }, "node_modules/@ory/client": { - "version": "0.0.0-next.f88d10559361", - "resolved": "https://registry.npmjs.org/@ory/client/-/client-0.0.0-next.f88d10559361.tgz", - "integrity": "sha512-mItHDBAiefd0wdSxduVDYvnEUiBqJuiDos3P0KVyBlg9d7G++c0Bkz0lUBtqwWP5LWwQoFULAa40QJfgjFQNXw==", - "deprecated": "An incorrect version was published.", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@ory/client/-/client-1.6.2.tgz", + "integrity": "sha512-eeSkFZsrX/hLaariBg2I9PQWueE9IVAV3Tps5UE7CYEvrGziFB1zdv8joQDGMss5O3Yv/CSlSf4rOwTeENDqBg==", "dependencies": { - "axios": "^0.26.1" - } - }, - "node_modules/@ory/client/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" + "axios": "^1.6.1" } }, "node_modules/@ory/integrations": { @@ -1319,6 +1310,14 @@ "axios": "^0.21.4" } }, + "node_modules/@ory/integrations/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, "node_modules/@ory/integrations/node_modules/next": { "version": "13.2.4", "resolved": "https://registry.npmjs.org/next/-/next-13.2.4.tgz", @@ -2045,13 +2044,33 @@ } }, "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "dependencies": { - "follow-redirects": "^1.14.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -3977,9 +3996,9 @@ "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash." }, "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -9227,21 +9246,11 @@ } }, "@ory/client": { - "version": "0.0.0-next.f88d10559361", - "resolved": "https://registry.npmjs.org/@ory/client/-/client-0.0.0-next.f88d10559361.tgz", - "integrity": "sha512-mItHDBAiefd0wdSxduVDYvnEUiBqJuiDos3P0KVyBlg9d7G++c0Bkz0lUBtqwWP5LWwQoFULAa40QJfgjFQNXw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@ory/client/-/client-1.6.2.tgz", + "integrity": "sha512-eeSkFZsrX/hLaariBg2I9PQWueE9IVAV3Tps5UE7CYEvrGziFB1zdv8joQDGMss5O3Yv/CSlSf4rOwTeENDqBg==", "requires": { - "axios": "^0.26.1" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - } + "axios": "^1.6.1" } }, "@ory/integrations": { @@ -9340,6 +9349,14 @@ "axios": "^0.21.4" } }, + "axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "requires": { + "follow-redirects": "^1.14.0" + } + }, "next": { "version": "13.2.4", "resolved": "https://registry.npmjs.org/next/-/next-13.2.4.tgz", @@ -9859,11 +9876,30 @@ "dev": true }, "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "requires": { - "follow-redirects": "^1.14.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + } } }, "axobject-query": { @@ -11291,9 +11327,9 @@ "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" }, "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "forever-agent": { "version": "0.6.1", diff --git a/package.json b/package.json index f3c5970..9ff242c 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "module": "dist/index.mjs", "typings": "dist/index.d.ts", "dependencies": { - "@ory/client": "^0.0.0-next.f88d10559361", + "@ory/client": "1.6.2", "@ory/integrations": "0.2.8", "@ory/themes": "~0.0.101", "classnames": "^2.3.1", diff --git a/pages/api/consent.ts b/pages/api/consent.ts new file mode 100644 index 0000000..4211a8a --- /dev/null +++ b/pages/api/consent.ts @@ -0,0 +1,80 @@ +import { NextApiRequest, NextApiResponse } from "next" +import { Configuration, OAuth2Api } from "@ory/client" + +const hydra = new OAuth2Api( + new Configuration({ + basePath: process.env.HYDRA_ADMIN_URL, + baseOptions: { + "X-Forwarded-Proto": "https", + withCredentials: true, + }, + }), +) + +// Helper function to extract session data +const extractSession = (identity: any, grantScope: string[]) => { + const session: any = { + access_token: { + roles: identity.metadata_public.roles, + scope: identity.metadata_public.scope, + authorities: identity.metadata_public.authorities, + sources: identity.metadata_public.sources, + user_name: identity.id, + }, + id_token: {}, + } + return session +} + +export default async (req: NextApiRequest, res: NextApiResponse) => { + const { consentChallenge, consentAction, grantScope, remember, identity } = + req.body + + try { + if (req.method === "GET") { + const { consent_challenge } = req.query + const response = await hydra.getOAuth2ConsentRequest({ + consentChallenge: String(consent_challenge), + }) + return res.status(200).json(response.data) + } else { + if (!consentChallenge || !consentAction) { + return res.status(400).json({ error: "Missing required parameters" }) + } + if (consentAction === "accept") { + const { data: body } = await hydra.getOAuth2ConsentRequest({ + consentChallenge, + }) + const session = extractSession(identity, grantScope) + const acceptResponse = await hydra.acceptOAuth2ConsentRequest({ + consentChallenge, + acceptOAuth2ConsentRequest: { + grant_scope: grantScope, + grant_access_token_audience: body.requested_access_token_audience, + session, + remember: Boolean(remember), + remember_for: 3600, + }, + }) + return res + .status(200) + .json({ redirect_to: acceptResponse.data.redirect_to }) + } else { + const rejectResponse = await hydra.rejectOAuth2ConsentRequest({ + consentChallenge, + rejectOAuth2Request: { + error: "access_denied", + error_description: "The resource owner denied the request", + }, + }) + + return res + .status(200) + .json({ redirect_to: rejectResponse.data.redirect_to }) + } + } + } catch (error) { + console.error(error) + return res.status(500).json({ error: "Internal server error" }) + } +} diff --git a/pages/consent.tsx b/pages/consent.tsx index 056ebdd..3054d96 100644 --- a/pages/consent.tsx +++ b/pages/consent.tsx @@ -1,208 +1,145 @@ -import { - SettingsFlow, - UpdateSettingsFlowBody, - UpdateSettingsFlowWithProfileMethod, -} from "@ory/client" -import { H3, P } from "@ory/themes" -import { AxiosError } from "axios" -import type { NextPage } from "next" -import Head from "next/head" -import Link from "next/link" +import React, { useEffect, useState } from "react" import { useRouter } from "next/router" -import { ReactNode, useEffect, useState } from "react" -import { consentQuestions } from "../data/consent-questionnaire" - -import { - ActionCard, - CenterLink, - Flow, - Messages, - Methods, - CardTitle, - InnerCard, -} from "../pkg" -import { handleFlowError } from "../pkg/errors" import ory from "../pkg/sdk" -interface Props { - flow?: SettingsFlow - only?: Methods -} - -function SettingsCard({ - flow, - only, - children, -}: Props & { children: ReactNode }) { - return {children} -} - -const Consent: NextPage = () => { - const [flow, setFlow] = useState() +import { MarginCard, CardTitle, TextCenterButton } from "../pkg" - // Get ?flow=... from the URL +const Consent = () => { const router = useRouter() - const { flow: flowId, return_to: returnTo } = router.query - const [csrfToken, setCsrfToken] = useState("") - const [traits, setTraits] = useState() - const [consent, setConsent] = useState({}) + const [consent, setConsent] = useState(null) + const [identity, setIdentity] = useState(null) + const [csrfToken, setCsrfToken] = useState(null) useEffect(() => { - // If the router is not ready yet, or we already have a flow, do nothing. - if (!router.isReady || flow) { - return - } + const { consent_challenge } = router.query + + ory + .toSession() + .then(({ data }) => { + setIdentity(data.identity) + }) + .catch((e) => console.log(e)) - // If ?flow=.. was in the URL, we fetch it - if (flowId) { - ory - .getSettingsFlow({ id: String(flowId) }) - .then(({ data }) => { - setFlow(data) - }) - .catch(handleFlowError(router, "settings", setFlow)) + if (!consent_challenge) { + // router.push("/404") return } - // Otherwise we initialize it - ory - .createBrowserSettingsFlow({ - returnTo: String(returnTo || ""), + fetch(`/api/consent?consent_challenge=${consent_challenge}`) + .then((response) => response.json()) + .then((data) => { + if (data.error) { + throw new Error(data.error) + } + setConsent(data) }) - .then(({ data }) => { - setFlow(data) - const csrfTokenFromHeaders = data.ui.nodes.find( - (node: any) => node.attributes.name === "csrf_token", - )?.attributes.value - const traits = data.identity.traits - setCsrfToken(csrfTokenFromHeaders || "") - setTraits(traits) - setConsent(traits.consent) + .catch((err) => { + console.error(err) }) - .catch(handleFlowError(router, "settings", setFlow)) - }, [flowId, router, router.isReady, returnTo, flow]) + }, [router]) - const handleChange = (event) => { - setConsent({ - ...consent, - [event.target.name]: String(event.target.checked), - }) - } - - const onSubmit = (event: React.FormEvent) => { + const handleSubmit = (event: React.FormEvent) => { event.preventDefault() - const updatedValues = { - csrf_token: csrfToken, - method: "profile", - traits: { - ...traits, - consent, - }, - } + const form = event.target as HTMLFormElement + const formData = new FormData(form) - return ( - 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(`/`) - .then(() => - ory - .updateSettingsFlow({ - flow: String(flow?.id), - updateSettingsFlowBody: updatedValues, - }) - .then(({ data }) => { - // The settings have been saved and the flow was updated. Let's show it to the user! - setFlow(data) + const submitter = event.nativeEvent.submitter as HTMLButtonElement + const consentAction = submitter.value - if (data.return_to) { - window.location.href = data.return_to - return - } - }) - .catch(handleFlowError(router, "consent", setFlow)) - .catch(async (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?.data) - return - } + const consentChallenge = formData.get("consent_challenge") as string + const remember = formData.get("remember") as string + const grantScope = formData.getAll("grant_scope") as string[] - return Promise.reject(err) - }), - ) - ) + if (!consentChallenge || !consentAction) { + console.error("consentChallenge or consentAction is missing") + return + } + + fetch("/api/consent", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + consentChallenge, + consentAction, + grantScope, + remember, + identity, // Include any additional identity data if needed + }), + }) + .then((response) => response.json()) + .then((data) => { + if (data.error) { + console.error(data.error) + return + } + router.push(data.redirect_to) + }) + .catch((err) => { + console.error(err) + }) } - return ( - <> - - Study Consent - - - - - Study Consent - - - - - Go back - - - - ) -} + if (!consent) { + return
Loading...
+ } -const ConsentForm: React.FC = ({ - questions, - onSubmit, - handleChange, - consent, -}) => { return ( -
- {questions.map((question, index) => { - if (question.field_type === "info") { - return ( - question.select_choices_or_calculations instanceof Array && - question.select_choices_or_calculations.map((info, idx) => ( -
- - {info.label} -
- )) - ) - } else if (question.field_type === "checkbox") { - return ( -
-
+ +
+ Consent Request + + + +
+ +

{consent.client.client_name || consent.client.client_id}

+
+
+ + {consent.requested_scope.map((scope: string) => ( +
- +
-
- - - ) - } - return null - })} -
+ ))} +
+

+
+ + +
+

+ + + +
+ ) } diff --git a/pages/login.tsx b/pages/login.tsx index 2b9fc8f..e926352 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -31,6 +31,7 @@ const Login: NextPage = () => { // AAL = Authorization Assurance Level. This implies that we want to upgrade the AAL, meaning that we want // to perform two-factor authentication/verification. aal, + login_challenge: loginChallenge, } = router.query // This might be confusing, but we want to show the user an option @@ -60,12 +61,13 @@ const Login: NextPage = () => { refresh: Boolean(refresh), aal: aal ? String(aal) : undefined, returnTo: returnTo ? String(returnTo) : undefined, + loginChallenge: loginChallenge ? String(loginChallenge) : undefined, }) .then(({ data }) => { setFlow(data) }) .catch(handleFlowError(router, "login", setFlow)) - }, [flowId, router, router.isReady, aal, refresh, returnTo, flow]) + }, [flowId, router, router.isReady, aal, refresh, returnTo, loginChallenge, flow]) const onSubmit = (values: UpdateLoginFlowBody) => router diff --git a/styles/globals.css b/styles/globals.css index 7e513aa..e627b09 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -22,6 +22,18 @@ button, font-size: 16px; } +.consent-button { + border-radius: 8px !important; + background-color: #706ef4 !important; + color: #fff !important; + width: 30%; + border: none; + padding: 8px; + margin: 8px; + font-size: 16px; + font-weight: 600; +} + .Toastify__close-button { width: 10% !important; border-radius: 30px !important; From 654bd234479fd3ab21afa405916bf94e184813d7 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 8 Aug 2024 12:46:58 +0100 Subject: [PATCH 2/5] Get username from mp_login --- pages/api/consent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/consent.ts b/pages/api/consent.ts index 4211a8a..035d98a 100644 --- a/pages/api/consent.ts +++ b/pages/api/consent.ts @@ -19,7 +19,7 @@ const extractSession = (identity: any, grantScope: string[]) => { scope: identity.metadata_public.scope, authorities: identity.metadata_public.authorities, sources: identity.metadata_public.sources, - user_name: identity.id, + user_name: identity.metadata_public.mp_login, }, id_token: {}, } From 82433a2369b9030a19a20b282bc4a0b597057599 Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 13 Aug 2024 17:45:15 +0100 Subject: [PATCH 3/5] Fix formatting --- pages/api/consent.ts | 2 +- pages/consent.tsx | 4 ++-- pages/login.tsx | 11 ++++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pages/api/consent.ts b/pages/api/consent.ts index 035d98a..5632cf5 100644 --- a/pages/api/consent.ts +++ b/pages/api/consent.ts @@ -1,5 +1,5 @@ -import { NextApiRequest, NextApiResponse } from "next" import { Configuration, OAuth2Api } from "@ory/client" +import { NextApiRequest, NextApiResponse } from "next" const hydra = new OAuth2Api( new Configuration({ diff --git a/pages/consent.tsx b/pages/consent.tsx index 3054d96..607b74a 100644 --- a/pages/consent.tsx +++ b/pages/consent.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useState } from "react" import { useRouter } from "next/router" -import ory from "../pkg/sdk" +import React, { useEffect, useState } from "react" import { MarginCard, CardTitle, TextCenterButton } from "../pkg" +import ory from "../pkg/sdk" const Consent = () => { const router = useRouter() diff --git a/pages/login.tsx b/pages/login.tsx index 2552da3..68ceaa7 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -67,7 +67,16 @@ const Login: NextPage = () => { setFlow(data) }) .catch(handleFlowError(router, "login", setFlow)) - }, [flowId, router, router.isReady, aal, refresh, returnTo, loginChallenge, flow]) + }, [ + flowId, + router, + router.isReady, + aal, + refresh, + returnTo, + loginChallenge, + flow, + ]) const onSubmit = (values: UpdateLoginFlowBody) => router From 28778bacd482b51529ea588f06091b27382e5336 Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 13 Aug 2024 17:59:02 +0100 Subject: [PATCH 4/5] Fix types --- pages/consent.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pages/consent.tsx b/pages/consent.tsx index 607b74a..1a5ab5a 100644 --- a/pages/consent.tsx +++ b/pages/consent.tsx @@ -8,7 +8,7 @@ const Consent = () => { const router = useRouter() const [consent, setConsent] = useState(null) const [identity, setIdentity] = useState(null) - const [csrfToken, setCsrfToken] = useState(null) + const [csrfToken, setCsrfToken] = useState("") useEffect(() => { const { consent_challenge } = router.query @@ -43,7 +43,8 @@ const Consent = () => { const form = event.target as HTMLFormElement const formData = new FormData(form) - const submitter = event.nativeEvent.submitter as HTMLButtonElement + const submitter = (event.nativeEvent as SubmitEvent) + .submitter as HTMLButtonElement const consentAction = submitter.value const consentChallenge = formData.get("consent_challenge") as string From a3b29e58e35c8756a6adadb920144302e93e763a Mon Sep 17 00:00:00 2001 From: Pauline Date: Mon, 19 Aug 2024 20:48:02 +0100 Subject: [PATCH 5/5] Fix login issue when session exists --- pages/consent.tsx | 2 +- pages/login.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/consent.tsx b/pages/consent.tsx index 1a5ab5a..56fd2b5 100644 --- a/pages/consent.tsx +++ b/pages/consent.tsx @@ -48,7 +48,7 @@ const Consent = () => { const consentAction = submitter.value const consentChallenge = formData.get("consent_challenge") as string - const remember = formData.get("remember") as string + const remember = !!formData.get("remember") const grantScope = formData.getAll("grant_scope") as string[] if (!consentChallenge || !consentAction) { diff --git a/pages/login.tsx b/pages/login.tsx index 68ceaa7..257828c 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -58,7 +58,7 @@ const Login: NextPage = () => { // Otherwise we initialize it ory .createBrowserLoginFlow({ - refresh: Boolean(refresh), + refresh: loginChallenge? true : Boolean(refresh), aal: aal ? String(aal) : undefined, returnTo: returnTo ? String(returnTo) : undefined, loginChallenge: loginChallenge ? String(loginChallenge) : undefined,