/// <summary> /// Build a LogoutRequest and send it to the Federation Partner with the given entity ID. /// </summary> /// <param name="entityID"></param> private static void CreateLogoutRequest(string entityID) { User user = UserSessionsHandler.CurrentUser; Saml20LogoutRequest request = new Saml20LogoutRequest(); request.Issuer = IDPConfig.ServerBaseUrl; request.SessionIndex = Guid.NewGuid().ToString("N"); request.SubjectToLogOut = new NameID(); request.SubjectToLogOut.Format = Saml20Constants.NameIdentifierFormats.Unspecified; request.SubjectToLogOut.Value = user.Username; Saml20MetadataDocument metadata = GetMetadata(entityID); // HTTPRedirect(SAMLAction.SAMLRequest, metadata.SLOEndpoint(SAMLBinding.REDIRECT), request.GetXml()); HttpPostBindingBuilder builder = new HttpPostBindingBuilder(metadata.SLOEndpoint(SAMLBinding.POST)); builder.Action = SAMLAction.SAMLRequest; //builder.Response = assertionDoc.OuterXml; string xmloutput = request.GetXml().OuterXml; TextWriter tw = new StreamWriter("C:\\temp\\idp.txt", true); tw.WriteLine(xmloutput); tw.Close(); builder.Response = xmloutput; builder.GetPage().ProcessRequest(HttpContext.Current); HttpContext.Current.Response.End(); }
private void TransferClient(IDPEndPoint idpEndpoint, Saml20AuthnRequest request, HttpContext context) { AuditLogging.AssertionId = request.ID; AuditLogging.IdpId = idpEndpoint.Id; //Set the last IDP we attempted to login at. context.Session[IDPTempSessionKey]= idpEndpoint.Id; // Determine which endpoint to use from the configuration file or the endpoint metadata. IDPEndPointElement destination = DetermineEndpointConfiguration(SAMLBinding.REDIRECT, idpEndpoint.SSOEndpoint, idpEndpoint.metadata.SSOEndpoints()); request.Destination = destination.Url; if (idpEndpoint.ForceAuthn) request.ForceAuthn = true; object isPassiveFlag = context.Session[IDPIsPassive]; if (isPassiveFlag != null && (bool)isPassiveFlag) { request.IsPassive = true; context.Session[IDPIsPassive] = null; } if (idpEndpoint.IsPassive) request.IsPassive = true; object forceAuthnFlag = context.Session[IDPForceAuthn]; if (forceAuthnFlag != null && (bool)forceAuthnFlag) { request.ForceAuthn = true; context.Session[IDPForceAuthn] = null; } if (idpEndpoint.SSOEndpoint != null) { if (!string.IsNullOrEmpty(idpEndpoint.SSOEndpoint.ForceProtocolBinding)) { request.ProtocolBinding = idpEndpoint.SSOEndpoint.ForceProtocolBinding; } } //Save request message id to session context.Session.Add(ExpectedInResponseToSessionKey, request.ID); if (destination.Binding == SAMLBinding.REDIRECT) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Redirect, idpEndpoint.Id)); HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder(); builder.signingKey = _certificate.PrivateKey; builder.Request = request.GetXml().OuterXml; string s = request.Destination + "?" + builder.ToQuery(); AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT, "Redirecting user to IdP for authentication", builder.Request); context.Response.Redirect(s, true); return; } if (destination.Binding == SAMLBinding.POST) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Post, idpEndpoint.Id)); HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination); //Honor the ForceProtocolBinding and only set this if it's not already set if (string.IsNullOrEmpty(request.ProtocolBinding)) request.ProtocolBinding = Saml20Constants.ProtocolBindings.HTTP_Post; XmlDocument req = request.GetXml(); XmlSignatureUtils.SignDocument(req, request.ID); builder.Request = req.OuterXml; AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_POST); builder.GetPage().ProcessRequest(context); return; } if(destination.Binding == SAMLBinding.ARTIFACT) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Artifact, idpEndpoint.Id)); HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context); //Honor the ForceProtocolBinding and only set this if it's not already set if(string.IsNullOrEmpty(request.ProtocolBinding)) request.ProtocolBinding = Saml20Constants.ProtocolBindings.HTTP_Artifact; AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT_ARTIFACT); builder.RedirectFromLogin(destination, request); } HandleError(context, Resources.BindingError); }
private void HandleRequest(HttpContext context) { Trace.TraceMethodCalled(GetType(), "HandleRequest()"); //Fetch the endpoint configuration IDPEndPoint idpEndpoint = RetrieveIDPConfiguration(context.Session[IDPLoginSessionKey].ToString()); IDPEndPointElement destination = DetermineEndpointConfiguration(SAMLBinding.REDIRECT, idpEndpoint.SLOEndpoint, idpEndpoint.metadata.SLOEndpoints()); //Fetch config object SAML20FederationConfig config = ConfigurationReader.GetConfig<SAML20FederationConfig>(); //Build the response object Saml20LogoutResponse response = new Saml20LogoutResponse(); response.Issuer = config.ServiceProvider.ID; response.Destination = destination.Url; response.StatusCode = Saml20Constants.StatusCodes.Success; string message = string.Empty; if(context.Request.RequestType == "GET") // HTTP Redirect binding { HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url); IDPEndPoint endpoint = config.FindEndPoint(idpEndpoint.Id); if (endpoint.metadata == null) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP"); HandleError(context, "Cannot find metadata for IdP " + idpEndpoint.Id); return; } Saml20MetadataDocument metadata = endpoint.metadata; if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.signing))) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Invalid signature redirect-binding, msg: " + parser.Message); HandleError(context, Resources.SignatureInvalid); return; } message = parser.Message; } else if (context.Request.RequestType == "POST") // HTTP Post binding { HttpPostBindingParser parser = new HttpPostBindingParser(context); if (!parser.IsSigned()) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message); HandleError(context, Resources.SignatureNotPresent); } IDPEndPoint endpoint = config.FindEndPoint(idpEndpoint.Id); if (endpoint.metadata == null) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP"); HandleError(context, "Cannot find metadata for IdP " + idpEndpoint.Id); return; } Saml20MetadataDocument metadata = endpoint.metadata; // handle a logout-request if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing))) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Invalid signature post-binding, msg: " + parser.Message); HandleError(context, Resources.SignatureInvalid); } message = parser.Message; }else { //Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS HandleError(context, Resources.UnsupportedRequestTypeFormat(context.Request.RequestType)); } AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, message); //Log the user out locally DoLogout(context, true); LogoutRequest req = Serialization.DeserializeFromXmlString<LogoutRequest>(message); response.InResponseTo = req.ID; //Respond using redirect binding if(destination.Binding == SAMLBinding.REDIRECT) { HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder(); builder.RelayState = context.Request.Params["RelayState"]; builder.Response = response.GetXml().OuterXml; builder.signingKey = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey; string s = destination.Url + "?" + builder.ToQuery(); context.Response.Redirect(s, true); return; } //Respond using post binding if (destination.Binding == SAMLBinding.POST) { HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination); builder.Action = SAMLAction.SAMLResponse; XmlDocument responseDocument = response.GetXml(); XmlSignatureUtils.SignDocument(responseDocument, response.ID); builder.Response = responseDocument.OuterXml; builder.RelayState = context.Request.Params["RelayState"]; builder.GetPage().ProcessRequest(context); return; } }
private void TransferClient(IDPEndPoint endpoint, HttpContext context) { Trace.TraceMethodCalled(GetType(), "TransferClient()"); Saml20LogoutRequest request = Saml20LogoutRequest.GetDefault(); AuditLogging.AssertionId = request.ID; AuditLogging.IdpId = endpoint.Id; // Determine which endpoint to use from the configuration file or the endpoint metadata. IDPEndPointElement destination = DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints()); request.Destination = destination.Url; string nameIdFormat = context.Session[IDPNameIdFormat].ToString(); request.SubjectToLogOut.Format = nameIdFormat; if (destination.Binding == SAMLBinding.POST) { HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination); request.Destination = destination.Url; request.Reason = Saml20Constants.Reasons.User; request.SubjectToLogOut.Value = context.User.Identity.Name; request.SessionIndex = context.Session[IDPSessionIdKey].ToString(); XmlDocument requestDocument = request.GetXml(); XmlSignatureUtils.SignDocument(requestDocument, request.ID); builder.Request = requestDocument.OuterXml; if(Trace.ShouldTrace(TraceEventType.Information)) Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "POST", endpoint.Id, requestDocument.OuterXml)); AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Binding: POST"); builder.GetPage().ProcessRequest(context); context.Response.End(); return; } if(destination.Binding == SAMLBinding.REDIRECT) { HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder(); builder.signingKey = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey; request.Destination = destination.Url; request.Reason = Saml20Constants.Reasons.User; request.SubjectToLogOut.Value = context.User.Identity.Name; request.SessionIndex = context.Session[IDPSessionIdKey].ToString(); builder.Request = request.GetXml().OuterXml; string redirectUrl = destination.Url + "?" + builder.ToQuery(); if (Trace.ShouldTrace(TraceEventType.Information)) Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "REDIRECT", endpoint.Id, redirectUrl)); AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Binding: Redirect"); context.Response.Redirect(redirectUrl, true); return; } if(destination.Binding == SAMLBinding.ARTIFACT) { if (Trace.ShouldTrace(TraceEventType.Information)) Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "ARTIFACT", endpoint.Id, string.Empty)); request.Destination = destination.Url; request.Reason = Saml20Constants.Reasons.User; request.SubjectToLogOut.Value = context.User.Identity.Name; request.SessionIndex = context.Session[IDPSessionIdKey].ToString(); HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context); AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Method: Artifact"); builder.RedirectFromLogout(destination, request, Guid.NewGuid().ToString("N")); } HandleError(context, Resources.BindingError); }
private void CreateAuthenticationFailedResponse() { string entityId = request.Issuer.Value; Saml20MetadataDocument metadataDocument = IDPConfig.GetServiceProviderMetadata(entityId); IDPEndPointElement endpoint = metadataDocument.AssertionConsumerServiceEndpoints().Find(delegate(IDPEndPointElement e) { return e.Binding == SAMLBinding.POST; }); if (endpoint == null) { Context.Response.Write(string.Format("'{0}' does not have a SSO endpoint that supports the POST binding.", entityId)); Context.Response.End(); return; } Response response = new Response(); response.Destination = endpoint.Url; response.Status = new Status(); response.Status.StatusCode = new StatusCode(); response.Status.StatusCode.Value = Saml20Constants.StatusCodes.Requester; response.Status.StatusCode.SubStatusCode = new StatusCode(); response.Status.StatusCode.SubStatusCode.Value = Saml20Constants.StatusCodes.AuthnFailed; response.Status.StatusMessage = "Authentication failed. Username and/or password was incorrect."; HttpPostBindingBuilder builder = new HttpPostBindingBuilder(endpoint); builder.Action = SAMLAction.SAMLResponse; builder.Response = Serialization.SerializeToXmlString(response); builder.GetPage().ProcessRequest(Context); Context.Response.End(); }
private void CreateAssertionResponse(User user) { string entityId = request.Issuer.Value; Saml20MetadataDocument metadataDocument = IDPConfig.GetServiceProviderMetadata(entityId); IDPEndPointElement endpoint = metadataDocument.AssertionConsumerServiceEndpoints().Find(delegate(IDPEndPointElement e) { return e.Binding == SAMLBinding.POST; }); if (endpoint == null) { Context.Response.Write(string.Format("'{0}' does not have a SSO endpoint that supports the POST binding.", entityId)); Context.Response.End(); return; } UserSessionsHandler.AddLoggedInSession(entityId); Response response = new Response(); response.Destination = endpoint.Url; response.InResponseTo = request.ID; response.Status = new Status(); response.Status.StatusCode = new StatusCode(); response.Status.StatusCode.Value = Saml20Constants.StatusCodes.Success; Assertion assertion = CreateAssertion(user, entityId); response.Items = new object[] { assertion }; // Serialize the response. XmlDocument assertionDoc = new XmlDocument(); assertionDoc.PreserveWhitespace = true; assertionDoc.LoadXml(Serialization.SerializeToXmlString(response)); // Sign the assertion inside the response message. XmlSignatureUtils.SignDocument(assertionDoc, assertion.ID, IDPConfig.IDPCertificate); HttpPostBindingBuilder builder = new HttpPostBindingBuilder(endpoint); builder.Action = SAMLAction.SAMLResponse; builder.Response = assertionDoc.OuterXml; builder.GetPage().ProcessRequest(Context); Context.Response.End(); }