/// <summary> /// Displays an error page. /// </summary> /// <param name="context">The current HTTP context.</param> /// <param name="errorMessage">The error message.</param> /// <param name="overrideConfigSetting">if set to <c>true</c> [override config setting].</param> public void HandleError(HttpContext context, string errorMessage, bool overrideConfigSetting) { Trace.TraceData(TraceEventType.Error, "Error: " + errorMessage); Boolean showError = SAML20FederationConfig.GetConfig().ShowError; String DEFAULT_MESSAGE = "Unable to validate SAML message!"; if (!string.IsNullOrEmpty(ErrorBehaviour) && ErrorBehaviour.Equals(dk.nita.saml20.config.ErrorBehaviour.THROWEXCEPTION.ToString())) { if (showError) { throw new Saml20Exception(errorMessage); } else { throw new Saml20Exception(DEFAULT_MESSAGE); } } else { ErrorPage page = new ErrorPage(); page.OverrideConfig = overrideConfigSetting; page.ErrorText = (showError) ? errorMessage?.Replace("\n", "<br />") : DEFAULT_MESSAGE; page.ProcessRequest(context); context.Response.End(); } }
/// <summary> /// Handles all artifact creations and redirects. /// </summary> /// <param name="destination">The destination.</param> /// <param name="localEndpointIndex">Index of the local endpoint.</param> /// <param name="signedSamlMessage">The signed saml message.</param> /// <param name="relayState">The query string relay state value to add to the communication</param> private void ArtifactRedirect(IDPEndPointElement destination, Int16 localEndpointIndex, XmlDocument signedSamlMessage, string relayState) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); string sourceId = config.ServiceProvider.ID; byte[] sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceId); byte[] messageHandle = ArtifactUtil.GenerateMessageHandle(); string artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle); _context.Cache.Insert(artifact, signedSamlMessage, null, DateTime.Now.AddMinutes(1), SamlCache.NoSlidingExpiration); string destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" + HttpUtility.UrlEncode(artifact); if (!string.IsNullOrEmpty(relayState)) { destinationUrl += "&relayState=" + relayState; } if (Trace.ShouldTrace(TraceEventType.Information)) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.CreatedArtifact, artifact, signedSamlMessage.OuterXml)); } _context.Response.Redirect(destinationUrl); }
/// <summary> /// Send an authentication request to the IDP. /// </summary> private void SendRequest(HttpContext context) { Trace.TraceMethodCalled(GetType(), "SendRequest()"); // See if the "ReturnUrl" - parameter is set. string returnUrl = context.Request.QueryString["ReturnUrl"]; if (!string.IsNullOrEmpty(returnUrl)) { context.Session["RedirectUrl"] = returnUrl; } IDPEndPoint idpEndpoint = RetrieveIDP(context); if (idpEndpoint == null) { //Display a page to the user where she can pick the IDP SelectSaml20IDP page = new SelectSaml20IDP(); page.ProcessRequest(context); return; } Saml20AuthnRequest authnRequest = Saml20AuthnRequest.GetDefault(); // VALTECH: Publish AssertionConsumerServiceURL which is missing in DK framework. Reguired by Logica idp. authnRequest.Request.AssertionConsumerServiceURL = SAML20FederationConfig.GetConfig().ServiceProvider.AssertionConsumerServiceURL ?? context.Request.Url.ToString(); TransferClient(idpEndpoint, authnRequest, context); }
/// <summary> /// Returns an instance of the class with meaningful default values set. /// </summary> /// <returns></returns> public static Saml20AuthnRequest GetDefault() { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); if (config.ServiceProvider == null || string.IsNullOrEmpty(config.ServiceProvider.ID)) { throw new Saml20FormatException(Resources.ServiceProviderNotSet); } Saml20AuthnRequest result = new Saml20AuthnRequest(); result.Issuer = config.ServiceProvider.ID; List <ConditionAbstract> audienceRestrictions = new List <ConditionAbstract>(1); AudienceRestriction audienceRestriction = new AudienceRestriction(); audienceRestriction.Audience = new List <string>(1); audienceRestriction.Audience.Add(config.ServiceProvider.ID); audienceRestrictions.Add(audienceRestriction); result.SetConditions(audienceRestrictions); return(result); }
/// <summary> /// Displays an error page. /// </summary> /// <param name="context">The current HTTP context.</param> /// <param name="errorMessage">The error message.</param> /// <param name="overrideConfigSetting">if set to <c>true</c> [override config setting].</param> public void HandleError(HttpContext context, string errorMessage, bool overrideConfigSetting) { Boolean showError = SAML20FederationConfig.GetConfig().ShowError; String DEFAULT_MESSAGE = "Unable to validate SAML message!"; if (!string.IsNullOrEmpty(ErrorBehaviour) && ErrorBehaviour.Equals(com.authright.saml2.config.ErrorBehaviour.THROWEXCEPTION.ToString())) { if (showError) { throw new Saml20Exception(errorMessage); } else { throw new Saml20Exception(DEFAULT_MESSAGE); } } else { ErrorPage page = new ErrorPage(); page.OverrideConfig = overrideConfigSetting; page.ErrorText = (showError) ? errorMessage : DEFAULT_MESSAGE; page.ProcessRequest(context); context.Response.End(); } }
/// <summary> /// Looks through the Identity Provider configurations and /// </summary> public IDPEndPoint RetrieveIDPConfiguration(string IDPId) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); config.Endpoints.Refresh(); return(config.FindEndPoint(IDPId)); }
protected void Page_Load(object sender, EventArgs e) { litIDPList.Text = "<ul>"; SAML20FederationConfig.GetConfig().Endpoints.IDPEndPoints.ForEach(idp => litIDPList.Text += "<li><a href=\"" + idp.GetIDPLoginUrl(false, false) + "\">" + (string.IsNullOrEmpty(idp.Name) ? idp.Id : idp.Name) + "</a></li>"); litIDPList.Text += "</ul>"; }
/// <summary> /// Creates an artifact for the LogoutRequest and redirects the user to the IdP. /// </summary> /// <param name="destination">The destination of the request.</param> /// <param name="request">The logout request.</param> /// <param name="relayState">The query string relay state value to add to the communication</param> public void RedirectFromLogout(IDPEndPointElement destination, Saml20LogoutRequest request, string relayState) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); Int16 index = (Int16)config.ServiceProvider.LogoutEndpoint.endPointIndex; XmlDocument doc = request.GetXml(); XmlSignatureUtils.SignDocument(doc, request.Request.ID); ArtifactRedirect(destination, index, doc, relayState); }
/// <summary> /// Helper method for generating URL to a link, that the user can click to select that particular IDPEndPoint for authorization. /// Usually not called directly, but called from IDPEndPoint.GetIDPLoginUrl() /// </summary> /// <param name="idpId">Id of IDP that an authentication URL is needed for</param> /// <param name="forceAuthn">Specifies wether or not the user is forced to login even if the user is already logged in. True means that the user must login into the federation again even if the user was already logged in.</param> /// <param name="isPassive">Specifies wether or not the user must be promthed with a login screen at IdP if user is not already logged into the federation. True means that the user must not be promthed with a login screen.</param> /// <param name="desiredNsisLoa">Specifies the desired level of assurance.</param> /// <param name="desiredProfile">Specifies the desired type of profile (Person or Professional)</param> /// <returns>A URL that can be used for logging in at the IDP</returns> public static string GetIDPLoginUrl(string idpId, bool forceAuthn, bool isPassive, string desiredNsisLoa, string desiredProfile) { return(string.Format("{0}?{1}={2}&{3}={4}&{5}={6}&{7}={8}&{9}={10}", SAML20FederationConfig.GetConfig().ServiceProvider.SignOnEndpoint.localPath, Saml20SignonHandler.IDPChoiceParameterName, HttpUtility.UrlEncode(idpId), Saml20SignonHandler.IDPForceAuthn, forceAuthn.ToString(), Saml20SignonHandler.IDPIsPassive, isPassive.ToString(), Saml20SignonHandler.NsisLoa, desiredNsisLoa, Saml20SignonHandler.Profile, desiredProfile)); }
/// <summary> /// Looks through the Identity Provider configurations and /// </summary> public IDPEndPoint RetrieveIDPConfiguration(string IDPId) { if (IDPId == null) { return(null); } SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); return(config.FindEndPoint(IDPId)); }
/// <summary> /// Decrypts an assertion we received from "fælles-offentlige brugerstyring". /// </summary> private static void DecryptFOBSAssertion(string file) { string assertionBase64 = File.ReadAllText(file); byte[] assertionBytes = Convert.FromBase64String(assertionBase64); XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; doc.Load(new MemoryStream(assertionBytes)); XmlNodeList encryptedList = doc.GetElementsByTagName(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION); Assert.That(encryptedList.Count == 1); // Do some mock configuration. FederationConfig config = FederationConfig.GetConfig(); config.AllowedAudienceUris.Audiences.Add("https://saml.safewhere.net"); SAML20FederationConfig descr = SAML20FederationConfig.GetConfig(); descr.Endpoints.MetadataLocation = @"Saml20\Protocol\MetadataDocs\FOBS"; // Set it manually. Assert.That(Directory.Exists(descr.Endpoints.MetadataLocation)); X509Certificate2 cert = new X509Certificate2(@"Saml20\Certificates\SafewhereTest_SFS.pfx", "test1234"); Saml20EncryptedAssertion encass = new Saml20EncryptedAssertion((RSA)cert.PrivateKey); encass.LoadXml((XmlElement)encryptedList[0]); encass.Decrypt(); // Retrieve metadata Saml20Assertion assertion = new Saml20Assertion(encass.Assertion.DocumentElement, null, false); IDPEndPoint endp = descr.FindEndPoint(assertion.Issuer); Assert.IsNotNull(endp, "Endpoint not found"); Assert.IsNotNull(endp.metadata, "Metadata not found"); try { assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer)); Assert.Fail("Verification should fail. Token does not include its signing key."); } catch (InvalidOperationException) {} Assert.IsNull(assertion.SigningKey, "Signing key is already present on assertion. Modify test."); IEnumerable <string> validationFailures; Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp, out validationFailures))); Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance."); }
/// <summary> /// Creates an artifact for the LogoutRequest and redirects the user to the IdP. /// </summary> /// <param name="idpEndPoint">The IdP endpoint</param> /// <param name="destination">The destination of the request.</param> /// <param name="request">The logout request.</param> /// <param name="relayState">The query string relay state value to add to the communication</param> public void RedirectFromLogout(IDPEndPoint idpEndPoint, IDPEndPointElement destination, Saml20LogoutRequest request, string relayState) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); Int16 index = (Int16)config.ServiceProvider.LogoutEndpoint.endPointIndex; XmlDocument doc = request.GetXml(); var signingCertificate = FederationConfig.GetConfig().GetFirstValidCertificate(); var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(idpEndPoint.ShaHashingAlgorithm); var signatureProvider = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm); signatureProvider.SignAssertion(doc, request.Request.ID, signingCertificate); ArtifactRedirect(destination, index, doc, relayState); }
private void GenerateMetadataExtensionDocument(HttpContext context) { SAML20FederationConfig configuration = SAML20FederationConfig.GetConfig(); string sdID = configuration.ServiceProvider.ID; string xmlTemplatePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Metadata/Templates/metadata.extended.template.xml"); string fileContents = File.ReadAllText(xmlTemplatePath).Replace("[[SP.ID]]", sdID); context.Response.Write(fileContents); //, doc.ToXml(context.Response.ContentEncoding) }
protected void Page_Load(object sender, EventArgs e) { Title = "My page on SP " + SAML20FederationConfig.GetConfig().ServiceProvider.ID; if (Request.QueryString["action"] == "sso") { // Example of logging required by the requirements BSA6/SSO6 ("Id of internal account that is matched to SAML Assertion") // Since FormsAuthentication is used in this sample, the user name to log can be found in context.User.Identity.Name. // This user will not be set until after a new redirect, so unfortunately we cannot just log it in our LogAction.LoginAction AuditLogging.logEntry(Direction.IN, Operation.LOGIN, "ServiceProvider login", "SP internal user id: " + (Context.User.Identity.IsAuthenticated ? Context.User.Identity.Name : "(not logged in)")); } }
private void CreateMetadataDocument(HttpContext context, bool sign) { SAML20FederationConfig configuration = SAML20FederationConfig.GetConfig(); KeyInfo keyinfo = new KeyInfo(); KeyInfoX509Data keyClause = new KeyInfoX509Data(FederationConfig.GetConfig().SigningCertificate.GetCertificate(), X509IncludeOption.EndCertOnly); keyinfo.AddClause(keyClause); Saml20MetadataDocument doc = new Saml20MetadataDocument(configuration, keyinfo, sign); context.Response.Write(doc.ToXml(context.Response.ContentEncoding)); }
/// <summary> /// Initializes a new instance of the <see cref="Saml20LogoutHandler"/> class. /// </summary> public Saml20LogoutHandler() { // Read the proper redirect url from config try { RedirectUrl = SAML20FederationConfig.GetConfig().ServiceProvider.LogoutEndpoint.RedirectUrl; ErrorBehaviour = SAML20FederationConfig.GetConfig().ServiceProvider.LogoutEndpoint.ErrorBehaviour.ToString(); } catch (Exception e) { if (Trace.ShouldTrace(TraceEventType.Error)) Trace.TraceData(TraceEventType.Error, e.ToString()); } }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Load"/> event. /// </summary> /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param> protected override void OnLoad(EventArgs e) { TitleText = Resources.ChooseIDP; HeaderText = Resources.ChooseIDP; BodyPanel.Controls.Add(new LiteralControl(Resources.ChooseDesc)); BodyPanel.Controls.Add(new LiteralControl("<br/><br/>")); SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); foreach (IDPEndPoint endPoint in config.IDPEndPoints) { if (endPoint.metadata != null) { HyperLink link = new HyperLink(); // Link text. If a name has been specified in web.config, use it. Otherwise, use id from metadata. link.Text = string.IsNullOrEmpty(endPoint.Name) ? endPoint.metadata.EntityId : endPoint.Name; string forceAuthnAsString = HttpContext.Current.Request.Params[Saml20SignonHandler.IDPForceAuthn]; bool forceAuthn; bool.TryParse(forceAuthnAsString, out forceAuthn); string isPassiveAsString = HttpContext.Current.Request.Params[Saml20SignonHandler.IDPIsPassive]; bool isPassive; bool.TryParse(isPassiveAsString, out isPassive); string desiredNsisLoa = HttpContext.Current.Request.Params[Saml20SignonHandler.NsisLoa]; string desiredProfile = HttpContext.Current.Request[Saml20SignonHandler.Profile]; link.NavigateUrl = endPoint.GetIDPLoginUrl(forceAuthn, isPassive, desiredNsisLoa, desiredProfile); BodyPanel.Controls.Add(link); BodyPanel.Controls.Add(new LiteralControl("<br/>")); } else { Label label = new Label(); label.Text = endPoint.Name; label.Style.Add(HtmlTextWriterStyle.TextDecoration, "line-through"); BodyPanel.Controls.Add(label); label = new Label(); label.Text = " (Metadata not found)"; label.Style.Add(HtmlTextWriterStyle.FontSize, "x-small"); BodyPanel.Controls.Add(label); BodyPanel.Controls.Add(new LiteralControl("<br/>")); } } }
/// <summary> /// Validates if a AssuranceLevel is equals to or higher than a minimum required AssuranceLevel. /// If validation fails, response is modified to display an error page. /// </summary> /// <returns>True if valid, otherwise false (and modified response).</returns> private bool ValidateAssuranceLevel(string assouranceLevel, HttpContext context, XmlElement assertionXml) { var minAL = SAML20FederationConfig.GetConfig().MinimumAssuranceLevel; if (assouranceLevel != null && int.TryParse(assouranceLevel, out var sourceLoaInt) && int.TryParse(minAL, out var minLoaInt) && sourceLoaInt >= minLoaInt) { return(true); } HandleLoaValidationError(Resources.NsisLoaTooLow, assouranceLevel, minAL, context, assertionXml); return(false); }
/// <summary> /// Gets a default instance of this class with meaningful default values set. /// </summary> /// <returns></returns> public static Saml20AttributeQuery GetDefault() { Saml20AttributeQuery result = new Saml20AttributeQuery(); SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); if (config.ServiceProvider == null || string.IsNullOrEmpty(config.ServiceProvider.ID)) { throw new Saml20FormatException(Resources.ServiceProviderNotSet); } result.Issuer = config.ServiceProvider.ID; return(result); }
/// <summary> /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. /// </summary> /// <param name="context">An <see cref="T:System.Web.SamlContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> public override void ProcessRequest(SamlHttpContext context) { try { Trace.TraceMethodCalled(GetType(), "ProcessRequest()"); SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); if (config == null) { throw new Saml20Exception("Missing SAML20Federation config section in web.config."); } Saml20ServiceEndpoint endp = config.ServiceProvider.serviceEndpoints.Find(delegate(Saml20ServiceEndpoint ep) { return(ep.endpointType == EndpointType.SIGNON); }); if (endp == null) { throw new Saml20Exception("Signon endpoint not found in configuration"); } string returnUrl = config.ServiceProvider.Server + endp.localPath + "?r=1"; SamlHttpCookie samlIdp = context.Request.Cookies[CommonDomainCookie.COMMON_DOMAIN_COOKIE_NAME]; if (samlIdp != null) { returnUrl += "&_saml_idp=" + HttpUtility.UrlEncode(samlIdp.Value); if (Trace.ShouldTrace(TraceEventType.Information)) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.CDC, samlIdp.Value)); } AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT, "Redirection to Signon endpoint found in Common Domain Cookie: " + samlIdp.Value); } else { AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT, "Redirection to Signon endpoint, no Common Domain Cookie found: " + returnUrl); } context.Response.Redirect(returnUrl); } catch (Exception ex) { HandleError(context, ex); } }
/// <summary> /// Handles a request. /// </summary> /// <param name="context">The context.</param> protected override void Handle(HttpContext context) { Trace.TraceMethodCalled(GetType(), "Handle()"); //Some IdP's are known to fail to set an actual value in the SOAPAction header //so we just check for the existence of the header field. if (Array.Exists(context.Request.Headers.AllKeys, delegate(string s) { return(s == SOAPConstants.SOAPAction); })) { SessionStore.AssertSessionExists(); HandleSOAP(context, context.Request.InputStream); return; } if (!string.IsNullOrEmpty(context.Request.Params["SAMLart"])) { SessionStore.AssertSessionExists(); HandleArtifact(context); } if (!string.IsNullOrEmpty(context.Request.Params["SamlResponse"])) { SessionStore.AssertSessionExists(); HandleResponse(context); } else { if (SAML20FederationConfig.GetConfig().CommonDomain.Enabled&& context.Request.QueryString["r"] == null && context.Request.Params["cidp"] == null) { AuditLogging.logEntry(Direction.OUT, Operation.DISCOVER, "Redirecting to Common Domain for IDP discovery"); context.Response.Redirect(SAML20FederationConfig.GetConfig().CommonDomain.LocalReaderEndpoint); } else { AuditLogging.logEntry(Direction.IN, Operation.ACCESS, "User accessing resource: " + context.Request.RawUrl + " without authentication."); SessionStore.CreateSessionIfNotExists(); SendRequest(context); } } }
/// <summary> /// Returns an instance of the class with meaningful default values set. /// </summary> /// <returns></returns> public static Saml20LogoutRequest GetDefault() { Saml20LogoutRequest result = new Saml20LogoutRequest(); result.SubjectToLogOut = new NameID(); //format SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); if (config.ServiceProvider == null || string.IsNullOrEmpty(config.ServiceProvider.ID)) { throw new Saml20FormatException(Resources.ServiceProviderNotSet); } result.Issuer = config.ServiceProvider.ID; return(result); }
/// <summary> /// Initializes a new instance of the <see cref="Saml20SignonHandler"/> class. /// </summary> public Saml20SignonHandler() { _certificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate(); // Read the proper redirect url from config try { RedirectUrl = SAML20FederationConfig.GetConfig().ServiceProvider.SignOnEndpoint.RedirectUrl; ErrorBehaviour = SAML20FederationConfig.GetConfig().ServiceProvider.SignOnEndpoint.ErrorBehaviour.ToString(); } catch (Exception e) { if (Trace.ShouldTrace(TraceEventType.Error)) { Trace.TraceData(TraceEventType.Error, e.ToString()); } } }
/// <summary> /// This method converts the received Saml assertion into a .Net principal. /// </summary> internal static IPrincipal InitSaml20Identity(Saml20AssertionLite assertion) { // Find IDPEndPoint IDPEndPoint point = SAML20FederationConfig.GetConfig().FindEndPoint(assertion.Issuer); bool isPersistentPseudonym = assertion.Subject.Format == Saml20Constants.NameIdentifierFormats.Persistent; // Protocol-level support for persistent pseudonyms: If a mapper has been configured, use it here before constructing the principal. string subjectIdentifier = assertion.Subject.Value; if (isPersistentPseudonym && point.PersistentPseudonym != null) { subjectIdentifier = point.PersistentPseudonym.GetMapper().MapIdentity(assertion.Subject); } // Create identity var identity = new Saml20Identity(subjectIdentifier, assertion.Attributes, isPersistentPseudonym ? assertion.Subject.Value : null); return(new GenericPrincipal(identity, new string[] { })); }
/// <summary> /// Performs the attribute query and adds the resulting attributes to Saml20Identity.Current. /// </summary> /// <param name="context">The http context.</param> public void PerformQuery(HttpContext context) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); string endpointId = Saml20PrincipalCache.GetSaml20AssertionLite().Issuer; if (string.IsNullOrEmpty(endpointId)) { Trace.TraceData(TraceEventType.Information, Tracing.AttrQueryNoLogin); throw new InvalidOperationException(Tracing.AttrQueryNoLogin); } IDPEndPoint ep = config.FindEndPoint(endpointId); if (ep == null) { throw new Saml20Exception(string.Format("Unable to find information about the IdP with id \"{0}\"", endpointId)); } PerformQuery(context, ep); }
/// <summary> /// Performs the attribute query and adds the resulting attributes to Saml20Identity.Current. /// </summary> /// <param name="context">The http context.</param> public void PerformQuery(HttpContext context) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); string endpointId = context.Session[Saml20AbstractEndpointHandler.IDPLoginSessionKey].ToString(); if (string.IsNullOrEmpty(endpointId)) { Trace.TraceData(TraceEventType.Information, Tracing.AttrQueryNoLogin); throw new InvalidOperationException(Tracing.AttrQueryNoLogin); } IDPEndPoint ep = config.FindEndPoint(endpointId); if (ep == null) { throw new Saml20Exception(string.Format("Unable to find information about the IdP with id \"{0}\"", endpointId)); } PerformQuery(context, ep); }
/// <summary> /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. /// </summary> /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> public override void ProcessRequest(HttpContext context) { try { Trace.TraceMethodCalled(GetType(), "ProcessRequest()"); SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); if (config == null) { throw new Saml20Exception("Missing SAML20Federation config section in web.config."); } Saml20ServiceEndpoint endp = config.ServiceProvider.serviceEndpoints.Find(delegate(Saml20ServiceEndpoint ep) { return(ep.endpointType == EndpointType.SIGNON); }); if (endp == null) { throw new Saml20Exception("Signon endpoint not found in configuration"); } string redirectUrl = (string)context.Session["RedirectUrl"]; if (!string.IsNullOrEmpty(redirectUrl)) { context.Session.Remove("RedirectUrl"); context.Response.Redirect(redirectUrl); } else if (string.IsNullOrEmpty(endp.RedirectUrl)) { context.Response.Redirect("~/"); } else { context.Response.Redirect(endp.RedirectUrl); } } catch (Exception ex) { HandleError(context, ex); } }
/// <summary> /// Determines which IdP an artifact has been sent from. /// </summary> /// <param name="artifact">The artifact.</param> /// <returns>An IdP configuration element</returns> private IDPEndPoint DetermineIdp(string artifact) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); short typeCodeValue = -1; short endPointIndex = -1; byte[] sourceIdHash = new byte[20]; byte[] messageHandle = new byte[20]; if (ArtifactUtil.TryParseArtifact(artifact, ref typeCodeValue, ref endPointIndex, ref sourceIdHash, ref messageHandle)) { foreach(IDPEndPoint ep in config.IDPEndPoints) { byte[] hash = ArtifactUtil.GenerateSourceIdHash(ep.Id); if (AreEqual(sourceIdHash, hash)) return ep; } } return null; }
public static IEnumerable <AsymmetricAlgorithm> GetTrustedSigners(string issuer) { if (issuer == null) { throw new ArgumentNullException("issuer"); } SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); IDPEndPoint idpEndpoint = config.FindEndPoint(issuer); if (idpEndpoint == null) { throw new InvalidOperationException(String.Format("No idp endpoint found for issuer {0}", issuer)); } if (idpEndpoint.metadata == null) { throw new InvalidOperationException(String.Format("No metadata found for issuer {0}", issuer)); } if (idpEndpoint.metadata.Keys == null) { throw new InvalidOperationException(String.Format("No key descriptors found in metadata found for issuer {0}", issuer)); } List <AsymmetricAlgorithm> result = new List <AsymmetricAlgorithm>(1); foreach (KeyDescriptor key in idpEndpoint.metadata.Keys) { KeyInfo ki = (KeyInfo)key.KeyInfo; foreach (KeyInfoClause clause in ki) { AsymmetricAlgorithm aa = XmlSignatureUtils.ExtractKey(clause); result.Add(aa); } } return(result); }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Load"/> event. /// </summary> /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param> protected override void OnLoad(EventArgs e) { TitleText = Resources.ChooseIDP; HeaderText = Resources.ChooseIDP; BodyPanel.Controls.Add(new LiteralControl(Resources.ChooseDesc)); BodyPanel.Controls.Add(new LiteralControl("<br/><br/>")); SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); foreach (IDPEndPoint endPoint in config.IDPEndPoints) { if (endPoint.metadata != null) { HyperLink link = new HyperLink(); // Link text. If a name has been specified in web.config, use it. Otherwise, use id from metadata. link.Text = string.IsNullOrEmpty(endPoint.Name) ? endPoint.metadata.EntityId : endPoint.Name; link.NavigateUrl = endPoint.GetIDPLoginUrl(); BodyPanel.Controls.Add(link); BodyPanel.Controls.Add(new LiteralControl("<br/>")); } else { Label label = new Label(); label.Text = endPoint.Name; label.Style.Add(HtmlTextWriterStyle.TextDecoration, "line-through"); BodyPanel.Controls.Add(label); label = new Label(); label.Text = " (Metadata not found)"; label.Style.Add(HtmlTextWriterStyle.FontSize, "x-small"); BodyPanel.Controls.Add(label); BodyPanel.Controls.Add(new LiteralControl("<br/>")); } } }