Single Sign-On (SSO) est un mécanisme d'authentification qui permet aux utilisateurs de se connecter une seule fois et d'accéder à plusieurs applications ou systèmes connectés sans avoir besoin de se réauthentifier pour chacun. SSO centralise l'authentification des utilisateurs dans un système unique et fiable (souvent appelé fournisseur d'identité ou IdP), qui gère ensuite les informations d'identification et émet des jetons ou des données de session pour vérifier l'identité de l'utilisateur sur d'autres services (appelés fournisseurs de services ou SP).
Dans ce guide, nous explorerons le fonctionnement du SSO, ses avantages et ses inconvénients, des cas d'utilisation courants et des exemples d'implémentation de SSO dans une API (Node.js avec Express), une application principale (React) et une application externe. application (Réagir). En comprenant les principes et les pratiques du SSO, les organisations peuvent améliorer l'expérience utilisateur, la sécurité et l'efficacité opérationnelle dans leurs applications et systèmes.
Single Sign-On (SSO) est un mécanisme d'authentification qui permet aux utilisateurs de se connecter une seule fois et d'accéder à plusieurs applications ou systèmes connectés sans avoir besoin de se réauthentifier pour chacun.
SSO centralise l'authentification des utilisateurs dans un système unique et fiable (souvent appelé fournisseur d'identité ou IdP), qui gère ensuite les informations d'identification et émet des jetons ou des données de session pour vérifier l'identité de l'utilisateur sur d'autres services (appelés fournisseurs de services ou SP). ).
SSO fonctionne via des mécanismes sécurisés basés sur des jetons tels que OAuth 2.0, OpenID Connect (OIDC) ou Security Assertion Markup Language (SAML). Voici un flux simplifié :
Connexion utilisateur : l'utilisateur saisit ses informations d'identification dans le fournisseur d'identité (IdP).
Émission de jeton : l'IdP valide les informations d'identification et émet un jeton d'authentification (par exemple, une assertion JWT ou SAML).
Accès au service : le jeton est transmis aux fournisseurs de services, qui le valident et accordent l'accès sans nécessiter de connexions supplémentaires.
Expérience utilisateur améliorée : les utilisateurs peuvent accéder à plusieurs services avec une seule connexion, réduisant ainsi les frictions et améliorant la convivialité.
Sécurité améliorée :
Gestion simplifiée des utilisateurs :
Efficacité en termes de temps et de coûts :
Conformité et audit :
Point de défaillance unique :
Mise en œuvre complexe :
Risques de sécurité :
Verrouillage du fournisseur :
Défis de la gestion des jetons :
Applications d'entreprise :
Services Cloud :
Portails clients :
Intégration des partenaires :
L'API agit en tant que fournisseur d'identité (IdP). Il authentifie les utilisateurs et émet des jetons JWT pour l'accès.
Vous trouverez ci-dessous une ventilation structurée du code fourni, expliquant le but de chaque section pour vos abonnés. Cela constitue un exemple solide de la façon d'implémenter la fonctionnalité SSO dans la couche API.
Les packages suivants sont utilisés dans cette configuration :
dotenv.config(); const SECRET_KEY = process.env.SECRET_KEY || "secret";
app.use( cors({ origin: ["http://localhost:5173", "http://localhost:5174"], credentials: true, }) ); app.use(express.json()); app.use(cookieParser());
Les données simulées simulent les utilisateurs et leurs tâches associées.
Les utilisateurs ont des rôles (administrateur ou utilisateur) et des informations de profil de base.
Les tâches sont liées aux identifiants des utilisateurs pour un accès personnalisé.
Les utilisateurs reçoivent un cookie (sso_token) contenant le JWT lors d'une connexion réussie.
Ce jeton est sécurisé, HTTP uniquement et limité dans le temps pour éviter toute falsification.
app.post("/login", (req, res) => { const { email, password } = req.body; const user = users.find( (user) => user.email === email && user.password === password ); if (user) { const token = jwt.sign({ user }, SECRET_KEY, { expiresIn: "1h" }); res.cookie("sso_token", token, { httpOnly: true, secure: process.env.NODE_ENV === "production", maxAge: 3600000, sameSite: "strict", }); res.json({ message: "Login successful" }); } else { res.status(400).json({ error: "Invalid credentials" }); } });
app.get("/verify", (req, res) => { const token = req.cookies.sso_token; if (!token) { return res.status(401).json({ authenticated: false }); } try { const decoded = jwt.verify(token, SECRET_KEY); res.json({ authenticated: true, user: decoded }); } catch { res.status(401).json({ authenticated: false, error: "Invalid token" }); } });
Garantit que les utilisateurs peuvent se déconnecter en toute sécurité en effaçant leur jeton.
dotenv.config(); const SECRET_KEY = process.env.SECRET_KEY || "secret";
app.use( cors({ origin: ["http://localhost:5173", "http://localhost:5174"], credentials: true, }) ); app.use(express.json()); app.use(cookieParser());
app.post("/login", (req, res) => { const { email, password } = req.body; const user = users.find( (user) => user.email === email && user.password === password ); if (user) { const token = jwt.sign({ user }, SECRET_KEY, { expiresIn: "1h" }); res.cookie("sso_token", token, { httpOnly: true, secure: process.env.NODE_ENV === "production", maxAge: 3600000, sameSite: "strict", }); res.json({ message: "Login successful" }); } else { res.status(400).json({ error: "Invalid credentials" }); } });
app.get("/verify", (req, res) => { const token = req.cookies.sso_token; if (!token) { return res.status(401).json({ authenticated: false }); } try { const decoded = jwt.verify(token, SECRET_KEY); res.json({ authenticated: true, user: decoded }); } catch { res.status(401).json({ authenticated: false, error: "Invalid token" }); } });
app.post("/logout", (req, res) => { res.clearCookie("sso_token"); res.json({ message: "Logout successful" }); });
L'application principale agit en tant que fournisseur de services (SP) qui consomme l'API et gère les interactions des utilisateurs.
Vous trouverez ci-dessous une ventilation structurée du code fourni, expliquant le but de chaque section pour vos abonnés. Cela constitue un exemple solide de la façon d'implémenter la fonctionnalité SSO dans la couche d'application principale.
Le composant App gère l'authentification des utilisateurs et les redirections en fonction de l'état de connexion.
app.get("/todos/:userId", (req, res) => { const ssoToken = req.cookies.sso_token; const user = getUser(ssoToken); if (!user) { return res.status(401).json({ error: "Unauthorized" }); } const userTodos = todos.filter((todo) => todo.userId === user.id); res.json(userTodos); });
Le composant de connexion gère la connexion de l'utilisateur et redirige vers la page Todos une fois l'authentification réussie.
app.post("/todos", (req, res) => { const ssoToken = req.cookies.sso_token; const user = getUser(ssoToken); if (!user) { return res.status(401).json({ error: "Unauthorized" }); } const { title, description } = req.body; const newTodo = { id: faker.string.uuid(), userId: user.id, title, description, }; todos.push(newTodo); res.status(201).json({ message: "Todo added successfully", data: newTodo }); });
Le composant Todos affiche les tâches spécifiques à l'utilisateur et permet d'ajouter et de supprimer des tâches.
// Update a todo app.put("/todos/:id", (req, res) => { const ssotoken = req.cookies.sso_token; const user = getUser(ssotoken); if (!user) { return res.status(401).json({ message: "Unauthorized" }); } const { id } = req.params; const { title, description } = req.body; const index = todos.findIndex((todo) => todo.id === id); if (index !== -1) { todos[index] = { ...todos[index], title, description, }; res.json({ message: "Todo updated successfully", data: todos[index], }); } else { res.status(404).json({ message: "Todo not found" }); } });
L'application externe agit comme un autre fournisseur de services (SP) qui consomme l'API et gère les interactions des utilisateurs.
Vous trouverez ci-dessous une ventilation structurée du code fourni, expliquant le but de chaque section pour vos abonnés. Cela constitue un exemple solide de la façon d'implémenter la fonctionnalité SSO dans la couche d'application externe.
Le composant App gère l'authentification des utilisateurs et les redirections en fonction de l'état de connexion.
// Delete a todo app.delete("/todos/:id", (req, res) => { const ssoToken = req.cookies.sso_token; const user = getUser(ssoToken); if (!user) { return res.status(401).json({ message: "Unauthorized" }); } const { id } = req.params; const index = todos.findIndex((todo) => todo.id === id); if (index !== -1) { todos = todos.filter((todo) => todo.id !== id); res.json({ message: "Todo deleted successfully" }); } else { res.status(404).json({ message: "Todo not found" }); } });
Le composant Todos affiche les tâches spécifiques à l'utilisateur.
import { useState, useEffect } from "react"; import { Navigate, Route, Routes, useNavigate, useSearchParams, } from "react-router-dom"; import Todos from "./components/Todos"; import Login from "./components/Login"; import { toast } from "react-toastify"; import api from "./api"; function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); const [searchParams] = useSearchParams(); const navigate = useNavigate(); useEffect(() => { const verifyLogin = async () => { const returnUrl = searchParams.get("returnUrl"); try { const response = await api.get("/verify", { withCredentials: true, }); if (response.data.authenticated) { setIsLoggedIn(true); toast.success("You are logged in."); navigate("/todos"); } else { setIsLoggedIn(false); if (!returnUrl) { toast.error("You are not logged in."); } } } catch (error) { setIsLoggedIn(false); console.error("Verification failed:", error); } }; verifyLogin(); const handleVisibilityChange = () => { if (document.visibilityState === "visible") { verifyLogin(); } }; document.addEventListener("visibilitychange", handleVisibilityChange); return () => { document.removeEventListener("visibilitychange", handleVisibilityChange); }; }, [navigate, searchParams]); return ( <div className="container p-4 mx-auto"> <Routes> <Route path="/" element={<Login />} /> <Route path="/todos" element={isLoggedIn ? <Todos /> : <Navigate to={"/"} />} /> </Routes> </div> ); } export default App;
L'authentification unique (SSO) simplifie l'authentification des utilisateurs et la gestion des accès sur plusieurs applications, améliorant ainsi l'expérience utilisateur, la sécurité et l'efficacité opérationnelle. En centralisant l'authentification et en tirant parti de mécanismes sécurisés basés sur des jetons, les organisations peuvent rationaliser l'accès des utilisateurs, réduire les risques liés aux mots de passe et améliorer les capacités de conformité et d'audit.
Bien que le SSO offre de nombreux avantages, il présente également des défis tels que des points de défaillance uniques, des exigences de mise en œuvre complexes, des risques de sécurité et une dépendance potentielle envers un fournisseur. Les organisations doivent soigneusement planifier et mettre en œuvre des solutions SSO pour atténuer ces risques et maximiser les avantages de l'authentification centralisée.
En suivant les meilleures pratiques, en tirant parti des protocoles établis et en choisissant des normes ouvertes, les organisations peuvent mettre en œuvre avec succès le SSO pour améliorer l'expérience utilisateur, la sécurité et l'efficacité opérationnelle dans leurs applications et systèmes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!