/// <summary> /// Sends the SAML response to the Service Provider. /// </summary> /// <param name="samlResponse">The SAML response object.</param> /// <param name="relayState">The relay state.</param> public static void SendResponse(Page page, ComponentPro.Saml2.Response samlResponse, string relayState) { // Sign the SAML response. X509Certificate2 x509Certificate = (X509Certificate2)page.Application[Global.IdPCertKey]; samlResponse.Sign(x509Certificate); switch (Global.AssertionServiceSamlBinding) { case SamlBinding.HttpPost: // Send the SAML Response object. samlResponse.SendPostBindingForm(page.Response.OutputStream, Global.AssertionServiceUrl, relayState); break; case SamlBinding.HttpArtifact: // Create the artifact. string identificationUrl = GetAbsoluteUrl(page, "~/"); Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(SamlArtifact.GetSourceId(identificationUrl), SamlArtifact.GetHandle()); // Convert the authentication request to XML and save to the application Cache. SamlSettings.CacheProvider.Insert(httpArtifact.ToString(), samlResponse.GetXml(), new TimeSpan(1, 0, 0)); // Send the artifact with POST form. httpArtifact.SendPostForm(page.Response.OutputStream, Global.AssertionServiceUrl, relayState); break; default: throw new ApplicationException("Invalid assertion consumer service binding."); } }
protected void Page_Load(object sender, EventArgs e) { try { // Get the artifact resolve request. ArtifactResolve artifactResolve = ArtifactResolve.Create(Request); // Create a new artifact. Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(artifactResolve.Artifact.ArtifactValue); // Remove the artifact state from the cache. XmlElement samlResponseXml = (XmlElement)SamlSettings.CacheProvider.Remove(httpArtifact.ToString()); if (samlResponseXml == null) { throw new ApplicationException("Invalid artifact."); } // Create an artifact response containing the cached SAML message. ArtifactResponse artifactResponse = new ArtifactResponse(); artifactResponse.Issuer = new Issuer(Util.GetAbsoluteUrl(this, "~/")); artifactResponse.Message = samlResponseXml; // Send the artifact response. artifactResponse.Send(Response); } catch (Exception exception) { Trace.Write("ServiceProvider", "An Error occurred", exception); } }
// Send the SAML response over the specified binding. public static void SendSamlResponse(Page page, ComponentPro.Saml2.Response samlResponse, SsoAuthnState ssoState) { // Sign the SAML response X509Certificate2 x509Certificate = (X509Certificate2)page.Application[Global.IdPCertKey]; samlResponse.Sign(x509Certificate); // Send the SAML response to the service provider. switch (ssoState.IdpProtocolBinding) { case SamlBinding.HttpPost: samlResponse.SendPostBindingForm(page.Response.OutputStream, ssoState.AssertionConsumerServiceURL, ssoState.RelayState); break; case SamlBinding.HttpArtifact: // Create the artifact. string identificationUrl = Util.GetAbsoluteUrl(page, "~/"); Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(SamlArtifact.GetSourceId(identificationUrl), SamlArtifact.GetHandle()); // Cache the authentication request for subsequent sending using the artifact resolution protocol. Sliding expiration time is 1 hour. SamlSettings.CacheProvider.Insert(httpArtifact.ToString(), samlResponse.GetXml(), new TimeSpan(1, 0, 0)); // Send the artifact. httpArtifact.SendPostForm(page.Response.OutputStream, ssoState.AssertionConsumerServiceURL, ssoState.RelayState); break; default: Trace.Write("IdentityProvider", "Invalid identity provider binding"); break; } }
protected void btnIdPLogin_Click(object sender, EventArgs e) { // Get the authentication request. Issuer issuer = new Issuer(Global.entityId); AuthnRequest authnRequest = Util.GetAuthnRequest(this); authnRequest.Issuer.NameIdentifier = Global.entityId; // Get SP Resource URL. string spResourceUrl = Util.GetAbsoluteUrl(this, FormsAuthentication.GetRedirectUrl("", false)); // Create relay state. string relayState = Guid.NewGuid().ToString(); // Save the SP Resource URL to the cache. SamlSettings.CacheProvider.Insert(relayState, spResourceUrl, new TimeSpan(1, 0, 0)); switch (Global.SingleSignOnServiceBinding) { case SamlBinding.HttpRedirect: X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.SpCertKey]; // Send authentication request using HTTP Redirect. System.Diagnostics.Debug.WriteLine("Sending redirect request to " + Global.SingleSignOnServiceURL); authnRequest.Redirect(Response, Global.SingleSignOnServiceURL, relayState, x509Certificate.PrivateKey, SignatureAlgorithms.RsaSha256); break; case SamlBinding.HttpPost: // Send authentication request using HTTP POST form. System.Diagnostics.Debug.WriteLine("Sending POST request to " + Global.SingleSignOnServiceURL); authnRequest.SendHttpPost(Response, Global.SingleSignOnServiceURL, relayState); // End the response. Response.End(); break; case SamlBinding.HttpArtifact: // Create a new http artifact. string identificationUrl = Util.GetAbsoluteUrl(this, "~/"); Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(SamlArtifact.GetSourceId(identificationUrl), SamlArtifact.GetHandle()); // Save the authentication request for subsequent sending using the artifact resolution protocol. SamlSettings.CacheProvider.Insert(httpArtifact.ToString(), authnRequest.GetXml(), new TimeSpan(1, 0, 0)); // Send the artifact using HTTP POST form. httpArtifact.SendHttpPost(Response.OutputStream, Global.SingleSignOnServiceURL, relayState); // End the response. Response.End(); break; default: throw new ApplicationException("Invalid binding type"); } }
protected void btnIdPLogin_Click(object sender, EventArgs e) { // Get the authentication request. AuthnRequest authnRequest = Util.GetAuthnRequest(this); // Get SP Resource URL. string spResourceUrl = Util.GetAbsoluteUrl(this, FormsAuthentication.GetRedirectUrl("", false)); // Create relay state. string relayState = Guid.NewGuid().ToString(); // Save the SP Resource URL to the cache. SamlSettings.CacheProvider.Insert(relayState, spResourceUrl, new TimeSpan(1, 0, 0)); switch (Global.SingleSignOnServiceBinding) { case SamlBinding.HttpRedirect: X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.SpCertKey]; // Send authentication request using HTTP Redirect. authnRequest.Redirect(Response, Global.SingleSignOnServiceURL, relayState, x509Certificate.PrivateKey); break; case SamlBinding.HttpPost: // Send authentication request using HTTP POST form. authnRequest.SendHttpPost(Response, Global.SingleSignOnServiceURL, relayState); // End the response. Response.End(); break; case SamlBinding.HttpArtifact: // Create a new http artifact. string identificationUrl = Util.GetAbsoluteUrl(this, "~/"); Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(SamlArtifact.GetSourceId(identificationUrl), SamlArtifact.GetHandle()); // Save the authentication request for subsequent sending using the artifact resolution protocol. SamlSettings.CacheProvider.Insert(httpArtifact.ToString(), authnRequest.GetXml(), new TimeSpan(1, 0, 0)); // Send the artifact using HTTP POST form. httpArtifact.SendPostForm(Response.OutputStream, Global.SingleSignOnServiceURL, relayState); // End the response. Response.End(); break; default: throw new ApplicationException("Invalid binding type"); } }
/// <summary> /// Processes the SAML response received from the IdP. /// </summary> /// <param name="page">The page object.</param> /// <param name="relayState">The relay state</param> /// <param name="samlResponse">The SAML response object.</param> public static void ProcessResponse(Page page, out ComponentPro.Saml2.Response samlResponse, out string relayState) { // Extract the binding type from the query string. string bindingType = page.Request.QueryString["binding"]; switch (bindingType) { case "artifact": // Create an artifact from the query string. Saml2ArtifactType0004 httpArtifact = Saml2ArtifactType0004.CreateFromHttpArtifactQueryString(page.Request); // Create an artifact resolve request. ArtifactResolve artifactResolve = new ArtifactResolve(); artifactResolve.Issuer = new Issuer(GetAbsoluteUrl(page, "~/")); artifactResolve.Artifact = new Artifact(httpArtifact.ToString()); // Send the artifact resolve request and create an artifact response from the received XML. ArtifactResponse artifactResponse = ArtifactResponse.SendSamlMessageReceiveAftifactResponse(Global.ArtifactServiceUrl, artifactResolve); // Get the SAML Response from the artifact response. samlResponse = new ComponentPro.Saml2.Response(artifactResponse.Message); relayState = httpArtifact.RelayState; break; case "post": System.Diagnostics.Debug.WriteLine("POST"); // Create a SAML response from the form data. samlResponse = ComponentPro.Saml2.Response.Create(page.Request); relayState = samlResponse.RelayState; break; default: throw new ApplicationException("Unknown binding type"); } // Is the SAML response signed? if (samlResponse.IsSigned()) { // Get the previously loaded certificate. X509Certificate2 x509Certificate = (X509Certificate2)page.Application[Global.IdPCertKey]; // Validate the certificate. if (!samlResponse.Validate(x509Certificate)) { throw new ApplicationException("The SAML response signature failed to verify."); } } }
/// <summary> /// Processes the authentication request. /// </summary> /// <param name="authnRequest">The AuthnRequest object.</param> /// <param name="relayState">The relayState string.</param> public static void ProcessAuthnRequest(Page page, out AuthnRequest authnRequest, out string relayState) { // Use a single endpoint and use a query string parameter to determine the Service Provider to Identity Provider binding type. string bindingType = page.Request.QueryString[SP2IdPBindingTypeVar]; // Get the previously loaded certificate. X509Certificate2 cert = (X509Certificate2)page.Application[Global.SPCertKey]; switch (bindingType) { case RedirectBinding: authnRequest = AuthnRequest.Create(page.Request.RawUrl, cert.PublicKey.Key); relayState = authnRequest.RelayState; break; case PostBinding: authnRequest = AuthnRequest.CreateFromHttpPost(page.Request); relayState = authnRequest.RelayState; break; case ArtifactBinding: Saml2ArtifactType0004 httpArtifact = Saml2ArtifactType0004.CreateFromHttpArtifactHttpForm(page.Request); // Create an artifact resolve request. ArtifactResolve artifactResolve = new ArtifactResolve(); artifactResolve.Issuer = new Issuer(new Uri(page.Request.Url, page.ResolveUrl("~/")).ToString()); artifactResolve.Artifact = new Artifact(httpArtifact.ToString()); // Send the SAML Artifact Resolve Request and parse the received response. ArtifactResponse artifactResponse = ArtifactResponse.SendSamlMessageReceiveAftifactResponse(Global.ArtifactResolutionUrl, artifactResolve); // Extract the authentication request from the received artifact response. authnRequest = new AuthnRequest(artifactResponse.Message); relayState = httpArtifact.RelayState; break; default: throw new ApplicationException("Invalid binding type"); } if (authnRequest.IsSigned()) { if (!authnRequest.Validate(cert)) { throw new ApplicationException("The authentication request signature failed to verify."); } } }
/// <summary> /// Receives the SAML response from the identity provider. /// </summary> /// <param name="samlResponse"></param> /// <param name="relayState"></param> private void ReceiveResponse(out ComponentPro.Saml2.Response samlResponse, out string relayState) { // Determine the identity provider to service provider binding type. // We use a query string parameter rather than having separate endpoints per binding. string bindingType = Request.QueryString[Util.BindingVarName]; switch (bindingType) { case SamlBindingUri.HttpPost: samlResponse = ComponentPro.Saml2.Response.Create(Request); relayState = samlResponse.RelayState; break; case SamlBindingUri.HttpArtifact: Saml2ArtifactType0004 httpArtifact = Saml2ArtifactType0004.CreateFromHttpArtifactHttpForm(Request); // Create an artifact resolve request. ArtifactResolve artifactResolve = new ArtifactResolve(); artifactResolve.Issuer = new Issuer(Util.GetAbsoluteUrl(this, "~/")); artifactResolve.Artifact = new Artifact(httpArtifact.ToString()); // Send the artifact resolve request and receive the artifact response. string spArtifactResponderUrl = WebConfigurationManager.AppSettings["ArtifactIdProviderUrl"]; ArtifactResponse artifactResponse = ArtifactResponse.SendSamlMessageReceiveAftifactResponse(spArtifactResponderUrl, artifactResolve); // Extract the authentication request from the artifact response. samlResponse = new Response(artifactResponse.Message); relayState = httpArtifact.RelayState; break; default: Trace.Write("ServiceProvider", "Invalid identity provider to service provider binding"); samlResponse = null; relayState = null; return; } // Verify the response's signature. X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.IdPCertKey]; if (!samlResponse.Validate(x509Certificate)) { throw new System.ApplicationException("The SAML response signature failed to verify."); } }
/// <summary> /// Handles the IdpLogin button to requests login at the Identify Provider site. /// </summary> /// <param name="sender">The button object.</param> /// <param name="e">The event arguments.</param> protected void btnIdPLogin_Click(object sender, EventArgs e) { // Create the authentication request. AuthnRequest authnRequest = BuildAuthenticationRequest(); // Create and cache the relay state so we remember which SP resource the user wishes // to access after SSO. string spResourceUrl = Util.GetAbsoluteUrl(this, FormsAuthentication.GetRedirectUrl("", false)); string relayState = Guid.NewGuid().ToString(); SamlSettings.CacheProvider.Insert(relayState, spResourceUrl, new TimeSpan(1, 0, 0)); // Send the authentication request to the identity provider over the selected binding. string idpUrl = string.Format("{0}?{1}={2}", WebConfigurationManager.AppSettings["SingleSignonIdProviderUrl"], Util.BindingVarName, HttpUtility.UrlEncode(spToIdPBindingList.SelectedValue)); switch (spToIdPBindingList.SelectedValue) { case SamlBindingUri.HttpRedirect: X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.SPCertKey]; authnRequest.Redirect(Response, idpUrl, relayState, x509Certificate.PrivateKey); break; case SamlBindingUri.HttpPost: authnRequest.SendHttpPost(Response, idpUrl, relayState); // Don't send this form. Response.End(); break; case SamlBindingUri.HttpArtifact: // Create the artifact. string identificationUrl = Util.GetAbsoluteUrl(this, "~/"); Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(SamlArtifact.GetSourceId(identificationUrl), SamlArtifact.GetHandle()); // Cache the authentication request for subsequent sending using the artifact resolution protocol. SamlSettings.CacheProvider.Insert(httpArtifact.ToString(), authnRequest.GetXml(), new TimeSpan(1, 0, 0)); // Send the artifact. httpArtifact.Redirect(Response, idpUrl, relayState); break; } }
protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); try { // Receive the artifact resolve request. ArtifactResolve artifactResolve = ArtifactResolve.Create(Request); // Get the artifact. Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(artifactResolve.Artifact.ArtifactValue); // Remove the artifact state from the cache. XmlElement samlResponseXml = (XmlElement)SamlSettings.CacheProvider.Remove(httpArtifact.ToString()); if (samlResponseXml == null) { return; } // Create an artifact response containing the cached SAML message. ArtifactResponse artifactResponse = new ArtifactResponse(); artifactResponse.Issuer = new Issuer(new Uri(Request.Url, ResolveUrl("~/")).ToString()); artifactResponse.Message = samlResponseXml; // Send the artifact response. artifactResponse.Send(Response); } catch (Exception exception) { Trace.Write("ServiceProvider", "An Error occurred", exception); } }
protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); try { // Process the artifact resolve request received from the identity provider in response // to the artifact sent by the service provider. ArtifactResolve artifactResolve = ArtifactResolve.Create(Request); // Get the artifact. Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(artifactResolve.Artifact.ArtifactValue); // Remove the artifact state from the cache. XmlElement artifactXml = (XmlElement)SamlSettings.CacheProvider.Remove(httpArtifact.ToString()); if (artifactXml == null) { return; } // Create an artifact response containing the cached SAML message. ArtifactResponse artifactResponse = new ArtifactResponse(); artifactResponse.Issuer = new Issuer(Util.GetAbsoluteUrl(this, "~/")); artifactResponse.Message = artifactXml; // Send the artifact response. artifactResponse.Send(Response); } catch (System.Exception exception) { Trace.Write("ServiceProvider", "Error in artifact responder", exception); } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { // Create a new Artifact Resolve from the request stream. ArtifactResolve artifactResolve = ArtifactResolve.Create(Request); // Get the ArtifactType0004. Saml2ArtifactType0004 httpArtifact = new Saml2ArtifactType0004(artifactResolve.Artifact.ArtifactValue); // Remove the saved http artifact from the cache. XmlElement samlResponseXml = (XmlElement)SamlSettings.CacheProvider.Remove(httpArtifact.ToString()); if (samlResponseXml == null) { throw new ApplicationException("Invalid artifact."); } // Create an ArtifactResponse. ArtifactResponse artifactResponse = new ArtifactResponse(); Uri uri = new Uri(Request.Url, ResolveUrl("~/")); artifactResponse.Issuer = new Issuer(uri.ToString()); // Add the SAML response XML to the artifact response. artifactResponse.Message = samlResponseXml; // Send the artifact response. artifactResponse.Send(Response); } catch (Exception exception) { Trace.Write("IdentityProvider", "An Error occurred", exception); } }
// Receive the authentication request from the service provider. public static void ReceiveAuthnRequest(Page page, out AuthnRequest authnRequest, out string relayState) { // Determine the service provider to identity provider binding type. // We use a query string parameter rather than having separate endpoints per binding. string bindingType = page.Request.QueryString[BindingQueryParameter]; switch (bindingType) { case SamlBindingUri.HttpRedirect: X509Certificate2 x509Certificate = (X509Certificate2)page.Application[Global.SPCertKey]; authnRequest = AuthnRequest.Create(page.Request.RawUrl, x509Certificate.PublicKey.Key); relayState = authnRequest.RelayState; break; case SamlBindingUri.HttpPost: authnRequest = AuthnRequest.CreateFromHttpPost(page.Request); relayState = authnRequest.RelayState; break; case SamlBindingUri.HttpArtifact: // Receive the artifact. Saml2ArtifactType0004 httpArtifact = Saml2ArtifactType0004.CreateFromHttpArtifactQueryString(page.Request); // Create an artifact resolve request. ArtifactResolve artifactResolve = new ArtifactResolve(); artifactResolve.Issuer = new Issuer(Util.GetAbsoluteUrl(page, "~/")); artifactResolve.Artifact = new Artifact(httpArtifact.ToString()); // Look up for the appropriate artifact SP url string referer = page.Request.UrlReferrer.AbsoluteUri; int i; for (i = 0; i < Services.AllowedServiceUrls.Length; i++) { string url = Services.AllowedServiceUrls[i]; if (referer.StartsWith(url)) { break; } } if (i == Services.AllowedServiceUrls.Length) { throw new Exception("Your SP is not allowed"); } // Send the artifact resolve request and receive the artifact response. string artifactServiceProviderUrl = Services.ArtifactServiceProviderUrls[i]; ArtifactResponse artifactResponse = ArtifactResponse.SendSamlMessageReceiveAftifactResponse(artifactServiceProviderUrl, artifactResolve); // Extract the authentication request from the artifact response. authnRequest = new AuthnRequest(artifactResponse.Message); relayState = httpArtifact.RelayState; break; default: Trace.Write("IdentityProvider", "Invalid service provider to identity provider binding"); authnRequest = null; relayState = null; return; } // If using HTTP redirect the message isn't signed as the generated query string is too long for most browsers. if (bindingType != SamlBindingUri.HttpRedirect) { if (authnRequest.IsSigned()) { // Verify the request's signature. X509Certificate2 x509Certificate = (X509Certificate2)page.Application[Global.SPCertKey]; if (!authnRequest.Validate(x509Certificate)) { throw new ApplicationException("The authentication request signature failed to verify."); } } } }