Add Authelia as centralized authentication and OIDC provider
Authelia runs as a managed native service on Wild Central, providing two integration patterns for network services: - Forward-auth via HAProxy for apps without native SSO (Lua auth-request script intercepts requests, redirects unauthenticated users to login portal) - OIDC provider for apps with native support (Gitea, Grafana, etc.) Backend: new internal/authelia/ package with service manager, config generation, file-based user management (argon2id), and OIDC client management. API endpoints for status, config, users CRUD, and OIDC clients CRUD. HAProxy: config generator extended with lua-load, auth-request directives, and Authelia backend. Auth directives scoped to session cookie domain — only subdomains of the auth portal's parent are eligible for forward-auth. Frontend: Authentication page with enable/disable, user management, OIDC client management (add/edit/delete), and protected domains toggles. Advanced subsystem page for raw config view. Dashboard service card and sidebar entries.
This commit is contained in:
90
web/src/hooks/useAuthelia.ts
Normal file
90
web/src/hooks/useAuthelia.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { autheliaApi } from '../services/api/authelia';
|
||||
import type { CreateUserRequest, UpdateUserRequest, CreateOIDCClientRequest, UpdateOIDCClientRequest } from '../services/api/authelia';
|
||||
|
||||
export function useAuthelia() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const statusQuery = useQuery({
|
||||
queryKey: ['authelia', 'status'],
|
||||
queryFn: () => autheliaApi.getStatus(),
|
||||
staleTime: 10000,
|
||||
});
|
||||
|
||||
const usersQuery = useQuery({
|
||||
queryKey: ['authelia', 'users'],
|
||||
queryFn: () => autheliaApi.listUsers(),
|
||||
enabled: !!statusQuery.data?.enabled,
|
||||
});
|
||||
|
||||
const oidcClientsQuery = useQuery({
|
||||
queryKey: ['authelia', 'oidc', 'clients'],
|
||||
queryFn: () => autheliaApi.listOIDCClients(),
|
||||
enabled: !!statusQuery.data?.active,
|
||||
});
|
||||
|
||||
const invalidateAll = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['authelia'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['central', 'status'] });
|
||||
};
|
||||
|
||||
const updateConfigMutation = useMutation({
|
||||
mutationFn: (data: { enabled?: boolean; domain?: string; defaultPolicy?: string }) =>
|
||||
autheliaApi.updateConfig(data),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const restartMutation = useMutation({
|
||||
mutationFn: () => autheliaApi.restart(),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const createUserMutation = useMutation({
|
||||
mutationFn: (req: CreateUserRequest) => autheliaApi.createUser(req),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const updateUserMutation = useMutation({
|
||||
mutationFn: ({ username, ...req }: UpdateUserRequest & { username: string }) =>
|
||||
autheliaApi.updateUser(username, req),
|
||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['authelia', 'users'] }),
|
||||
});
|
||||
|
||||
const deleteUserMutation = useMutation({
|
||||
mutationFn: (username: string) => autheliaApi.deleteUser(username),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const createOIDCClientMutation = useMutation({
|
||||
mutationFn: (req: CreateOIDCClientRequest) => autheliaApi.createOIDCClient(req),
|
||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['authelia', 'oidc', 'clients'] }),
|
||||
});
|
||||
|
||||
const updateOIDCClientMutation = useMutation({
|
||||
mutationFn: ({ clientId, ...req }: UpdateOIDCClientRequest & { clientId: string }) =>
|
||||
autheliaApi.updateOIDCClient(clientId, req),
|
||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['authelia', 'oidc', 'clients'] }),
|
||||
});
|
||||
|
||||
const deleteOIDCClientMutation = useMutation({
|
||||
mutationFn: (clientId: string) => autheliaApi.deleteOIDCClient(clientId),
|
||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['authelia', 'oidc', 'clients'] }),
|
||||
});
|
||||
|
||||
return {
|
||||
status: statusQuery.data,
|
||||
isLoadingStatus: statusQuery.isLoading,
|
||||
users: usersQuery.data?.users ?? [],
|
||||
isLoadingUsers: usersQuery.isLoading,
|
||||
oidcClients: oidcClientsQuery.data?.clients ?? [],
|
||||
isLoadingClients: oidcClientsQuery.isLoading,
|
||||
updateConfig: updateConfigMutation,
|
||||
restart: restartMutation,
|
||||
createUser: createUserMutation,
|
||||
updateUser: updateUserMutation,
|
||||
deleteUser: deleteUserMutation,
|
||||
createOIDCClient: createOIDCClientMutation,
|
||||
updateOIDCClient: updateOIDCClientMutation,
|
||||
deleteOIDCClient: deleteOIDCClientMutation,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user