diff --git a/.github/workflows/pr-review-client-deploy.yml b/.github/workflows/pr-review-client-deploy.yml index 372a119beb..b4c1d410c4 100644 --- a/.github/workflows/pr-review-client-deploy.yml +++ b/.github/workflows/pr-review-client-deploy.yml @@ -141,7 +141,8 @@ jobs: echo "URL=$URL" >> $GITHUB_ENV aws lambda update-function-configuration \ - --function-name $FUNCTION_NAME-$PR_NUMBER > /dev/null 2>&1 + --function-name $FUNCTION_NAME-$PR_NUMBER \ + --environment "Variables={NEXTAUTH_URL=$URL}" > /dev/null 2>&1 aws logs create-log-group --log-group-name /aws/lambda/$FUNCTION_NAME-$PR_NUMBER > /dev/null 2>&1 aws logs put-retention-policy --log-group-name /aws/lambda/$FUNCTION_NAME-$PR_NUMBER --retention-in-days 14 > /dev/null 2>&1 diff --git a/Dockerfile.pr b/Dockerfile.pr index 3c6a062fa3..f2be62b1aa 100755 --- a/Dockerfile.pr +++ b/Dockerfile.pr @@ -53,6 +53,9 @@ ENV AWS_LWA_ENABLE_COMPRESSION=true ENV HOSTNAME=localhost ENV PORT=3000 +ENV ZITADEL_CLIENT_ID=343363438019420754 +ENV ZITADEL_URL=https://auth.forms-staging.cdssandbox.xyz + # Use the LAMBDA_ENV environment variable to determine if the app is running in a Lambda environment # Enables memory caching for the prerendering of pages ENV LAMBDA_ENV=1 diff --git a/app/(gcforms)/[locale]/(user authentication)/auth/login/pilot/Login.tsx b/app/(gcforms)/[locale]/(user authentication)/auth/login/pilot/Login.tsx new file mode 100644 index 0000000000..f0798149e4 --- /dev/null +++ b/app/(gcforms)/[locale]/(user authentication)/auth/login/pilot/Login.tsx @@ -0,0 +1,29 @@ +"use client"; +import { signIn } from "next-auth/react"; +import { useSession } from "next-auth/react"; + +export const Login = ({ language = "en" }) => { + const { data, status } = useSession(); + + if (status === "loading") { + return; + } + + if (status === "authenticated") { + return
{`Hello ${data.user?.name}`}
; + } + return ( +
{ + signIn("gcForms", { redirectTo: `/${language}/auth/policy` }); + }} + > + +
+ ); +}; diff --git a/app/(gcforms)/[locale]/(user authentication)/auth/login/pilot/page.tsx b/app/(gcforms)/[locale]/(user authentication)/auth/login/pilot/page.tsx new file mode 100644 index 0000000000..631af0fe74 --- /dev/null +++ b/app/(gcforms)/[locale]/(user authentication)/auth/login/pilot/page.tsx @@ -0,0 +1,35 @@ +import { serverTranslation } from "@i18n"; +import { Metadata } from "next"; +import { Login } from "./Login"; +import { authCheckAndThrow } from "@lib/actions"; +import { redirect } from "next/navigation"; + +export async function generateMetadata(props: { + params: Promise<{ locale: string }>; +}): Promise { + const params = await props.params; + + const { locale } = params; + + const { t } = await serverTranslation(["login"], { lang: locale }); + return { + title: t("title"), + }; +} + +export default async function Page(props: { params: Promise<{ locale: string }> }) { + const params = await props.params; + + const { locale } = params; + + const { session } = await authCheckAndThrow().catch(() => ({ session: null })); + if (session) { + redirect(`/${locale}/forms`); + } + + return ( +
+ +
+ ); +} diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index f54c8bbcd3..46c4b9be96 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -1,19 +1,34 @@ import { GET as NextGET, POST as NextPOST } from "@lib/auth"; import { NextRequest, NextResponse } from "next/server"; +import { logMessage } from "@root/lib/logger"; // Only allow methods and paths that the application uses for Authjs const GET = async (req: NextRequest) => { - if (["/api/auth/session", "/api/auth/csrf"].includes(req.nextUrl.pathname)) { + if ( + [ + "/api/auth/error", + "/api/auth/session", + "/api/auth/csrf", + "/api/auth/providers", + "/api/auth/callback/gcForms", + ].includes(req.nextUrl.pathname) + ) { return NextGET(req); } + logMessage.error(`Attempted GET URL: ${req.nextUrl.pathname}`); return NextResponse.json({ error: "Bad Request" }, { status: 400 }); }; const POST = async (req: NextRequest) => { - if (["/api/auth/session", "/api/auth/signout"].includes(req.nextUrl.pathname)) { + if ( + ["/api/auth/session", "/api/auth/signout", "/api/auth/signin/gcForms"].includes( + req.nextUrl.pathname + ) + ) { return NextPOST(req); } + logMessage.error(`Attempted POST URL: ${req.nextUrl.pathname}`); return NextResponse.json({ error: "Bad Request" }, { status: 400 }); }; diff --git a/components/clientComponents/globals/Header/Header.tsx b/components/clientComponents/globals/Header/Header.tsx index cea6745f90..e888d82800 100644 --- a/components/clientComponents/globals/Header/Header.tsx +++ b/components/clientComponents/globals/Header/Header.tsx @@ -13,7 +13,6 @@ import Markdown from "markdown-to-jsx"; import { useFeatureFlags } from "@lib/hooks/useFeatureFlags"; import { FeatureFlags } from "@lib/cache/types"; import { SkipLink } from "../SkipLink"; - type HeaderParams = { context?: "admin" | "formBuilder" | "default"; className?: string; diff --git a/lib/auth/nextAuth.ts b/lib/auth/nextAuth.ts index 6ac87faa50..dcf6dd624a 100644 --- a/lib/auth/nextAuth.ts +++ b/lib/auth/nextAuth.ts @@ -12,7 +12,6 @@ import { activeStatusCheck, activeStatusUpdate } from "@lib/cache/userActiveStat import { JWT } from "next-auth/jwt"; import { cache } from "react"; import { headers } from "next/headers"; -// import ZitadelProvider from "next-auth/providers/zitadel"; /** * Checks the active status of a user using a cache strategy @@ -50,23 +49,21 @@ const { signOut, } = NextAuth({ providers: [ - // Keep this commented out for now, as we are not using Zitadel for authentication within the app - // ZitadelProvider({ - // issuer: process.env.ZITADEL_ISSUER, - // clientId: process.env.ZITADEL_CLIENT_ID, - // checks: ["pkce"], - // client: { - // token_endpoint_auth_method: "none", - // }, - // allowDangerousEmailAccountLinking: true, - // async profile(profile) { - // return { - // id: profile.sub, - // name: profile.name, - // email: profile.email, - // }; - // }, - // }), + { + id: "gcForms", // signIn("my-provider") and will be part of the callback URL + name: "GC Forms", // optional, used on the default login page as the button text. + type: "oidc", + issuer: process.env.ZITADEL_URL, + clientId: process.env.ZITADEL_CLIENT_ID, + checks: ["pkce", "state"], + client: { token_endpoint_auth_method: "none" }, + allowDangerousEmailAccountLinking: true, + authorization: { + params: { + scope: "openid email profile", + }, + }, + }, CredentialsProvider({ id: "mfa", name: "MultiFactorAuth", @@ -137,7 +134,6 @@ const { }, // Elastic Load Balancer safely sets the host header and ignores the incoming request headers trustHost: true, - debug: process.env.NODE_ENV !== "production", logger: { error(error) { if (!(error instanceof CredentialsSignin)) { @@ -148,6 +144,11 @@ const { warn(code) { logMessage.warn(`NextAuth warning - Code: ${code}`); }, + debug(code, ...message) { + // TODO.. switch back to debug + logMessage.info(code); + logMessage.info(message); + }, }, adapter: PrismaAdapter(prisma), diff --git a/scripts/pr-review-entrypoint.sh b/scripts/pr-review-entrypoint.sh index 705bad6e9f..b78cc0f65f 100755 --- a/scripts/pr-review-entrypoint.sh +++ b/scripts/pr-review-entrypoint.sh @@ -35,7 +35,7 @@ load_non_existing_envs() { key="${line%%=*}" value="${line#*=}" - if [ -z "$(var_expand "$key")" ] && [ $key != "NEXTAUTH_URL" ]; then # Check if environment variable doesn't exist + if [ -z "$(var_expand "$key")" ] && [ $key != "NEXTAUTH_URL" ] && [ $key != "ZITADEL_URL" ]; then # Check if environment variable doesn't exist export "${key}=${value}" fi done < $TMP_ENV_FILE