/// <summary> /// Handles the request. /// </summary> /// <param name="context">The context.</param> private void HandleRequest(HttpContext context) { Logger.DebugFormat(TraceMessages.LogoutRequestReceived); // Fetch the endpoint configuration var idp = RetrieveIDPConfiguration(StateService.Get<string>(IdpLoginSessionKey)); var destination = DetermineEndpointConfiguration(BindingType.Redirect, idp.Endpoints.LogoutEndpoint, idp.Metadata.IDPSLOEndpoints); // Fetch config object var config = Saml2Config.GetConfig(); // Build the response object var response = new Saml20LogoutResponse { Issuer = config.ServiceProvider.Id, Destination = destination.Url, StatusCode = Saml20Constants.StatusCodes.Success }; string message; if (context.Request.RequestType == "GET") { // HTTP Redirect binding var parser = new HttpRedirectBindingParser(context.Request.Url); Logger.DebugFormat(TraceMessages.LogoutRequestRedirectBindingParse, parser.Message, parser.SignatureAlgorithm, parser.Signature); var endpoint = config.IdentityProviders.FirstOrDefault(x => x.Id == idp.Id); if (endpoint == null || endpoint.Metadata == null) { Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id); throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id)); } var metadata = endpoint.Metadata; if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.Signing))) { Logger.Error(ErrorMessages.RequestSignatureInvalid); throw new Saml20Exception(ErrorMessages.RequestSignatureInvalid); } message = parser.Message; } else if (context.Request.RequestType == "POST") { // HTTP Post binding var parser = new HttpPostBindingParser(context); Logger.DebugFormat(TraceMessages.LogoutRequestPostBindingParse, parser.Message); if (!parser.IsSigned) { Logger.Error(ErrorMessages.RequestSignatureMissing); throw new Saml20Exception(ErrorMessages.RequestSignatureMissing); } var endpoint = config.IdentityProviders.FirstOrDefault(x => x.Id == idp.Id); if (endpoint == null || endpoint.Metadata == null) { Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id); throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id)); } var metadata = endpoint.Metadata; // Check signature if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.Signing))) { Logger.Error(ErrorMessages.RequestSignatureInvalid); throw new Saml20Exception(ErrorMessages.RequestSignatureInvalid); } message = parser.Message; } else { // Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS Logger.ErrorFormat(ErrorMessages.UnsupportedRequestType, context.Request.RequestType); throw new Saml20Exception(string.Format(ErrorMessages.UnsupportedRequestType, context.Request.RequestType)); } Logger.DebugFormat(TraceMessages.LogoutRequestParsed, message); // Log the user out locally DoLogout(context, true); var req = Serialization.DeserializeFromXmlString<LogoutRequest>(message); response.InResponseTo = req.Id; // Respond using redirect binding if (destination.Binding == BindingType.Redirect) { var builder = new HttpRedirectBindingBuilder { RelayState = context.Request.Params["RelayState"], Response = response.GetXml().OuterXml, SigningKey = Saml2Config.GetConfig().ServiceProvider.SigningCertificate.GetCertificate().PrivateKey }; Logger.DebugFormat(TraceMessages.LogoutResponseSent, builder.Response); context.Response.Redirect(destination.Url + "?" + builder.ToQuery(), true); return; } // Respond using post binding if (destination.Binding == BindingType.Post) { var builder = new HttpPostBindingBuilder(destination) { Action = SamlActionType.SAMLResponse }; var responseDocument = response.GetXml(); Logger.DebugFormat(TraceMessages.LogoutResponseSent, responseDocument.OuterXml); XmlSignatureUtils.SignDocument(responseDocument, response.Id); builder.Response = responseDocument.OuterXml; builder.RelayState = context.Request.Params["RelayState"]; builder.GetPage().ProcessRequest(context); } }
/// <summary> /// Handles the response. /// </summary> /// <param name="context">The context.</param> private void HandleResponse(HttpContext context) { Logger.DebugFormat(TraceMessages.LogoutResponseReceived); var message = string.Empty; LogoutResponse response = null; if (context.Request.RequestType == "GET") { var parser = new HttpRedirectBindingParser(context.Request.Url); response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message); Logger.DebugFormat(TraceMessages.LogoutResponseRedirectBindingParse, parser.Message, parser.SignatureAlgorithm, parser.Signature); var idp = RetrieveIDPConfiguration(response.Issuer.Value); if (idp.Metadata == null) { Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id); throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id)); } if (!parser.VerifySignature(idp.Metadata.Keys)) { Logger.Error(ErrorMessages.ResponseSignatureInvalid); throw new Saml20Exception(ErrorMessages.ResponseSignatureInvalid); } message = parser.Message; } else if (context.Request.RequestType == "POST") { var parser = new HttpPostBindingParser(context); Logger.DebugFormat(TraceMessages.LogoutResponsePostBindingParse, parser.Message); response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message); var idp = RetrieveIDPConfiguration(response.Issuer.Value); if (idp.Metadata == null) { Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id); throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id)); } if (!parser.IsSigned) { Logger.Error(ErrorMessages.ResponseSignatureMissing); throw new Saml20Exception(ErrorMessages.ResponseSignatureMissing); } // signature on final message in logout if (!parser.CheckSignature(idp.Metadata.Keys)) { Logger.Error(ErrorMessages.ResponseSignatureInvalid); throw new Saml20Exception(ErrorMessages.ResponseSignatureInvalid); } message = parser.Message; } if (response == null) { Logger.ErrorFormat(ErrorMessages.UnsupportedRequestType, context.Request.RequestType); throw new Saml20Exception(string.Format(ErrorMessages.UnsupportedRequestType, context.Request.RequestType)); } Logger.DebugFormat(TraceMessages.LogoutResponseParsed, message); if (response.Status.StatusCode.Value != Saml20Constants.StatusCodes.Success) { Logger.ErrorFormat(ErrorMessages.ResponseStatusNotSuccessful, response.Status.StatusCode.Value); throw new Saml20Exception(string.Format(ErrorMessages.ResponseStatusNotSuccessful, response.Status.StatusCode.Value)); } // Log the user out locally DoLogout(context); }
private void ValidateLogoutViaGet(Uri requestUrl, out string message, out LogoutResponse response) { var parser = new HttpRedirectBindingParser(requestUrl); response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message); logger.DebugFormat(TraceMessages.LogoutResponseRedirectBindingParse, parser.Message, parser.SignatureAlgorithm, parser.Signature); var idp = IdpSelectionUtil.RetrieveIDPConfiguration(response.Issuer.Value, config); if (idp.Metadata == null) { logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, idp.Id); throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, idp.Id)); } if (!parser.VerifySignature(idp.Metadata.Keys)) { logger.Error(ErrorMessages.ResponseSignatureInvalid); throw new Saml20Exception(ErrorMessages.ResponseSignatureInvalid); } message = parser.Message; }