From c874bb4f59a2b9c9830930102f9bf597ae451861 Mon Sep 17 00:00:00 2001 From: rdbsolutions Date: Wed, 9 Apr 2025 10:24:44 +0100 Subject: [PATCH] updated authentication for welsh url --- .gitignore | 5 +- components/header.js | 6 +- components/myportal.js | 4 +- components/myportal/servicebanner.js | 12 ++-- components/timeout/index copy.js | 73 --------------------- components/timeout/index.js | 4 +- pages/api/auth/[...nextauth].js | 98 ++++++++++++++++++++++------ pages/auth/signin.js | 45 ++++++++++++- pages/auth/signin2.js | 30 +++++++-- 9 files changed, 167 insertions(+), 110 deletions(-) delete mode 100644 components/timeout/index copy.js diff --git a/.gitignore b/.gitignore index fdf5dd65..e329ead9 100644 --- a/.gitignore +++ b/.gitignore @@ -35,7 +35,6 @@ pages/polling.js # dev apis to no include -/pages/api/endpoint/getaccounts_api.js - - +pages/api/endpoint/getaccounts_api.js +pages/auth/signin2.js diff --git a/components/header.js b/components/header.js index fedc8d72..77b9cc5f 100644 --- a/components/header.js +++ b/components/header.js @@ -78,7 +78,9 @@ const Header = (props) => { destroyCookie(null, "next-auth.callback-url", { path: "/" }), destroyCookie(null, "pedw_locale", { path: "/" }), destroyCookie(null, "pinsUser", { path: "/" }), - signOut({ callbackUrl: "/logout" }); + signOut({ + callbackUrl: locale == "cy" ? "/cy/allgofnodi" : "/logout", + }); }; return ( @@ -220,7 +222,7 @@ const Header = (props) => { { diff --git a/components/myportal.js b/components/myportal.js index d9a0e183..5ea4a188 100644 --- a/components/myportal.js +++ b/components/myportal.js @@ -32,7 +32,9 @@ const MyPortal = (props) => { destroyCookie(null, "next-auth.callback-url", { path: "/" }), destroyCookie(null, "pedw_locale", { path: "/" }), destroyCookie(null, "pinsUser", { path: "/" }), - signOut({ callbackUrl: "/logout" }); + signOut({ + callbackUrl: locale == "cy" ? "/cy/allgofnodi" : "/logout", + }); }; const isLPA = diff --git a/components/myportal/servicebanner.js b/components/myportal/servicebanner.js index dd3eee09..2d6f3960 100644 --- a/components/myportal/servicebanner.js +++ b/components/myportal/servicebanner.js @@ -18,7 +18,7 @@ const ServiceBanner = (props) => { ); }; - const handleLogout = () => { + const handleLogout = (locale) => { console.info("////////////\n" + "logout" + "\n////////////"); window.localStorage.clear(), destroyCookie(null, "next-auth.csrf-token"), @@ -26,7 +26,9 @@ const ServiceBanner = (props) => { destroyCookie(null, "next-auth.callback-url", { path: "/" }), destroyCookie(null, "pedw_locale", { path: "/" }), destroyCookie(null, "pinsUser", { path: "/" }), - signOut({ callbackUrl: "/logout" }); + signOut({ + callbackUrl: locale == "cy" ? "/cy/allgofnodi" : "/logout", + }); }; const portalLogoLink = [ @@ -87,9 +89,11 @@ const ServiceBanner = (props) => {
{ - handleLogout(); + handleLogout(router.locale); }} className="govuk-header__link " > diff --git a/components/timeout/index copy.js b/components/timeout/index copy.js deleted file mode 100644 index 05475c36..00000000 --- a/components/timeout/index copy.js +++ /dev/null @@ -1,73 +0,0 @@ -import { signOut } from "next-auth/react"; -import useTranslation from "next-translate/useTranslation"; -import { useRouter } from "next/router"; -import { destroyCookie } from "nookies"; -import { useState } from "react"; -import IdleTimer from "react-idle-timer"; -import TimeoutModal from "./timeoutmodal"; - -const TimeOut = (props) => { - let { t } = useTranslation(); - - const router = useRouter(); - const { locale } = router; - const [showModal, setShowModal] = useState(false); - const inactiveTimeOut = 1200; // in seconds - const reminderTimeout = 60; // in seconds - - let idleTimer = null; - let logoutTimer = null; - - let onIdle = () => { - togglePopup(); - logoutTimer = setTimeout(() => { - handleLogout(); - }, 1000 * reminderTimeout * 1); - }; - - let togglePopup = () => { - showModal == true ? setShowModal(false) : setShowModal(true); - }; - - let handleStayLoggedIn = () => { - if (logoutTimer) { - clearTimeout(logoutTimer); - logoutTimer = null; - } - idleTimer.reset(); - togglePopup(); - }; - - const handleLogout = () => { - console.info("////////////\n" + "logout" + "\n////////////"); - window.localStorage.clear(), - destroyCookie(null, "next-auth.csrf-token", { path: "/" }), - destroyCookie(null, "next-auth.callback-url", { path: "/" }), - destroyCookie(null, "pedw_locale", { path: "/" }), - destroyCookie(null, "pinsUser", { path: "/" }), - signOut({ callbackUrl: "/logout" }); - }; - - return ( - <> - { - idleTimer = ref; - }} - element={document} - stopOnIdle={true} - //onActive={console.log(" bbis active", idleTimer)} - onIdle={onIdle} - timeout={1000 * inactiveTimeOut * 1} - /> - - - ); -}; - -export default TimeOut; diff --git a/components/timeout/index.js b/components/timeout/index.js index b810a8b6..76f56ab3 100644 --- a/components/timeout/index.js +++ b/components/timeout/index.js @@ -26,7 +26,9 @@ const TimeOut = (props) => { destroyCookie(null, "next-auth.callback-url", { path: "/" }), destroyCookie(null, "pedw_locale", { path: "/" }), destroyCookie(null, "pinsUser", { path: "/" }), - signOut({ callbackUrl: "/logout" }); + signOut({ + callbackUrl: locale == "cy" ? "/cy/allgofnodi" : "/logout", + }); setOpen(false); }; diff --git a/pages/api/auth/[...nextauth].js b/pages/api/auth/[...nextauth].js index 6fdcd6ea..2f5616e6 100644 --- a/pages/api/auth/[...nextauth].js +++ b/pages/api/auth/[...nextauth].js @@ -118,6 +118,24 @@ const parseUrl = (url) => { }; }; +const appendParamsAndPathToNewUrl = (fromUrl, toUrl) => { + const fromUrlObj = new URL(fromUrl); // Parse the source URL + const params = fromUrlObj.searchParams; // Extract the query parameters + + const toUrlObj = new URL(toUrl); // Parse the new domain URL + toUrlObj.pathname = fromUrlObj.pathname; // Copy the path from the source URL + + // Append only the parameters that don't already exist in the destination URL + params.forEach((value, key) => { + if (!toUrlObj.searchParams.has(key)) { + // Check if the parameter already exists + toUrlObj.searchParams.append(key, value); + } + }); + + return toUrlObj.toString(); // Return the full new URL as a string +}; + const authOptions = (locale, req, res) => { //console.log(req.query.callbackUrl); // let newURL = parseUrl( @@ -125,7 +143,9 @@ const authOptions = (locale, req, res) => { // ? "https://" + process.env.I18N_DOMAIN + ":3000" // : process.env.NEXTAUTH_URL // ); - + // console.log("which locale", locale); + // console.log("which referer", req.body); + // console.log("cookie locale", req.cookies["pedw_locale"]); return { providers: [ { @@ -140,9 +160,29 @@ const authOptions = (locale, req, res) => { "verification url API: " + url + "\n", "============================================================\n" ); + + let newURL = + locale == "cy" + ? process.env.CY_API_ROOT + + "/api/auth/callback/email?callbackUrl=" + + encodeURIComponent(process.env.CY_API_ROOT) + + "&token=" + + searchParams.get("token") + + "&email=" + + encodeURIComponent(email) + : url; + + let formURL = appendParamsAndPathToNewUrl(url, newURL); + + console.log( + "============================================================\n", + "new verification url----: " + formURL + "\n", + "============================================================\n" + ); + return res .writeHead(200, { "Content-Type": "application/json" }) - .json({ url: url }); + .json({ url: formURL }); }, }, EmailProvider({ @@ -156,7 +196,7 @@ const authOptions = (locale, req, res) => { const emailAddress = email; console.log( "============================================================\n", - "verification url: " + url + "\n", + "verification url----: " + url + "\n", "============================================================\n" ); let newURL = @@ -168,11 +208,19 @@ const authOptions = (locale, req, res) => { searchParams.get("token") + "&email=" + encodeURIComponent(email) - : process.env.NEXTAUTH_URL; + : url; + + let formURL = appendParamsAndPathToNewUrl(url, newURL); + + console.log( + "============================================================\n", + "new verification url----: " + formURL + "\n", + "============================================================\n" + ); const personalisation = { "emailAddress": email, - "signInLink": url, + "signInLink": formURL, // locale == "cy" // ? url.split("&token")[0] + // "/cy&token" + @@ -228,7 +276,6 @@ const authOptions = (locale, req, res) => { }, pages: { signIn: (locale == "cy" ? "/cy" : "") + "/auth/signin", - //signOut: "/logout/signout", error: (locale == "cy" ? "/cy" : "") + "/auth/error", // Error code passed in query string as ?error= verifyRequest: (locale == "cy" ? "/cy" : "") + "/auth/verify-request", // (used for check email message) @@ -239,21 +286,32 @@ const authOptions = (locale, req, res) => { console.log("callback in auth", session, user); return Promise.resolve(session); }, - // redirect({ url, baseUrl }) { - // debugger; - // console.log("baseurl:", url, baseUrl); - // // Allows relative callback URLs - // if (url.startsWith("/")) return `${baseUrl}${url}`; - // // Allows callback URLs on the same origin - // else if (new URL(url).origin === baseUrl) return url; - // // let newURL = - // // locale == "cy" - // // ? process.env.CY_API_ROOT - // // : process.env.NEXTAUTH_URL; - // //return baseUrl; - // // return newURL; - // }, + redirect({ url, baseUrl }) { + //debugger; + console.log("baseurl:", url, baseUrl); + // Allows relative callback URLs + if (url.startsWith("/")) return `${baseUrl}${url}`; + // Allows callback URLs on the same origin + else if (new URL(url).origin === baseUrl) return url; + + const originalUrl = url; + let newUrl = + locale == "cy" + ? process.env.CY_API_ROOT + : process.env.NEXTAUTH_URL; + + const updatedUrl = appendParamsAndPathToNewUrl( + originalUrl, + newUrl + ); + console.log(updatedUrl); + + //return baseUrl; + + console.log("the url:", updatedUrl); + return updatedUrl; + }, }, }; }; diff --git a/pages/auth/signin.js b/pages/auth/signin.js index 02ad3eac..5882000b 100644 --- a/pages/auth/signin.js +++ b/pages/auth/signin.js @@ -148,12 +148,53 @@ export async function getServerSideProps(context) { context.locale, "\n//////////////////////\n" ); - let formURL = context.query.callbackUrl; + let formURL = context.req.headers.host; //console.log("formUrl:", formURL); formURL = typeof formURL == "undefined" ? null : formURL; + + let protocol = "http"; + if (context.req.headers["x-forwarded-proto"]) { + protocol = context.req.headers["x-forwarded-proto"]; + } + // Otherwise, check if the connection is encrypted (for https) + else if (context.req.connection.encrypted) { + protocol = "https"; + } + + formURL = protocol + "://" + formURL; + + console.log("Protocol:", protocol); + console.log("locale:", context.locale); + + const appendParamsAndPathToNewUrl = (fromUrl, toUrl) => { + const fromUrlObj = new URL(fromUrl); // Parse the source URL + const params = fromUrlObj.searchParams; // Extract the query parameters + + const toUrlObj = new URL(toUrl); // Parse the new domain URL + toUrlObj.pathname = fromUrlObj.pathname; // Copy the path from the source URL + + // Append the query parameters to the new URL + params.forEach((value, key) => + toUrlObj.searchParams.append(key, value) + ); + + return toUrlObj.toString(); // Return the full new URL as a string + }; + + formURL = appendParamsAndPathToNewUrl(context.query.callbackUrl, formURL); + + const url = new URL(formURL); // base URL + + const params = new URLSearchParams(url.search); + params.append("locale", context.locale); + + url.search = params.toString(); + + console.log("========== callback: ", url.toString()); + return { - props: { csrfToken: csrfToken, callbackUrl: formURL }, + props: { csrfToken: csrfToken, callbackUrl: url.toString() }, }; } diff --git a/pages/auth/signin2.js b/pages/auth/signin2.js index 86458778..0e14448a 100644 --- a/pages/auth/signin2.js +++ b/pages/auth/signin2.js @@ -219,16 +219,38 @@ export async function getServerSideProps(context) { const csrfToken = await getCsrfToken(context); console.log( "\n//////////////////////\n", - "Sign in callbackurl: " + context.query.callbackUrl, + "Sign in callbackurl: " + context.req.headers.host, context.locale, csrfToken + "\n//////////////////////\n" ); - let formURL = context.query.callbackUrl; - //console.log("formUrl:", formURL); + let formURL = context.req.headers.host; + console.log("formUrl:", formURL); formURL = typeof formURL == "undefined" ? null : formURL; + + let protocol = "http"; + if (context.req.headers["x-forwarded-proto"]) { + protocol = context.req.headers["x-forwarded-proto"]; + } + // Otherwise, check if the connection is encrypted (for https) + else if (context.req.connection.encrypted) { + protocol = "https"; + } + + formURL = protocol + "://" + formURL; + + console.log("Protocol:", protocol); + console.log("locale:", context.locale); + + const url = new URL(formURL); // base URL + + const params = new URLSearchParams(url.search); + params.append("locale", context.locale); + + url.search = params.toString(); + return { - props: { csrfToken: csrfToken, callbackUrl: formURL }, + props: { csrfToken: csrfToken, callbackUrl: url.toString() }, }; }