public ActionResult Logout(IFormCollection formCollection) { // Try to get logout request data string idPName = this.GetCookie("IdPName"); string spidLogoutRequestId = this.GetCookie("SpidLogoutRequestId"); // End the session and remove cookies HttpContext.Session.SetObject <UserInfo>("UserInfo", null); this.RemoveCookie("IdPName"); this.RemoveCookie("SpidAuthnRequestId"); this.RemoveCookie("SpidLogoutRequestId"); this.RemoveCookie("SubjectNameId"); this.RemoveCookie("AuthnStatementSessionIndex"); // The single logout process can be started directly by IdP provider without a client request done from this service // So an empty spidLogoutRequestId is still valid and do not represent an error. // In that context, we simply skip the response processing, since there isn't any response to check. if (!string.IsNullOrWhiteSpace(spidLogoutRequestId)) { try { IdpLogoutResponse idpLogoutResponse = SamlHelper.GetLogoutResponse(formCollection["SAMLResponse"].ToString()); if (!idpLogoutResponse.IsSuccessful) { // TODO: log.Error($"Error on ACSController [HttpPost]Index method: La risposta dell'IdP riporta il seguente StatusCode: {idpLogoutResponse.StatusCodeInnerValue} con StatusMessage: {idpLogoutResponse.StatusMessage} e StatusDetail: {idpLogoutResponse.StatusDetail}."); ViewData["Message"] = "La richiesta di logout è stata rifiutata."; ViewData["ErrorMessage"] = $"StatusCode: {idpLogoutResponse.StatusCodeInnerValue} con StatusMessage: {idpLogoutResponse.StatusMessage} e StatusDetail: {idpLogoutResponse.StatusDetail}."; return(View("Error")); } // Verifica la corrispondenza del valore di spidLogoutRequestId ricavato da cookie con quello restituito dalla risposta if (!SamlHelper.ValidLogoutResponse(idpLogoutResponse, spidLogoutRequestId)) { // TODO: log.Error($"Error on ACSController [HttpPost]Index method: La risposta dell'IdP non è valida (InResponseTo != spidLogoutRequestId)."); ViewData["Message"] = "La risposta dell'IdP non è valida perché non corrisponde alla richiesta."; ViewData["ErrorMessage"] = $"RequestId: _{spidLogoutRequestId}, InResponseTo: {idpLogoutResponse.InResponseTo}."; return(View("Error")); } } catch (Exception ex) { // TODO: log.Error("Error on ACSController [HttpPost]Index method", ex); ViewData["Message"] = "Errore nella lettura della risposta ricevuta dal provider."; ViewData["ErrorMessage"] = ex.Message; return(View("Error")); } } return(View("Logout")); }
/// <summary> /// Check the validity of IdP logout response /// </summary> /// <param name="idpLogoutResponse"></param> /// <param name="spidRequestId"></param> /// <returns>True if valid, false otherwise</returns> public static bool ValidLogoutResponse(IdpLogoutResponse idpLogoutResponse, string spidRequestId) { return(idpLogoutResponse.InResponseTo == "_" + spidRequestId); }
public ActionResult Logout(FormCollection formCollection) { string IdPName; string spidLogoutRequestId; // Try to get auth requesta data from cookie HttpCookie cookie = Request.Cookies[SPID_COOKIE]; if (cookie != null) { IdPName = cookie["IdPName"]; spidLogoutRequestId = cookie["SpidLogoutRequestId"]; log.Info($"Cookie {SPID_COOKIE} IdPName: {IdPName}, SpidLogoutRequestId: {spidLogoutRequestId}"); } else { log.Error("Error on ACSController [HttpPost]Index method: Impossibile recuperare l'Id della sessione."); ViewData["Message"] = "Impossibile recuperare i dati della sessione (cookie scaduto)."; return(View("Error")); } // Remove the cookie cookie.Values["IdPName"] = string.Empty; cookie.Values["SpidAuthnRequestId"] = string.Empty; cookie.Values["SpidLogoutRequestId"] = string.Empty; cookie.Values["SubjectNameId"] = string.Empty; cookie.Values["AuthnStatementSessionIndex"] = string.Empty; cookie.Expires = DateTime.Now.AddDays(-1); Response.Cookies.Add(cookie); // End the session Session["AppUser"] = null; try { IdpLogoutResponse idpLogoutResponse = SamlHelper.GetLogoutResponse(formCollection["SAMLResponse"].ToString()); if (!idpLogoutResponse.IsSuccessful) { log.Error($"Error on ACSController [HttpPost]Index method: La risposta dell'IdP riporta il seguente StatusCode: {idpLogoutResponse.StatusCodeInnerValue} con StatusMessage: {idpLogoutResponse.StatusMessage} e StatusDetail: {idpLogoutResponse.StatusDetail}."); ViewData["Message"] = "La richiesta di logout è stata rifiutata."; ViewData["ErrorMessage"] = $"StatusCode: {idpLogoutResponse.StatusCodeInnerValue} con StatusMessage: {idpLogoutResponse.StatusMessage} e StatusDetail: {idpLogoutResponse.StatusDetail}."; return(View("Error")); } // Verifica la corrispondenza del valore di spidLogoutRequestId ricavato da cookie con quello restituito dalla risposta if (!SamlHelper.ValidLogoutResponse(idpLogoutResponse, spidLogoutRequestId)) { log.Error($"Error on ACSController [HttpPost]Index method: La risposta dell'IdP non è valida (InResponseTo != spidLogoutRequestId)."); ViewData["Message"] = "La risposta dell'IdP non è valida perché non corrisponde alla richiesta."; ViewData["ErrorMessage"] = $"RequestId: _{spidLogoutRequestId}, RequestPath: {Request.Url.ToString()}, InResponseTo: {idpLogoutResponse.InResponseTo}."; return(View("Error")); } return(View("Logout")); } catch (Exception ex) { log.Error("Error on ACSController [HttpPost]Index method", ex); ViewData["Message"] = "Errore nella lettura della risposta ricevuta dal provider."; ViewData["ErrorMessage"] = ex.Message; return(View("Error")); } }