Only allow single NextAuth provider, Login middleware updates

This commit is contained in:
Darren Clarke 2024-09-27 14:52:44 +02:00
parent f86ce1e835
commit 8736b576a7
6 changed files with 111 additions and 99 deletions

View file

@ -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;

View file

@ -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: [
{

View file

@ -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<LoginProps> = ({ 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<LoginProps> = ({ session }) => {
},
};
useEffect(() => {
const fetchProviders = async () => {
const providers = await getProviders();
setProvider(Object.keys(providers)?.pop());
};
fetchProviders();
}, []);
return (
<Box sx={{ backgroundColor: darkGray, height: "100vh" }}>
<Container maxWidth="md" sx={{ p: 10 }}>
@ -142,6 +151,7 @@ export const Login: FC<LoginProps> = ({ session }) => {
</Box>
</Grid>
) : null}
{provider === "google" && (
<Grid item sx={{ width: "100%" }}>
<IconButton
sx={buttonStyles}
@ -155,6 +165,8 @@ export const Login: FC<LoginProps> = ({ session }) => {
Sign in with Google
</IconButton>
</Grid>
)}
{provider === "apple" && (
<Grid item sx={{ width: "100%" }}>
<IconButton
aria-label="Sign in with Apple"
@ -169,19 +181,9 @@ export const Login: FC<LoginProps> = ({ session }) => {
Sign in with Apple
</IconButton>
</Grid>
<Grid>
<Typography
variant="body1"
sx={{
fontSize: 18,
color: white,
textAlign: "center",
mt: 3,
}}
>
or
</Typography>
</Grid>
)}
{provider === "credentials" && (
<Grid item container spacing={3}>
<Grid item sx={{ width: "100%" }}>
<TextField
value={email}
@ -221,6 +223,8 @@ export const Login: FC<LoginProps> = ({ session }) => {
</IconButton>
</Grid>
</Grid>
)}
</Grid>
</Container>
) : null}
{session ? (

View file

@ -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 }) => {

View file

@ -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;
}

View file

@ -1,5 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
poweredByHeader: false,
transpilePackages: [
"@link-stack/leafcutter-ui",
"@link-stack/opensearch-common",