jeremy 4 月之前
父节点
当前提交
e3de8073af
共有 3 个文件被更改,包括 28 次插入92 次删除
  1. 5 33
      backend/src/routes/auth.js
  2. 0 2
      frontend/src/App.jsx
  3. 23 57
      frontend/src/pages/Login.jsx

+ 5 - 33
backend/src/routes/auth.js

@@ -1,5 +1,4 @@
 const express = require('express');
-const bcrypt = require('bcryptjs');
 const jwt = require('jsonwebtoken');
 const { Issuer } = require('openid-client');
 const pool = require('../db');
@@ -127,41 +126,14 @@ router.get('/oidc/callback', async (req, res) => {
   }
 });
 
-// ─── Auth locale ─────────────────────────────────────────────────────────────
+// ─── Auth locale (désactivée — authentification OIDC uniquement) ─────────────
 
-router.post('/register', async (req, res) => {
-  const { email, password, name } = req.body;
-  if (!email || !password || !name)
-    return res.status(400).json({ error: 'Tous les champs sont requis' });
-
-  try {
-    const hashed = await bcrypt.hash(password, 10);
-    const result = await pool.query(
-      'INSERT INTO users (email, password, name) VALUES ($1, $2, $3) RETURNING id',
-      [email, hashed, name]
-    );
-    const id = result.rows[0].id;
-    const token = jwt.sign({ userId: id }, JWT_SECRET, { expiresIn: '7d' });
-    res.json({ token, user: { id, email, name } });
-  } catch (err) {
-    if (err.code === '23505') return res.status(409).json({ error: 'Email déjà utilisé' });
-    res.status(500).json({ error: err.message });
-  }
+router.post('/register', (req, res) => {
+  res.status(403).json({ error: 'L\'inscription locale est désactivée. Utilisez le SSO.' });
 });
 
-router.post('/login', async (req, res) => {
-  const { email, password } = req.body;
-  if (!email || !password)
-    return res.status(400).json({ error: 'Email et mot de passe requis' });
-
-  const user = (await pool.query('SELECT * FROM users WHERE email = $1', [email])).rows[0];
-  if (!user) return res.status(401).json({ error: 'Identifiants incorrects' });
-
-  const valid = await bcrypt.compare(password, user.password);
-  if (!valid) return res.status(401).json({ error: 'Identifiants incorrects' });
-
-  const token = jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: '7d' });
-  res.json({ token, user: { id: user.id, email: user.email, name: user.name } });
+router.post('/login', (req, res) => {
+  res.status(403).json({ error: 'La connexion locale est désactivée. Utilisez le SSO.' });
 });
 
 router.get('/me', require('../auth').authMiddleware, async (req, res) => {

+ 0 - 2
frontend/src/App.jsx

@@ -3,7 +3,6 @@ import { Toaster } from 'react-hot-toast'
 import { AuthProvider, useAuth } from './context/AuthContext'
 import Layout from './components/Layout'
 import Login from './pages/Login'
-import Register from './pages/Register'
 import OAuthCallback from './pages/OAuthCallback'
 import Dashboard from './pages/Dashboard'
 import Properties from './pages/Properties'
@@ -34,7 +33,6 @@ export default function App() {
         <Toaster position="top-right" />
         <Routes>
           <Route path="/login" element={<PublicRoute><Login /></PublicRoute>} />
-          <Route path="/register" element={<PublicRoute><Register /></PublicRoute>} />
           <Route path="/auth/callback" element={<OAuthCallback />} />
           <Route path="/" element={<PrivateRoute><Layout /></PrivateRoute>}>
             <Route index element={<Dashboard />} />

+ 23 - 57
frontend/src/pages/Login.jsx

@@ -1,78 +1,44 @@
-import { useState, useEffect } from 'react'
-import { Link, useNavigate } from 'react-router-dom'
-import { useAuth } from '../context/AuthContext'
+import { useEffect, useState } from 'react'
 import api from '../api'
-import toast from 'react-hot-toast'
 
 export default function Login() {
-  const [form, setForm] = useState({ email: '', password: '' })
-  const [loading, setLoading] = useState(false)
   const [oidcConfig, setOidcConfig] = useState({ enabled: false, label: 'Se connecter via SSO' })
-  const { login } = useAuth()
-  const navigate = useNavigate()
+  const [loading, setLoading] = useState(true)
 
   useEffect(() => {
-    api.get('/auth/oidc/config').then(res => setOidcConfig(res.data)).catch(() => {})
+    api.get('/auth/oidc/config')
+      .then(res => setOidcConfig(res.data))
+      .catch(() => {})
+      .finally(() => setLoading(false))
   }, [])
 
-  const handleSubmit = async e => {
-    e.preventDefault()
-    setLoading(true)
-    try {
-      await login(form.email, form.password)
-      navigate('/')
-    } catch (err) {
-      toast.error(err.response?.data?.error || 'Erreur de connexion')
-    } finally {
-      setLoading(false)
-    }
-  }
-
   const handleSso = () => {
     window.location.href = '/api/auth/oidc/login'
   }
 
   return (
     <div className="min-h-screen bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center p-4">
-      <div className="bg-white rounded-2xl shadow-lg p-8 w-full max-w-md">
-        <div className="text-center mb-8">
-          <div className="text-5xl mb-3">🏠</div>
-          <h1 className="text-2xl font-bold text-gray-900">Gestion Locative</h1>
-          <p className="text-gray-500 mt-1">Connectez-vous à votre espace</p>
-        </div>
-
-        {oidcConfig.enabled && (
-          <>
-            <button type="button" onClick={handleSso}
-              className="w-full flex items-center justify-center gap-2 py-3 px-4 border-2 border-blue-600 text-blue-600 rounded-xl font-medium hover:bg-blue-50 transition-colors mb-4">
-              🔑 {oidcConfig.label}
-            </button>
-            <div className="relative mb-4">
-              <div className="absolute inset-0 flex items-center"><div className="w-full border-t border-gray-200" /></div>
-              <div className="relative text-center text-sm text-gray-400"><span className="bg-white px-3">ou</span></div>
-            </div>
-          </>
-        )}
+      <div className="bg-white rounded-2xl shadow-lg p-8 w-full max-w-sm text-center">
+        <div className="text-5xl mb-3">🏠</div>
+        <h1 className="text-2xl font-bold text-gray-900">Gestion Locative</h1>
+        <p className="text-gray-500 mt-1 mb-8">Connectez-vous à votre espace</p>
 
-        <form onSubmit={handleSubmit} className="space-y-4">
-          <div>
-            <label className="label">Email</label>
-            <input className="input" type="email" required value={form.email}
-              onChange={e => setForm(f => ({ ...f, email: e.target.value }))} placeholder="votre@email.com" />
+        {loading ? (
+          <div className="flex justify-center py-4">
+            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
           </div>
-          <div>
-            <label className="label">Mot de passe</label>
-            <input className="input" type="password" required value={form.password}
-              onChange={e => setForm(f => ({ ...f, password: e.target.value }))} placeholder="••••••••" />
-          </div>
-          <button type="submit" disabled={loading} className="btn-primary w-full py-3">
-            {loading ? 'Connexion...' : 'Se connecter'}
+        ) : oidcConfig.enabled ? (
+          <button type="button" onClick={handleSso}
+            className="w-full flex items-center justify-center gap-2 py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-xl font-semibold text-base transition-colors shadow">
+            🔑 {oidcConfig.label}
           </button>
-        </form>
-        <p className="text-center text-sm text-gray-500 mt-6">
-          Pas encore de compte ? <Link to="/register" className="text-blue-600 hover:underline font-medium">Créer un compte</Link>
-        </p>
+        ) : (
+          <div className="bg-orange-50 border border-orange-200 rounded-xl p-4 text-sm text-orange-700">
+            ⚠️ Le SSO n'est pas configuré.<br />Contactez l'administrateur.
+          </div>
+        )}
       </div>
     </div>
   )
 }
+