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,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,84 +151,79 @@ export const Login: FC<LoginProps> = ({ session }) => {
</Box>
</Grid>
) : null}
<Grid item sx={{ width: "100%" }}>
<IconButton
sx={buttonStyles}
onClick={() =>
signIn("google", {
callbackUrl: `${origin}`,
})
}
>
<GoogleIcon sx={{ mr: 1 }} />
Sign in with Google
</IconButton>
</Grid>
<Grid item sx={{ width: "100%" }}>
<IconButton
aria-label="Sign in with Apple"
sx={buttonStyles}
onClick={() =>
signIn("apple", {
callbackUrl: `${window.location.origin}`,
})
}
>
<AppleIcon sx={{ mr: 1 }} />
Sign in with Apple
</IconButton>
</Grid>
<Grid>
<Typography
variant="body1"
sx={{
fontSize: 18,
color: white,
textAlign: "center",
mt: 3,
}}
>
or
</Typography>
</Grid>
<Grid item sx={{ width: "100%" }}>
<TextField
value={email}
onChange={(e) => setEmail(e.target.value)}
label="Email"
variant="filled"
size="small"
fullWidth
sx={{ ...fieldStyles, backgroundColor: white }}
/>
</Grid>
<Grid item sx={{ ...fieldStyles, width: "100%" }}>
<TextField
value={password}
onChange={(e) => setPassword(e.target.value)}
label="Password"
variant="filled"
size="small"
fullWidth
sx={{ backgroundColor: white }}
type="password"
/>
</Grid>
<Grid item sx={{ width: "100%" }}>
<IconButton
sx={buttonStyles}
onClick={() =>
signIn("credentials", {
email,
password,
callbackUrl: `${origin}/setup`,
})
}
>
<KeyIcon sx={{ mr: 1 }} />
Sign in with Zammad credentials
</IconButton>
</Grid>
{provider === "google" && (
<Grid item sx={{ width: "100%" }}>
<IconButton
sx={buttonStyles}
onClick={() =>
signIn("google", {
callbackUrl: `${origin}`,
})
}
>
<GoogleIcon sx={{ mr: 1 }} />
Sign in with Google
</IconButton>
</Grid>
)}
{provider === "apple" && (
<Grid item sx={{ width: "100%" }}>
<IconButton
aria-label="Sign in with Apple"
sx={buttonStyles}
onClick={() =>
signIn("apple", {
callbackUrl: `${window.location.origin}`,
})
}
>
<AppleIcon sx={{ mr: 1 }} />
Sign in with Apple
</IconButton>
</Grid>
)}
{provider === "credentials" && (
<Grid item container spacing={3}>
<Grid item sx={{ width: "100%" }}>
<TextField
value={email}
onChange={(e) => setEmail(e.target.value)}
label="Email"
variant="filled"
size="small"
fullWidth
sx={{ ...fieldStyles, backgroundColor: white }}
/>
</Grid>
<Grid item sx={{ ...fieldStyles, width: "100%" }}>
<TextField
value={password}
onChange={(e) => setPassword(e.target.value)}
label="Password"
variant="filled"
size="small"
fullWidth
sx={{ backgroundColor: white }}
type="password"
/>
</Grid>
<Grid item sx={{ width: "100%" }}>
<IconButton
sx={buttonStyles}
onClick={() =>
signIn("credentials", {
email,
password,
callbackUrl: `${origin}/setup`,
})
}
>
<KeyIcon sx={{ mr: 1 }} />
Sign in with Zammad credentials
</IconButton>
</Grid>
</Grid>
)}
</Grid>
</Container>
) : null}

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