Improve login page security by dynamically showing default credentials

Adds API endpoint to check default admin password status and hides credentials.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 91318273-c764-4fd4-be04-bdc12c38af32
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/22c32c18-bf03-4830-a5c9-ef4544d0e27f.jpg
This commit is contained in:
michaelschal committed 2025-07-09 19:31:54 +00:00
1 parent a78d648c01
commit 1d46228fac
4 files changed
+60 -9

No files matched your search

+30 -8
View File
@@ -1,19 +1,31 @@
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { useToast } from "@/hooks/use-toast";
import { useAuth } from "@/hooks/useAuth";
import { loginSchema, type LoginData } from "@shared/schema";
import { LogIn, Sparkles } from "lucide-react";
import { LogIn, Sparkles, Info } from "lucide-react";
import { apiRequest } from "@/lib/queryClient";
export default function Login() {
const { login, isLoggingIn } = useAuth();
const { toast } = useToast();
// Check if default credentials should be shown
const { data: credentialsStatus } = useQuery({
queryKey: ['/api/auth/default-credentials-status'],
queryFn: async () => {
const response = await apiRequest('/api/auth/default-credentials-status');
return response.json();
},
});
const form = useForm<LoginData>({
resolver: zodResolver(loginSchema),
defaultValues: {
@@ -86,13 +98,23 @@ export default function Login() {
</form>
</Form>
<div className="mt-6 p-4 bg-blue-50 rounded-lg border border-blue-200">
<h4 className="font-medium text-blue-900 mb-2">Compte par défaut :</h4>
<div className="text-sm text-blue-700 space-y-1">
<p><strong>Utilisateur :</strong> admin</p>
<p><strong>Mot de passe :</strong> admin123</p>
</div>
</div>
{credentialsStatus?.showDefaultCredentials && (
<Alert className="mt-6">
<Info className="h-4 w-4" />
<AlertDescription>
<div className="space-y-2">
<p className="font-medium">Compte administrateur par défaut :</p>
<div className="text-sm space-y-1">
<p><strong>Utilisateur :</strong> admin</p>
<p><strong>Mot de passe :</strong> admin123</p>
</div>
<p className="text-xs text-orange-600 mt-2">
⚠️ Changez ce mot de passe après votre première connexion pour sécuriser l'application.
</p>
</div>
</AlertDescription>
</Alert>
)}
</CardContent>
</Card>
</div>
+7 -1
View File
@@ -174,4 +174,10 @@ Preferred communication style: Simple, everyday language.
- ✅ Backup files stored in server/backups/ directory with timestamped filenames
- ✅ Enhanced administration interface showing backup statistics and manual backup creation
- ✅ Real-time backup status monitoring with automatic stats refresh every 30 seconds
- ✅ Initial backup creation on server startup if no backups exist
- ✅ Initial backup creation on server startup if no backups exist
### Security Improvements (January 9, 2025)
- ✅ Enhanced login page to hide default admin credentials (admin/admin123) once password is changed
- ✅ Added dynamic credential visibility based on whether default password is still in use
- ✅ Security warning displayed when default credentials are shown
- ✅ API endpoint to check default credential status with password hash comparison
+11
View File
@@ -105,6 +105,17 @@ export async function registerRoutes(app: Express): Promise<Server> {
});
});
// Check if default admin credentials are still in use
app.get('/api/auth/default-credentials-status', async (req, res) => {
try {
const isUsingDefault = await storage.isUsingDefaultPassword();
res.json({ showDefaultCredentials: isUsingDefault });
} catch (error) {
console.error('Default credentials check error:', error);
res.status(500).json({ error: "Failed to check default credentials status" });
}
});
app.get('/api/auth/me', requireAuth, async (req, res) => {
try {
const user = await storage.getUser(req.session.userId!);
+12
View File
@@ -39,6 +39,7 @@ export interface IStorage {
authenticateUser(username: string, password: string): Promise<User | null>;
hashPassword(password: string): Promise<string>;
initializeDefaults(): Promise<{ defaultAdminCredentials?: { username: string; password: string } }>;
isUsingDefaultPassword(): Promise<boolean>;
}
export class DatabaseStorage implements IStorage {
@@ -168,6 +169,17 @@ export class DatabaseStorage implements IStorage {
return await bcrypt.hash(password, 12);
}
// Check if admin still uses default password
async isUsingDefaultPassword(): Promise<boolean> {
const adminUser = await this.getUserByUsername('admin');
if (!adminUser) {
return false;
}
// Check if the stored password hash matches the default password "admin123"
return await bcrypt.compare('admin123', adminUser.password);
}
// Initialize default admin user and store if none exist
async initializeDefaults(): Promise<{ defaultAdminCredentials?: { username: string; password: string } }> {
const existingUsers = await this.getAllUsers();