mirror of
https://github.com/freedbygrace/ActiveDirectoryManager.git
synced 2026-08-27 19:17:07 +00:00
Improve authentication by conditionally rendering LDAP and OIDC login options and fetching auth provider configurations.
Replit-Commit-Author: Agent Replit-Commit-Session-Id: 705f2157-ef97-4fbd-89e4-8c7f2ecaea90 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7ed01c5f-a82d-405a-b728-b2e3d127c60c/4f13eaa5-e266-4ec8-8273-939cfc3ca326.jpg
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { createContext, ReactNode, useContext } from "react";
|
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
useQuery,
|
useQuery,
|
||||||
useMutation,
|
useMutation,
|
||||||
@@ -17,6 +17,8 @@ type AuthContextType = {
|
|||||||
initiateOidcLogin: () => void;
|
initiateOidcLogin: () => void;
|
||||||
logoutMutation: UseMutationResult<void, Error, void>;
|
logoutMutation: UseMutationResult<void, Error, void>;
|
||||||
registerMutation: UseMutationResult<SelectUser, Error, InsertUser>;
|
registerMutation: UseMutationResult<SelectUser, Error, InsertUser>;
|
||||||
|
ldapEnabled: boolean;
|
||||||
|
oidcEnabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type LoginData = Pick<InsertUser, "username" | "password">;
|
type LoginData = Pick<InsertUser, "username" | "password">;
|
||||||
@@ -26,6 +28,9 @@ export const AuthContext = createContext<AuthContextType | null>(null);
|
|||||||
|
|
||||||
export function AuthProvider({ children }: { children: ReactNode }) {
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const [ldapEnabled, setLdapEnabled] = useState(false);
|
||||||
|
const [oidcEnabled, setOidcEnabled] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: user,
|
data: user,
|
||||||
error,
|
error,
|
||||||
@@ -34,6 +39,25 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
queryKey: ["/api/user"],
|
queryKey: ["/api/user"],
|
||||||
queryFn: getQueryFn({ on401: "returnNull" }),
|
queryFn: getQueryFn({ on401: "returnNull" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get auth provider configurations
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchAuthProviders = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/auth/providers');
|
||||||
|
if (response.ok) {
|
||||||
|
const providers = await response.json();
|
||||||
|
setLdapEnabled(providers.ldap?.enabled || false);
|
||||||
|
setOidcEnabled(providers.oidc?.enabled || false);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Silently fail - default is disabled
|
||||||
|
console.error('Failed to fetch auth providers:', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchAuthProviders();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const loginMutation = useMutation({
|
const loginMutation = useMutation({
|
||||||
mutationFn: async (credentials: LoginData) => {
|
mutationFn: async (credentials: LoginData) => {
|
||||||
@@ -133,6 +157,8 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
initiateOidcLogin,
|
initiateOidcLogin,
|
||||||
logoutMutation,
|
logoutMutation,
|
||||||
registerMutation,
|
registerMutation,
|
||||||
|
ldapEnabled,
|
||||||
|
oidcEnabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -234,61 +234,70 @@ export default function AuthPage() {
|
|||||||
{auth.loginMutation.isPending ? "Logging in..." : "Log in"}
|
{auth.loginMutation.isPending ? "Logging in..." : "Log in"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div className="relative my-5">
|
{/* Only show additional login methods when they are configured */}
|
||||||
<div className="absolute inset-0 flex items-center">
|
{(auth.ldapEnabled || auth.oidcEnabled) && (
|
||||||
<span className="w-full border-t border-gray-300"></span>
|
<>
|
||||||
</div>
|
<div className="relative my-5">
|
||||||
<div className="relative flex justify-center text-sm">
|
<div className="absolute inset-0 flex items-center">
|
||||||
<span className="px-2 bg-white text-gray-500">Or continue with</span>
|
<span className="w-full border-t border-gray-300"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="relative flex justify-center text-sm">
|
||||||
|
<span className="px-2 bg-white text-gray-500">Or continue with</span>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
</div>
|
||||||
<Button
|
</div>
|
||||||
type="button"
|
|
||||||
variant="outline"
|
<div className="grid grid-cols-2 gap-3">
|
||||||
className="w-full"
|
{auth.ldapEnabled && (
|
||||||
disabled={auth.ldapLoginMutation.isPending || auth.loginMutation.isPending}
|
<Button
|
||||||
onClick={() => {
|
type="button"
|
||||||
const username = loginForm.getValues("username");
|
variant="outline"
|
||||||
const password = loginForm.getValues("password");
|
className="w-full"
|
||||||
|
disabled={auth.ldapLoginMutation.isPending || auth.loginMutation.isPending}
|
||||||
|
onClick={() => {
|
||||||
|
const username = loginForm.getValues("username");
|
||||||
|
const password = loginForm.getValues("password");
|
||||||
|
|
||||||
|
// Validate the fields
|
||||||
|
if (!username || !password) {
|
||||||
|
loginForm.setError("username", {
|
||||||
|
type: "manual",
|
||||||
|
message: !username ? "Username is required" : undefined
|
||||||
|
});
|
||||||
|
loginForm.setError("password", {
|
||||||
|
type: "manual",
|
||||||
|
message: !password ? "Password is required" : undefined
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth.ldapLoginMutation.mutate(
|
||||||
|
{ username, password },
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
navigate("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{auth.ldapLoginMutation.isPending ? "Authenticating..." : "LDAP Login"}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
// Validate the fields
|
{auth.oidcEnabled && (
|
||||||
if (!username || !password) {
|
<Button
|
||||||
loginForm.setError("username", {
|
type="button"
|
||||||
type: "manual",
|
variant="outline"
|
||||||
message: !username ? "Username is required" : undefined
|
className={`w-full ${!auth.ldapEnabled ? "col-span-2" : ""}`}
|
||||||
});
|
disabled={auth.ldapLoginMutation.isPending || auth.loginMutation.isPending}
|
||||||
loginForm.setError("password", {
|
onClick={() => auth.initiateOidcLogin()}
|
||||||
type: "manual",
|
>
|
||||||
message: !password ? "Password is required" : undefined
|
OpenID Connect
|
||||||
});
|
</Button>
|
||||||
return;
|
)}
|
||||||
}
|
</div>
|
||||||
|
</>
|
||||||
auth.ldapLoginMutation.mutate(
|
)}
|
||||||
{ username, password },
|
|
||||||
{
|
|
||||||
onSuccess: () => {
|
|
||||||
navigate("/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{auth.ldapLoginMutation.isPending ? "Authenticating..." : "LDAP Login"}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
className="w-full"
|
|
||||||
disabled={auth.ldapLoginMutation.isPending || auth.loginMutation.isPending}
|
|
||||||
onClick={() => auth.initiateOidcLogin()}
|
|
||||||
>
|
|
||||||
OpenID Connect
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user