diff --git a/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts b/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts
new file mode 100644
index 000000000..6eb8ba863
--- /dev/null
+++ b/apps/scandic-web/app/[lang]/(live)/(protected)/logoutSafely/route.ts
@@ -0,0 +1,44 @@
+import { type NextRequest,NextResponse } from "next/server"
+import { AuthError } from "next-auth"
+
+import { logger } from "@scandic-hotels/common/logger"
+
+import { env } from "@/env/server"
+import { internalServerError } from "@/server/errors/next"
+import { getPublicURL } from "@/server/utils"
+
+import { signOut } from "@/auth"
+
+export async function GET(request: NextRequest) {
+ const publicURL = getPublicURL(request)
+ const redirectToSearchParamValue =
+ request.nextUrl.searchParams.get("redirectTo")
+ const redirectToFallback = "/"
+
+ let redirectTo: string = redirectToSearchParamValue || redirectToFallback
+
+ // Make relative URL to absolute URL
+ if (redirectTo.startsWith("/")) {
+ redirectTo = new URL(redirectTo, publicURL).href
+ }
+
+ try {
+ redirectTo = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${encodeURIComponent(redirectTo)}`
+ logger.debug(`[logoutSafely] final redirectUrl: ${redirectTo}`)
+
+ const redirectUrlObj = await signOut({
+ redirectTo,
+ redirect: false,
+ })
+
+ return NextResponse.redirect(redirectUrlObj.redirect)
+ } catch (error) {
+ if (error instanceof AuthError) {
+ logger.error("signOutSafelyAuthError", { signOutAuthError: error })
+ } else {
+ logger.error("signOutSafelyError", { signOutError: error })
+ }
+ }
+
+ return internalServerError()
+}
diff --git a/apps/scandic-web/app/[lang]/(live)/error/user-not-found/page.tsx b/apps/scandic-web/app/[lang]/(live)/error/user-not-found/page.tsx
new file mode 100644
index 000000000..42a99942a
--- /dev/null
+++ b/apps/scandic-web/app/[lang]/(live)/error/user-not-found/page.tsx
@@ -0,0 +1,14 @@
+import { UserNotFound } from "@/components/UserNotFound/UserNotFound"
+
+import type { Metadata } from "next"
+
+export const metadata: Metadata = {
+ robots: {
+ index: false,
+ follow: false,
+ },
+}
+
+export default function UserNotFoundPage() {
+ return
+}
diff --git a/apps/scandic-web/app/[lang]/(live)/layout.tsx b/apps/scandic-web/app/[lang]/(live)/layout.tsx
index 4f7c83769..197b6565d 100644
--- a/apps/scandic-web/app/[lang]/(live)/layout.tsx
+++ b/apps/scandic-web/app/[lang]/(live)/layout.tsx
@@ -24,6 +24,7 @@ import SitewideAlert from "@/components/SitewideAlert"
import { ToastHandler } from "@/components/TempDesignSystem/Toasts"
import AdobeSDKScript from "@/components/TrackingSDK/AdobeSDKScript"
import GTMScript from "@/components/TrackingSDK/GTMScript"
+import { UserExists } from "@/components/UserExists"
import { FontPreload } from "@/fonts/font-preloading"
import { getMessages } from "@/i18n"
import ClientIntlProvider from "@/i18n/Provider"
@@ -87,6 +88,7 @@ export default async function RootLayout(
+
diff --git a/apps/scandic-web/components/UserExists.tsx b/apps/scandic-web/components/UserExists.tsx
new file mode 100644
index 000000000..f8780d7fd
--- /dev/null
+++ b/apps/scandic-web/components/UserExists.tsx
@@ -0,0 +1,43 @@
+"use client"
+
+import { redirect } from "next/navigation"
+import { useSession } from "next-auth/react"
+
+import { trpc } from "@scandic-hotels/trpc/client"
+
+import { userNotFound } from "@/constants/routes/errorPages"
+import { logoutSafely } from "@/constants/routes/handleAuth"
+
+import useLang from "@/hooks/useLang"
+import { isValidClientSession } from "@/utils/clientSession"
+
+export function UserExists() {
+ const { data: session } = useSession()
+ const isUserLoggedIn = isValidClientSession(session)
+ const lang = useLang()
+
+ const { data, isLoading: isLoadingUser } = trpc.user.get.useQuery(undefined, {
+ enabled: isUserLoggedIn,
+ })
+
+ if (!isUserLoggedIn) {
+ return null
+ }
+
+ if (isLoadingUser) {
+ return null
+ }
+
+ if (data && "error" in data && data.error) {
+ switch (data.cause) {
+ case "notfound":
+ redirect(
+ `${logoutSafely[lang]}?redirectTo=${encodeURIComponent(userNotFound[lang])}`
+ )
+ default:
+ break
+ }
+ }
+
+ return null
+}
diff --git a/apps/scandic-web/components/UserNotFound/UserNotFound.module.css b/apps/scandic-web/components/UserNotFound/UserNotFound.module.css
new file mode 100644
index 000000000..2131b017b
--- /dev/null
+++ b/apps/scandic-web/components/UserNotFound/UserNotFound.module.css
@@ -0,0 +1,65 @@
+.container {
+ margin-top: 0;
+ background: var(--Main-Grey-White);
+ position: relative;
+ border-top: 50px solid var(--Main-Grey-White);
+ background-clip: content-box;
+}
+
+.content {
+ position: relative;
+ text-align: center;
+ box-sizing: content-box;
+ max-width: var(--max-width-page);
+ margin: 0 auto;
+ padding: 70px 30px;
+}
+
+.header {
+ font-family:
+ brandon text,
+ Arial,
+ Helvetica,
+ sans-serif;
+ font-size: 32px;
+ line-height: 1;
+ margin: 0;
+ text-transform: uppercase;
+ font-weight: 400;
+ color: #483729;
+}
+
+.pitch {
+ margin-top: 32px;
+ margin-bottom: 16px;
+}
+
+.text {
+ font-family:
+ Helvetica Neue,
+ Roboto,
+ Helvetica,
+ Arial,
+ sans-serif;
+ font-weight: 300;
+ line-height: normal;
+ text-transform: none;
+ font-size: 20px;
+ color: #333;
+}
+
+@media screen and (min-width: 740px) {
+ .content {
+ text-align: left;
+ }
+}
+
+@media screen and (min-width: 950px) {
+ .header {
+ font-size: 46px;
+ }
+
+ .text {
+ font-size: 24px;
+ }
+}
diff --git a/apps/scandic-web/components/UserNotFound/UserNotFound.tsx b/apps/scandic-web/components/UserNotFound/UserNotFound.tsx
new file mode 100644
index 000000000..d2ece9de4
--- /dev/null
+++ b/apps/scandic-web/components/UserNotFound/UserNotFound.tsx
@@ -0,0 +1,28 @@
+"use client"
+
+import { useIntl } from "react-intl"
+
+import styles from "./UserNotFound.module.css"
+
+export function UserNotFound() {
+ const intl = useIntl()
+
+ return (
+
+
+
+ {intl.formatMessage({
+ defaultMessage: "User not found",
+ })}
+
+
+
+ {intl.formatMessage({
+ defaultMessage: "Please try again or contact customer service!",
+ })}
+
+
+
+
+ )
+}
diff --git a/apps/scandic-web/constants/routes/errorPages.ts b/apps/scandic-web/constants/routes/errorPages.ts
new file mode 100644
index 000000000..6ec881849
--- /dev/null
+++ b/apps/scandic-web/constants/routes/errorPages.ts
@@ -0,0 +1,10 @@
+import type { LangRoute } from "@scandic-hotels/common/constants/routes/langRoute"
+
+export const userNotFound: LangRoute = {
+ en: "/en/error/user-not-found",
+ sv: "/sv/error/user-not-found",
+ no: "/no/error/user-not-found",
+ fi: "/fi/error/user-not-found",
+ da: "/da/error/user-not-found",
+ de: "/de/error/user-not-found",
+}
diff --git a/apps/scandic-web/constants/routes/handleAuth.js b/apps/scandic-web/constants/routes/handleAuth.js
index 507b481a5..faedc816e 100644
--- a/apps/scandic-web/constants/routes/handleAuth.js
+++ b/apps/scandic-web/constants/routes/handleAuth.js
@@ -32,6 +32,15 @@ export const logout = {
sv: "/sv/logga-ut",
}
+export const logoutSafely = {
+ da: "/da/logoutSafely",
+ de: "/de/logoutSafely",
+ en: "/en/logoutSafely",
+ fi: "/fi/logoutSafely",
+ no: "/no/logoutSafely",
+ sv: "/sv/logoutSafely",
+}
+
/** @type {import('@scandic-hotels/common/constants/routes/langRoute').LangRoute} */
export const logoutUnLocalized = {
da: "/da/logout",
@@ -58,4 +67,5 @@ export const handleAuth = [
...Object.values(verifymagiclink),
...Object.values(loginUnLocalized),
...Object.values(logoutUnLocalized),
+ ...Object.values(logoutSafely),
]
diff --git a/apps/scandic-web/middleware.ts b/apps/scandic-web/middleware.ts
index f7d915bc6..be8930342 100644
--- a/apps/scandic-web/middleware.ts
+++ b/apps/scandic-web/middleware.ts
@@ -12,6 +12,7 @@ import * as currentWebLogin from "@/middlewares/currentWebLogin"
import * as currentWebLoginEmail from "@/middlewares/currentWebLoginEmail"
import * as currentWebLogout from "@/middlewares/currentWebLogout"
import * as dateQueryParams from "@/middlewares/dateQueryParams"
+import * as errorPages from "@/middlewares/errorPages"
import * as familyAndFriends from "@/middlewares/familyAndFriends"
import * as handleAuth from "@/middlewares/handleAuth"
import * as handleDTMC from "@/middlewares/handleDTMC"
@@ -67,6 +68,7 @@ export const middleware: NextMiddleware = async (request, event) => {
dateQueryParams,
legacySearchParams,
bookingFlow,
+ errorPages,
familyAndFriends,
sasXScandic,
cmsContent,
diff --git a/apps/scandic-web/middlewares/errorPages.ts b/apps/scandic-web/middlewares/errorPages.ts
new file mode 100644
index 000000000..49044f0c9
--- /dev/null
+++ b/apps/scandic-web/middlewares/errorPages.ts
@@ -0,0 +1,20 @@
+import { type NextMiddleware, NextResponse } from "next/server"
+
+import { getDefaultRequestHeaders } from "./utils"
+
+import type { MiddlewareMatcher } from "@/types/middleware"
+
+export const middleware: NextMiddleware = async (request) => {
+ const headers = getDefaultRequestHeaders(request)
+ headers.set("X-Robots-Tag", "noindex, nofollow")
+
+ return NextResponse.next({
+ request: {
+ headers,
+ },
+ })
+}
+
+export const matcher: MiddlewareMatcher = (request) => {
+ return !!request.nextUrl.pathname.match(/^\/(da|de|en|fi|no|sv)\/(error)/)
+}