Add LDAP and OpenID Connect login options to the authentication system.

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/f6b3f7d6-52da-4746-abbf-fe5be5f16823.jpg
This commit is contained in:
alphaeusmote
2025-04-10 02:04:01 +00:00
2 changed files with 89 additions and 1 deletions
+32
View File
@@ -13,11 +13,14 @@ type AuthContextType = {
isLoading: boolean;
error: Error | null;
loginMutation: UseMutationResult<SelectUser, Error, LoginData>;
ldapLoginMutation: UseMutationResult<SelectUser, Error, LdapLoginData>;
initiateOidcLogin: () => void;
logoutMutation: UseMutationResult<void, Error, void>;
registerMutation: UseMutationResult<SelectUser, Error, InsertUser>;
};
type LoginData = Pick<InsertUser, "username" | "password">;
type LdapLoginData = Pick<InsertUser, "username" | "password">;
export const AuthContext = createContext<AuthContextType | null>(null);
@@ -74,6 +77,33 @@ export function AuthProvider({ children }: { children: ReactNode }) {
},
});
const ldapLoginMutation = useMutation({
mutationFn: async (credentials: LdapLoginData) => {
const res = await apiRequest("POST", "/api/auth/ldap", credentials);
return await res.json();
},
onSuccess: (user: SelectUser) => {
queryClient.setQueryData(["/api/user"], user);
toast({
title: "LDAP Login successful",
description: `Welcome back, ${user.username}!`,
});
},
onError: (error: Error) => {
toast({
title: "LDAP Login failed",
description: error.message,
variant: "destructive",
});
},
});
// Function to initiate OIDC login flow
const initiateOidcLogin = () => {
// OpenID Connect requires a redirect to the provider's login page
window.location.href = "/api/auth/oidc";
};
const logoutMutation = useMutation({
mutationFn: async () => {
await apiRequest("POST", "/api/logout");
@@ -101,6 +131,8 @@ export function AuthProvider({ children }: { children: ReactNode }) {
isLoading,
error,
loginMutation,
ldapLoginMutation,
initiateOidcLogin,
logoutMutation,
registerMutation,
}}
+57 -1
View File
@@ -206,10 +206,66 @@ export default function AuthPage() {
<Button
type="submit"
className="w-full"
disabled={auth.loginMutation.isPending}
disabled={auth.loginMutation.isPending || auth.ldapLoginMutation.isPending}
>
{auth.loginMutation.isPending ? "Logging in..." : "Log in"}
</Button>
<div className="relative my-5">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-gray-300"></span>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-2 bg-white text-gray-500">Or continue with</span>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<Button
type="button"
variant="outline"
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>
<Button
type="button"
variant="outline"
className="w-full"
disabled={auth.ldapLoginMutation.isPending || auth.loginMutation.isPending}
onClick={() => auth.initiateOidcLogin()}
>
OpenID Connect
</Button>
</div>
</form>
</Form>
</CardContent>