Closed EveCrystali closed 3 weeks ago
Frontend:
info: Frontend.Controllers.AuthController[0]
Service URL for Auth is https://localhost:5000/auth
Frontend.Controllers.AuthController: Information: Service URL for Auth is https://localhost:5000/auth
info: System.Net.Http.HttpClient.Default.LogicalHandler[100]
Start processing HTTP request POST https://localhost:5000/auth/logout/
System.Net.Http.HttpClient.Default.LogicalHandler: Information: Start processing HTTP request POST https://localhost:5000/auth/logout/
info: System.Net.Http.HttpClient.Default.ClientHandler[100]
Sending HTTP request POST https://localhost:5000/auth/logout/
System.Net.Http.HttpClient.Default.ClientHandler: Information: Sending HTTP request POST https://localhost:5000/auth/logout/
info: System.Net.Http.HttpClient.Default.ClientHandler[101]
Received HTTP response headers after 39.5143ms - 404
System.Net.Http.HttpClient.Default.ClientHandler: Information: Received HTTP response headers after 39.5143ms - 404
info: System.Net.Http.HttpClient.Default.LogicalHandler[101]
End processing HTTP request after 42.0732ms - 404
System.Net.Http.HttpClient.Default.LogicalHandler: Information: End processing HTTP request after 42.0732ms - 404
ApiGateway:
warn: Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware[0]
requestId: 0HN714M334T6I:00000001, previousRequestId: No PreviousRequestId, message: 'DownstreamRouteFinderMiddleware setting pipeline errors. IDownstreamRouteFinder returned Error Code: UnableToFindDownstreamRouteError Message: Failed to match Route configuration for upstream path: /auth/logout/, verb: POST.'
Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware: Warning: requestId: 0HN714M334T6I:00000001, previousRequestId: No PreviousRequestId, message: 'DownstreamRouteFinderMiddleware setting pipeline errors. IDownstreamRouteFinder returned Error Code: UnableToFindDownstreamRouteError Message: Failed to match Route configuration for upstream path: /auth/logout/, verb: POST.'
warn: Ocelot.Responder.Middleware.ResponderMiddleware[0]
requestId: 0HN714M334T6I:00000001, previousRequestId: No PreviousRequestId, message: 'Error Code: UnableToFindDownstreamRouteError Message: Failed to match Route configuration for upstream path: /auth/logout/, verb: POST. errors found in ResponderMiddleware. Setting error response for request path:/auth/logout/, request method: POST'
Ocelot.Responder.Middleware.ResponderMiddleware: Warning: requestId: 0HN714M334T6I:00000001, previousRequestId: No PreviousRequestId, message: 'Error Code: UnableToFindDownstreamRouteError Message: Failed to match Route configuration for upstream path: /auth/logout/, verb: POST. errors found in ResponderMiddleware. Setting error response for request path:/auth/logout/, request method: POST'
let's try : https://chatgpt.com/share/66fad2f1-c49c-8010-93ed-4346ce8e1503
Lors de la tentative de déconnexion via le Frontend, vous obtenez une erreur 404. En utilisant Postman pour envoyer une requête POST à https://localhost:5000/auth/logout, vous recevez une réponse 401 Unauthorized. La déconnexion fonctionne correctement lorsque vous accédez directement au microservice Auth (https://localhost:7201/auth/logout). Les logs du Frontend indiquent que le cookie P10AuthCookie n'est pas trouvé. Aucun log n'est généré du côté du microservice Auth lors de la tentative de déconnexion via Ocelot. Cause Probable :
Problème de Domaine des Cookies : Le cookie P10AuthCookie est défini pour le domaine d'Ocelot (localhost:5000), et le Frontend fonctionne sur localhost:7000. Par conséquent, le Frontend ne peut pas accéder directement à ce cookie, empêchant ainsi l'authentification de la requête de déconnexion via Ocelot.
Comprendre les Limites des Cookies sur localhost Les navigateurs traitent localhost avec des ports différents comme des origines distinctes. Cela signifie que les cookies définis pour https://localhost:5000 ne sont pas accessibles depuis https://localhost:7000 et vice versa. Cela entraîne l'impossibilité pour le Frontend de lire ou d'envoyer le cookie P10AuthCookie lorsqu'il interagit directement avec Ocelot.
Solution Proposée : Gérer la Déconnexion Directement via le Navigateur Pour contourner ce problème, nous devons permettre au navigateur de gérer directement la requête de déconnexion vers Ocelot. Cela garantit que le cookie P10AuthCookie est correctement envoyé avec la requête, permettant ainsi à Ocelot d'authentifier et de traiter la demande de déconnexion.
Étapes à Suivre : Supprimer la Méthode Logout dans le Frontend AuthController
Étant donné que le Frontend ne peut pas accéder au cookie P10AuthCookie, il est préférable de supprimer ou de désactiver la méthode Logout dans le Frontend AuthController. Cela évite des tentatives de déconnexion infructueuses via le serveur Frontend.
Action :
Dans Frontend>Controllers>AuthController.cs, commentez ou supprimez la méthode Logout :
// [HttpPost("logout")]
// [ValidateAntiForgeryToken]
// public async Task<IActionResult> Logout()
// {
// // Logique de déconnexion
// }
Modifier la Vue _LoginPartial.cshtml pour Soumettre la Déconnexion Directement à Ocelot
Au lieu d'envoyer la requête de déconnexion via le Frontend AuthController, configurez le formulaire de déconnexion pour qu'il soumette directement la requête au point de terminaison de déconnexion d'Ocelot (https://localhost:5000/auth/logout). De cette manière, le navigateur envoie automatiquement le cookie P10AuthCookie avec la requête.
Action :
Dans Frontend>Views>Shared>_LoginPartial.cshtml, modifiez le formulaire de déconnexion comme suit :
<ul class="navbar-nav">
<li class="nav-item" id="login-item" style="display: true;">
<a class="nav-link" asp-controller="auth" asp-action="login">Connexion</a>
</li>
<li class="nav-item" id="logout-item" style="display: false;">
<form class="form-inline" method="post" action="https://localhost:5000/auth/logout">
@* Supprimer ou commenter le jeton antiforgery *@
@* <input type="hidden" name="__RequestVerificationToken" value="@Antiforgery.GetTokens(Context).RequestToken" /> *@
<button type="submit" class="nav-link btn btn-link">Se déconnecter</button>
</form>
</li>
<li class="nav-item" id="user-name-item" style="display: none;">
<span class="nav-link" id="user-name"></span>
</li>
</ul>
Remarque : Puisque le Frontend ne peut pas gérer le cookie P10AuthCookie, il est préférable de retirer le jeton antiforgery pour cette requête spécifique.
Adapter le Contrôleur Auth dans le Microservice Auth pour Rediriger Après Déconnexion
Modifiez la méthode Logout dans le microservice Auth pour rediriger l'utilisateur vers la page d'accueil du Frontend après une déconnexion réussie.
Action :
Dans Auth>Controllers>AuthController.cs, ajustez la méthode Logout comme suit :
[HttpPost("logout")]
// [ValidateAntiForgeryToken] // Retirez ou commentez cet attribut si nécessaire
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return Redirect("https://localhost:7000"); // Redirige vers la page d'accueil du Frontend
}
Vérifier et Mettre à Jour la Configuration d'Ocelot
Assurez-vous que la route /auth/logout est correctement configurée dans ocelot.json pour accepter les requêtes POST et qu'elle ne nécessite pas de validation antiforgery si elle est désactivée dans la vue.
Action :
Dans ApiGateway>ocelot.json, assurez-vous que la configuration pour /auth/logout est la suivante :
{
"Routes": [
{
"DownstreamPathTemplate": "/auth/logout",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7201
}
],
"UpstreamPathTemplate": "/auth/logout",
"UpstreamHttpMethod": ["POST"],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "P10AuthCookie",
"AllowedScopes": []
},
"RateLimitOptions": {
"EnableRateLimiting": false
},
"CorsPolicy": {
"AllowAnyOrigin": false,
"AllowCredentials": true,
"AllowedOrigins": ["https://localhost:7000"],
"AllowedMethods": ["POST"],
"AllowedHeaders": ["*"]
}
},
// Autres routes...
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5000"
}
}
Assurez-vous que :
Les routes spécifiques (comme /auth/logout) sont définies avant les routes génériques pour éviter les conflits de routage. L'AuthenticationProviderKey correspond bien à celui configuré dans Ocelot ("P10AuthCookie"). Les politiques CORS sont correctement définies pour permettre les requêtes depuis le Frontend (https://localhost:7000). Redémarrer les Services et Tester
Après avoir effectué les modifications, redémarrez tous les services (Ocelot, Frontend, Auth) pour appliquer les nouvelles configurations.
Action :
Redémarrez Ocelot : Assurez-vous que les nouvelles routes sont chargées. Redémarrez le Frontend et le Microservice Auth : Pour appliquer les modifications de code. Tester la Déconnexion
Effectuez les tests suivants pour vérifier que la déconnexion fonctionne comme prévu :
Connexion : Connectez-vous via le Frontend (https://localhost:7000) et assurez-vous que le cookie P10AuthCookie est défini pour le domaine localhost:5000.
Déconnexion : Cliquez sur le bouton de déconnexion. Le formulaire devrait soumettre une requête POST directement à https://localhost:5000/auth/logout, envoyant ainsi le cookie P10AuthCookie.
Redirection : Après une déconnexion réussie, vous devriez être redirigé automatiquement vers la page d'accueil du Frontend (https://localhost:7000).
Vérification des Logs : Consultez les logs d'Ocelot et du microservice Auth pour vous assurer que la requête de déconnexion est bien reçue et traitée.
Vérification des Cookies : Utilisez les outils de développement de votre navigateur (F12) pour vérifier que le cookie P10AuthCookie est supprimé après la déconnexion.
CORS Configuration : La configuration CORS dans Ocelot doit permettre les requêtes depuis le Frontend (https://localhost:7000) avec les méthodes HTTP appropriées et les en-têtes nécessaires.
Ordre des Routes dans Ocelot : Les routes spécifiques doivent toujours être définies avant les routes génériques dans ocelot.json pour éviter que les requêtes spécifiques ne soient capturées par des routes génériques.
Antiforgery Tokens : Si vous désactivez la validation des jetons antiforgery pour la déconnexion, assurez-vous que cette action ne présente pas de risque de sécurité. Dans ce contexte, où la déconnexion est une action simple, cela peut être acceptable, mais soyez conscient des implications.
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
<ul class="navbar-nav">
<li class="nav-item" id="login-item" style="display: true;">
<a class="nav-link" asp-controller="auth" asp-action="login">Connexion</a>
</li>
<li class="nav-item" id="logout-item" style="display: false;">
<form class="form-inline" method="post" action="https://localhost:5000/auth/logout">
@* Supprimer le jeton antiforgery *@
@* <input type="hidden" name="__RequestVerificationToken" value="@Antiforgery.GetTokens(Context).RequestToken" /> *@
<button type="submit" class="nav-link btn btn-link">Se déconnecter</button>
</form>
</li>
<li class="nav-item" id="user-name-item" style="display: none;">
<span class="nav-link" id="user-name"></span>
</li>
</ul>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function () {
console.log("Starting to fetch user data from /status");
$.ajax({
url: window.location.protocol + '//' + window.location.host + '/auth/status',
method: "GET",
success: function (data) {
console.log("Received user data from /status", data);
// Vérifie le type des données reçues pour s'assurer qu'il s'agit bien d'un objet
console.log("Type of isAuthenticated:", typeof data.isAuthenticated);
console.log("Type of username:", typeof data.username);
// Assure-toi que `isAuthenticated` est un booléen et non un tableau vide
const isAuthenticated = Array.isArray(data.isAuthenticated) ? false : data.isAuthenticated;
const username = Array.isArray(data.username) ? "Utilisateur inconnu" : data.username;
if (isAuthenticated) {
console.log("User is authenticated, showing logout item and user name item");
$("#logout-item").show();
$("#user-name-item").show();
$("#user-name").text(username || "Utilisateur");
$("#login-item").hide();
} else {
console.log("User is not authenticated, showing login item");
$("#login-item").show();
$("#logout-item").hide();
$("#user-name-item").hide();
}
},
error: function (err) {
console.log("Error fetching user data from /status", err);
$("#login-item").show();
}
});
});
</script>
Auth>Controllers>AuthController.cs :
using Auth.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace Auth.Controllers;
[Route("auth")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<AuthController> _logger;
public AuthController(UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
ILogger<AuthController> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
[HttpPost("logout")]
// [ValidateAntiForgeryToken] // Retirez ou commentez cet attribut si nécessaire
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return Redirect("https://localhost:7000"); // Redirige vers la page d'accueil du Frontend
}
// Autres méthodes (login, register, status)...
}
ApiGateway>Ocelot.json :
Assurez-vous que les routes spécifiques sont placées avant les routes génériques et que la configuration CORS est correcte.
{
"Routes": [
{
"DownstreamPathTemplate": "/auth/logout",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7201
}
],
"UpstreamPathTemplate": "/auth/logout",
"UpstreamHttpMethod": ["POST"],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "P10AuthCookie",
"AllowedScopes": []
},
"RateLimitOptions": {
"EnableRateLimiting": false
},
"CorsPolicy": {
"AllowAnyOrigin": false,
"AllowCredentials": true,
"AllowedOrigins": ["https://localhost:7000"],
"AllowedMethods": ["POST"],
"AllowedHeaders": ["*"]
}
},
{
"DownstreamPathTemplate": "/auth/login",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7201
}
],
"UpstreamPathTemplate": "/auth/login",
"UpstreamHttpMethod": ["POST"],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": null,
"RateLimitOptions": {
"EnableRateLimiting": false
},
"CorsPolicy": {
"AllowAnyOrigin": false,
"AllowCredentials": true,
"AllowedOrigins": ["https://localhost:7000"],
"AllowedMethods": ["GET", "POST", "OPTIONS"],
"AllowedHeaders": ["*"]
}
},
{
"DownstreamPathTemplate": "/auth/status",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7201
}
],
"UpstreamPathTemplate": "/auth/status",
"UpstreamHttpMethod": ["GET"],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": null,
"RateLimitOptions": {
"EnableRateLimiting": false
},
"CorsPolicy": {
"AllowAnyOrigin": false,
"AllowCredentials": true,
"AllowedOrigins": ["https://localhost:7000"],
"AllowedMethods": ["GET"],
"AllowedHeaders": ["*"]
}
},
// Ajoutez la route pour le Frontend si nécessaire
// {
// "DownstreamPathTemplate": "/{everything}",
// "DownstreamScheme": "https",
// "DownstreamHostAndPorts": [
// { "Host": "localhost", "Port": 7000 }
// ],
// "UpstreamPathTemplate": "/frontend/{everything}",
// "UpstreamHttpMethod": ["GET", "POST", "PUT", "DELETE"]
// },
{
"UpstreamPathTemplate": "/",
"DownstreamPathTemplate": "/",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7200
}
]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5000"
}
}
Requêtes de Déconnexion : Assurez-vous que lorsque vous soumettez le formulaire de déconnexion, la requête POST est envoyée directement à https://localhost:5000/auth/logout et que le cookie P10AuthCookie est inclus dans cette requête.
Logs Ocelot et Auth : Consultez les logs d'Ocelot et du microservice Auth pour vous assurer que la requête de déconnexion est bien reçue et traitée sans erreurs.
Redirection : Après la déconnexion, l'utilisateur doit être redirigé vers la page d'accueil (https://localhost:7000).
Alternative : Utiliser JWT Tokens au Lieu des Cookies Si malgré ces ajustements le problème persiste, envisagez de passer à une authentification basée sur des tokens JWT. Les JWT peuvent être stockés côté client (par exemple, dans le localStorage ou les cookies avec les attributs appropriés) et envoyés dans les en-têtes Authorization avec chaque requête, ce qui simplifie la gestion des authentifications dans une architecture en microservices.
Conclusion Le problème principal était lié à l'inaccessibilité du cookie P10AuthCookie par le Frontend en raison des différences de domaines (localhost:5000 vs localhost:7000). En modifiant le processus de déconnexion pour que le navigateur envoie directement la requête à Ocelot, vous permettez à Ocelot d'accéder au cookie nécessaire pour authentifier et traiter la demande de déconnexion. Cette approche garantit que la déconnexion fonctionne correctement et que l'utilisateur est redirigé vers la page d'accueil sans rencontrer d'erreurs.
Si, après avoir suivi ces étapes, vous rencontrez toujours des problèmes, veuillez fournir les nouvelles logs d'Ocelot et du microservice Auth pour une analyse plus approfondie.
Bon courage et n'hésitez pas à revenir pour toute assistance supplémentaire !
Request = POST https://localhost:7000/auth/logout HTTP/2 application/x-www-form-urlencoded Response HttResponse = 200 OK
IsAuthenticated = false ??
{Method: POST, RequestUri: 'https://localhost:5000/auth/logout/', Version: 1.1, Content:, Headers:
{
traceparent: 00-511e7c383d06861aa64b0c3a4fbc88e2-812a131e1fe06417-00
}}
{StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Mon, 30 Sep 2024 07:57:49 GMT
Server: Kestrel
Content-Length: 0
}, Trailing Headers:
{
}}