From 8736b576a7f6085c76fd3b09932c320c0f4d4bdd Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 27 Sep 2024 14:52:44 +0200 Subject: [PATCH] Only allow single NextAuth provider, Login middleware updates --- apps/bridge-frontend/next.config.js | 1 + apps/leafcutter/next.config.js | 9 +- .../app/(login)/login/_components/Login.tsx | 164 +++++++++--------- apps/link/app/_lib/authentication.ts | 28 ++- apps/link/middleware.ts | 7 +- apps/link/next.config.js | 1 + 6 files changed, 111 insertions(+), 99 deletions(-) diff --git a/apps/bridge-frontend/next.config.js b/apps/bridge-frontend/next.config.js index 73f0796..1a7c807 100644 --- a/apps/bridge-frontend/next.config.js +++ b/apps/bridge-frontend/next.config.js @@ -1,6 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ["@link-stack/ui", "@link-stack/bridge-common", "@link-stack/bridge-ui"], + poweredByHeader: false, }; export default nextConfig; diff --git a/apps/leafcutter/next.config.js b/apps/leafcutter/next.config.js index 7b953ae..e8cb203 100644 --- a/apps/leafcutter/next.config.js +++ b/apps/leafcutter/next.config.js @@ -1,16 +1,9 @@ -const ContentSecurityPolicy = ` - default-src 'self'; - script-src 'self'; - child-src example.com; - style-src 'self' example.com; - font-src 'self'; -`; - module.exports = { transpilePackages: ["@link-stack/leafcutter-ui", "@link-stack/opensearch-common"], experimental: { missingSuspenseWithCSRBailout: false, }, + poweredByHeader: false, rewrites: async () => ({ fallback: [ { diff --git a/apps/link/app/(login)/login/_components/Login.tsx b/apps/link/app/(login)/login/_components/Login.tsx index 0a7f083..a1f57cb 100644 --- a/apps/link/app/(login)/login/_components/Login.tsx +++ b/apps/link/app/(login)/login/_components/Login.tsx @@ -1,6 +1,6 @@ "use client"; -import { FC, useState } from "react"; +import { FC, useState, useEffect } from "react"; import { Box, Grid, @@ -14,7 +14,7 @@ import { Google as GoogleIcon, Key as KeyIcon, } from "@mui/icons-material"; -import { signIn } from "next-auth/react"; +import { signIn, getProviders } from "next-auth/react"; import Image from "next/image"; import LinkLogo from "public/link-logo-small.png"; import { colors, fonts } from "@link-stack/ui"; @@ -29,6 +29,7 @@ export const Login: FC = ({ session }) => { typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; + const [provider, setProvider] = useState(undefined); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const params = useSearchParams(); @@ -63,6 +64,14 @@ export const Login: FC = ({ session }) => { }, }; + useEffect(() => { + const fetchProviders = async () => { + const providers = await getProviders(); + setProvider(Object.keys(providers)?.pop()); + }; + fetchProviders(); + }, []); + return ( @@ -142,84 +151,79 @@ export const Login: FC = ({ session }) => { ) : null} - - - signIn("google", { - callbackUrl: `${origin}`, - }) - } - > - - Sign in with Google - - - - - signIn("apple", { - callbackUrl: `${window.location.origin}`, - }) - } - > - - Sign in with Apple - - - - - ⸺ or ⸺ - - - - setEmail(e.target.value)} - label="Email" - variant="filled" - size="small" - fullWidth - sx={{ ...fieldStyles, backgroundColor: white }} - /> - - - setPassword(e.target.value)} - label="Password" - variant="filled" - size="small" - fullWidth - sx={{ backgroundColor: white }} - type="password" - /> - - - - signIn("credentials", { - email, - password, - callbackUrl: `${origin}/setup`, - }) - } - > - - Sign in with Zammad credentials - - + {provider === "google" && ( + + + signIn("google", { + callbackUrl: `${origin}`, + }) + } + > + + Sign in with Google + + + )} + {provider === "apple" && ( + + + signIn("apple", { + callbackUrl: `${window.location.origin}`, + }) + } + > + + Sign in with Apple + + + )} + {provider === "credentials" && ( + + + setEmail(e.target.value)} + label="Email" + variant="filled" + size="small" + fullWidth + sx={{ ...fieldStyles, backgroundColor: white }} + /> + + + setPassword(e.target.value)} + label="Password" + variant="filled" + size="small" + fullWidth + sx={{ backgroundColor: white }} + type="password" + /> + + + + signIn("credentials", { + email, + password, + callbackUrl: `${origin}/setup`, + }) + } + > + + Sign in with Zammad credentials + + + + )} ) : null} diff --git a/apps/link/app/_lib/authentication.ts b/apps/link/app/_lib/authentication.ts index 8029a06..79618ed 100644 --- a/apps/link/app/_lib/authentication.ts +++ b/apps/link/app/_lib/authentication.ts @@ -66,21 +66,24 @@ const login = async (email: string, password: string) => { } }; -export const authOptions: NextAuthOptions = { - pages: { - signIn: "/login", - error: "/login", - signOut: "/logout", - }, - providers: [ +const providers = []; + +if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) { + providers.push( Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), + ); +} else if (process.env.APPLE_CLIENT_ID && process.env.APPLE_CLIENT_SECRET) { + providers.push( Apple({ clientId: process.env.APPLE_CLIENT_ID, clientSecret: process.env.APPLE_CLIENT_SECRET, }), + ); +} else { + providers.push( Credentials({ name: "Zammad", credentials: { @@ -96,7 +99,16 @@ export const authOptions: NextAuthOptions = { } }, }), - ], + ); +} + +export const authOptions: NextAuthOptions = { + pages: { + signIn: "/login", + error: "/login", + signOut: "/logout", + }, + providers, secret: process.env.NEXTAUTH_SECRET, callbacks: { signIn: async ({ user }) => { diff --git a/apps/link/middleware.ts b/apps/link/middleware.ts index d01fd88..6926d0c 100644 --- a/apps/link/middleware.ts +++ b/apps/link/middleware.ts @@ -85,9 +85,6 @@ const checkRewrites = async (request: NextRequestWithAuth) => { }; export default withAuth(checkRewrites, { - pages: { - signIn: `/login`, - }, callbacks: { authorized: ({ token, req }) => { if (process.env.SETUP_MODE === "true") { @@ -97,6 +94,10 @@ export default withAuth(checkRewrites, { const path = req.nextUrl.pathname; const roles: any = token?.roles ?? []; + if (path.startsWith("/login")) { + return true; + } + if (path.startsWith("/admin") && !roles.includes("admin")) { return false; } diff --git a/apps/link/next.config.js b/apps/link/next.config.js index a3f1c8f..e9fa845 100644 --- a/apps/link/next.config.js +++ b/apps/link/next.config.js @@ -1,5 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + poweredByHeader: false, transpilePackages: [ "@link-stack/leafcutter-ui", "@link-stack/opensearch-common",