protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); try { // Look up for the SP ID string referer = this.Request.UrlReferrer.AbsoluteUri; int i = -1; if (!referer.StartsWith(Services.LocalUri)) { 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"); } } // Get the saved SSO state, if any. // If there isn't saved state then receive the authentication request. // If there is saved state then we've just completed a local login in response // to a prior authentication request. SsoAuthnState ssoState = (SsoAuthnState)Session[SsoSessionKey]; // Receive the authentication request. AuthnRequest authnRequest = null; string relayState = null; if (i != -1) { Util.ReceiveAuthnRequest(this, out authnRequest, out relayState); if (authnRequest == null) { // No authentication request found. return; } } if (ssoState == null) { // Process the authentication request. bool forceAuthn = authnRequest.ForceAuthn; bool allowCreate = false; if (authnRequest.NameIdPolicy != null) { allowCreate = authnRequest.NameIdPolicy.AllowCreate; } ssoState = new SsoAuthnState(); ssoState.AuthnRequest = authnRequest; ssoState.RelayState = relayState; ssoState.IdpProtocolBinding = SamlBindingUri.UriToBinding(authnRequest.ProtocolBinding); ssoState.AssertionConsumerServiceURL = authnRequest.AssertionConsumerServiceUrl; // Determine whether or not a local login is required. bool requireLocalLogin = false; if (forceAuthn) { requireLocalLogin = true; } else { if (!User.Identity.IsAuthenticated & allowCreate) { requireLocalLogin = true; } } // If a local login is required then save the authentication request // and initiate a local login. if (requireLocalLogin) { // Save the SSO state. Session[SsoSessionKey] = ssoState; // Initiate a local login. System.Web.Security.FormsAuthentication.RedirectToLoginPage(); return; } } // Create a SAML response with the user's local identity, if any. ComponentPro.Saml2.Response samlResponse = Util.CreateSamlResponse(this); if (i != -1) { // Update the Relay state before sending SAML response. // Dynamically update the assertion consumer service URL corresponding to the service provider. ssoState.AssertionConsumerServiceURL = authnRequest.AssertionConsumerServiceUrl; } // Send the SAML response to the service provider. Util.SendSamlResponse(this, samlResponse, ssoState); } catch (Exception exception) { Trace.Write("IdentityProvider", "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; } }