Files
claudetools/projects/msp-tools/guru-rmm/dashboard/src/hooks/useAuth.tsx
azcomputerguru 65086f4407 fix(security): Implement Phase 1 critical security fixes
CORS:
- Restrict CORS to DASHBOARD_URL environment variable
- Default to production dashboard domain

Authentication:
- Add AuthUser requirement to all agent management endpoints
- Add AuthUser requirement to all command endpoints
- Add AuthUser requirement to all metrics endpoints
- Add audit logging for command execution (user_id tracked)

Agent Security:
- Replace Unicode characters with ASCII markers [OK]/[ERROR]/[WARNING]
- Add certificate pinning for update downloads (allowlist domains)
- Fix insecure temp file creation (use /var/run/gururmm with 0700 perms)
- Fix rollback script backgrounding (use setsid instead of literal &)

Dashboard Security:
- Move token storage from localStorage to sessionStorage
- Add proper TypeScript types (remove 'any' from error handlers)
- Centralize token management functions

Legacy Agent:
- Add -AllowInsecureTLS parameter (opt-in required)
- Add Windows Event Log audit trail when insecure mode used
- Update documentation with security warnings

Closes: Phase 1 items in issue #1

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:16:24 -07:00

72 lines
2.0 KiB
TypeScript

import { createContext, useContext, useState, useEffect, ReactNode } from "react";
import { User, authApi, getToken, clearToken } from "../api/client";
interface AuthContextType {
user: User | null;
isAuthenticated: boolean;
isLoading: boolean;
login: (email: string, password: string) => Promise<void>;
register: (email: string, password: string, name?: string) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | null>(null);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);
// Check authentication status on mount
useEffect(() => {
const checkAuth = async () => {
const token = getToken();
if (token) {
try {
const res = await authApi.me();
setUser(res.data);
} catch {
// Token is invalid or expired, clear it
clearToken();
setUser(null);
}
}
setIsLoading(false);
};
checkAuth();
}, []);
const login = async (email: string, password: string) => {
const response = await authApi.login({ email, password });
// Token is automatically stored by authApi.login
setUser(response.user);
};
const register = async (email: string, password: string, name?: string) => {
const response = await authApi.register({ email, password, name });
// Token is automatically stored by authApi.register
setUser(response.user);
};
const logout = () => {
authApi.logout();
setUser(null);
};
const isAuthenticated = authApi.isAuthenticated();
return (
<AuthContext.Provider value={{ user, isAuthenticated, isLoading, login, register, logout }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}