Beispiel #1
0
        public void InvokeSingleSignOn(HttpContext context)
        {
            try
            {
                // Extract SAMLRequest information from httpRequest
                string strRequestId = string.Format("id-{0}", Guid.NewGuid());

                SAMLAuthnRequest request = GetSignedSamlAuthnRequest(strRequestId, "2.0", "https://www.google.com/", "");

                // Read SingleSignOn Cookie => return value might be null => checked by SAMLIdentityProvider
                UserContext.Current = SingleSignOnCookie.GetSingleSignOnUserInfo(context);

                // Read additional attributes from Cookie, which were added via extender
                IEnumerable <SAMLAssertionAttribute> additionalAttributes = SingleSignOnCookie.GetAttributes(context);

                // Process SAMLAuthnRequest and Signature and create SAMLAuthnResponse
                SAMLIdentityProvider identityProvider = new SAMLIdentityProvider();
                SAMLAuthnResponse    response         = identityProvider.CreateResponse(request, additionalAttributes == null ? null : additionalAttributes.ToArray());

                // Render self-submitting HTMl-Form to respond to the SAMLAuthnRequest
                RenderSAMLResponse(context, request, response);
            }
            catch (Exception ex)
            {
                AdeNetSingleSignOn.Log.Error(ex);
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
Beispiel #2
0
        public void ProcessRequest(HttpContext context)
        {
            try
            {
                // Extract SAMLRequest information from httpRequest
                SAMLAuthnRequest request = GetSAMLAuthnRequestFromContext(context);
                AdeNetSingleSignOn.Log.Info("A new SAMLAuthnRequest is being processed.", request);

                // Read SingleSignOn Cookie => return value might be null => checked by SAMLIdentityProvider
                UserContext.Current = SingleSignOnCookie.GetSingleSignOnUserInfo(context);

                // Read additional attributes from Cookie, which were added via extender
                IEnumerable <SAMLAssertionAttribute> additionalAttributes = SingleSignOnCookie.GetAttributes(context);

                // Process SAMLAuthnRequest and Signature and create SAMLAuthnResponse
                SAMLIdentityProvider identityProvider = new SAMLIdentityProvider();
                SAMLAuthnResponse    response         = identityProvider.CreateResponse(request, additionalAttributes == null ? null : additionalAttributes.ToArray());

                // Render self-submitting HTMl-Form to respond to the SAMLAuthnRequest
                RenderSAMLResponse(context, request, response);
            }
            catch (Exception ex)
            {
                AdeNetSingleSignOn.Log.Error(ex);
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
        private SAMLAuthnResponse CreateFailureResponse(SAMLAuthnRequest request, string strRequestId, string strIssuerURN, string strTopLevelSamlTopLevelStatusCode, string strStatusMessage,
                                                        params string[] strSecondLevelSAMLStatusCodes)
        {
            // Response - Root-Element
            XElement elementResponse = CreateResponseElement(strRequestId, strIssuerURN);

            // Issuer Element
            elementResponse.Add(
                new XElement(SAML_ASSERTION_NAMESPACE + "Issuer", SystemSettings <SingleSignOnSystemSettings> .Current.SamlServiceEntityId,
                             new XAttribute(XNamespace.Xmlns + SAML_ASSERTION_NAMESPACE_PREFIX, SAML_ASSERTION_NAMESPACE)));

            // Status Element
            elementResponse.Add(CreateStatusElement(strTopLevelSamlTopLevelStatusCode, strStatusMessage, strSecondLevelSAMLStatusCodes));

            // Create Response
            XDocument samlResponseXml = new XDocument(elementResponse);

            // Sign Assertion Element
            string            strSignedXmlResponseString = CreateSignedDocumentString(samlResponseXml, STATUS_ELEMENT_NAME, SAML_PROTOCOL_NAMESPACE_PREFIX, SAML_PROTOCOL_NAMESPACE.NamespaceName, "");
            SAMLAuthnResponse response = CreateAuthnResponse(strIssuerURN, strSignedXmlResponseString, request.RelayState);

            // Log the Error
            AdeNetSingleSignOn.Log.Error(strStatusMessage, strRequestId, request, response);

            return(response);
        }
Beispiel #4
0
        public SAMLAuthnRequest GetSignedSamlAuthnRequest(string strRequestId, string strVersion, string strDestination, string strIssuer)
        {
            XDocument        samlRequestDocument = GetSamlRequestDocument(strRequestId, strVersion, strDestination, strIssuer);
            string           strSignedRequest    = CreateSignedRequestValue(samlRequestDocument.ToString(), "#" + strRequestId);
            SAMLAuthnRequest request             = new SAMLAuthnRequest
            {
                HttpMethod  = "POST",
                RelayState  = "http://localhost/SAMLServiceProviderSimulator/default.aspx",
                SAMLRequest = strSignedRequest
            };

            return(request);
        }
        private ValidateResult ValidateAuthnRequest(SAMLAuthnRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            try
            {
                XmlDocument samlRequest = new XmlDocument();
                samlRequest.LoadXml(request.SAMLRequest);

                XmlNodeList nodesXMLSignatures = samlRequest.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");

                // Checking If the Response or the Assertion has been signed once and only once.
                if (nodesXMLSignatures.Count != 1)
                {
                    return(ValidateResult.Failure(string.Format("Number of <signature> elements in AuthnRequest is invalid. Expected number is 1. Actual number is {0}.", nodesXMLSignatures.Count)));
                }

                SignedXml signedSamlXml = new SignedXml(samlRequest);
                signedSamlXml.LoadXml((XmlElement)nodesXMLSignatures[0]);

                // Use KeyInfo-Element (X509Data) of the Signature-Element to instantiate the X509Certificate
                KeyInfoX509Data  keyInfoData          = signedSamlXml.Signature.KeyInfo.OfType <KeyInfoX509Data>().First();
                X509Certificate2 signatureCertificate = keyInfoData.Certificates[0] as X509Certificate2;

                if (!this.SAMLCertificateManager.IsValidAuthnRequestSignature(signedSamlXml, signatureCertificate))
                {
                    return(ValidateResult.Failure("Invalid digital Signature detected."));
                }
                if (!this.SAMLCertificateManager.IsValidAuthnRequestCertificate(signatureCertificate))
                {
                    return(ValidateResult.Failure("Signature-Certificate invalid."));
                }
                if (!this.SAMLCertificateManager.IsAuthorizedAuthnRequestCertificate(signatureCertificate))
                {
                    return(ValidateResult.Failure("Certificate Issuer not authorized for single sign on."));
                }
            }
            catch (Exception ex)
            {
                string strMessage = string.Format("AuthnRequest-Validation failed for user with E-Mail '{0}'. Message: {1}", UserContext.Current.EMail, ex.Message);
                AdeNetSingleSignOn.Log.Error(strMessage, ex, request);
                return(ValidateResult.Failure("An error occured while validating the signature-certificate."));
            }

            return(ValidateResult.Success);
        }
Beispiel #6
0
        private void RenderSAMLResponse(HttpContext context, SAMLAuthnRequest request, SAMLAuthnResponse response)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }
            if (string.IsNullOrWhiteSpace(response.SAMLAssertionConsumerServiceURL))
            {
                throw new Exception("SAMLAssertionConsumerServiceURL cannot be empty.");
            }

            AdeNetSingleSignOn.Log.Info("SAMLAuthnResponse corresponding to the previously processed SAMLAuthnRequest.", request, response);

            string strHtmlForm =
                string.Format(@"
								<html xmlns='http://www.w3.org/1999/xhtml'>
									<body onLoad='document.forms.formSAMLResponse.submit();'>
										<form id='formSAMLResponse' method='POST' action='{0}'>
											<input name='{1}' type='hidden' value='{2}' />
											<input name='{3}' type='hidden' value='{4}' />
										</form>
									</body>
								</html>"                                ,
                              response.SAMLAssertionConsumerServiceURL,
                              SAML_RESPONSE_FORM_ELEMENT_ID,
                              Convert.ToBase64String(Encoding.UTF8.GetBytes(response.SAMLResponse)),
                              SAML_RELAYSTATE_FORM_ELEMENT_ID,
                              response.RelayState);

            context.Response.StatusCode = (int)HttpStatusCode.OK;
            context.Response.Write(strHtmlForm);
        }
        internal SAMLAuthnResponse CreateResponse(SAMLAuthnRequest request, params SAMLAssertionAttribute[] additionalAttributes)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            /* Extracting AuthnRequest values */
            // Convert request string to xml-format
            XDocument samlXmlDocument = XDocument.Parse(request.SAMLRequest);
            XElement  elementRequest  = samlXmlDocument.Element(SAML_PROTOCOL_NAMESPACE + "AuthnRequest");

            if (elementRequest == null)
            {
                throw new InvalidOperationException("Missing root element 'AuthnRequest'.");
            }

            // Extract element and attribute values
            string strRequestID   = (string)elementRequest.Attribute("ID");
            string strVersion     = (string)elementRequest.Attribute("Version");
            string strDestination = (string)elementRequest.Attribute("Destination");
            string strIssuer      = (string)elementRequest.Element(SAML_ASSERTION_NAMESPACE + "Issuer");

            /* Checking AuthnRequest values */
            // Check ID Attribute
            if (string.IsNullOrWhiteSpace(strRequestID))
            {
                throw new InvalidOperationException("Attribute 'ID' of the <AuthnRequest/> element is not present.");
            }

            // Check Request Method
            if (request.HttpMethod != "POST")
            {
                // Only POST requests are accepted
                string strStatusMessage = string.Format("SAMLAuthnRequest was made via HttpMethod '{0}' when only HttpMethod 'POST' is supported.", request.HttpMethod);
                return(CreateFailureResponse(request, strRequestID, strIssuer, SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_REQUESTER, strStatusMessage,
                                             SAMLSecondLevelStatusCode.SAML_SECONDLEVEL_STATUSCODE_REQUESTUNSUPPORTED));
            }

            // Check Version
            if (strVersion != SAML_VERSION)
            {
                string strStatusMessage = string.Format("Version of SAMLAuthnRequest was '{0}' but only Version '2.0' is supported.", strVersion);
                return(CreateFailureResponse(request, strRequestID, strIssuer, SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_VERSION_MISMATCH, strStatusMessage,
                                             SAMLSecondLevelStatusCode.SAML_SECONDLEVEL_STATUSCODE_REQUESTVERSIONDEPRECATED));
            }

            // Check Destination
            string strSamlServiceLocationURL = SystemSettings <SingleSignOnSystemSettings> .Current.SamlServiceLocationURL;

            if (string.IsNullOrWhiteSpace(strSamlServiceLocationURL))
            {
                AdeNetSingleSignOn.Log.Warn("The SamlServiceLocationURL for SingleSignOn on the IdentityProvider is not configured in the systemsettings.");
            }
            else if (!string.Equals(strDestination, strSamlServiceLocationURL, StringComparison.InvariantCultureIgnoreCase))
            {
                string strStatusMessage = string.Format("SAMLAuthnRequest Destination-Attribute with value '{0}' does not match the configured url in the systemsettings with value '{1}'.", strDestination, SystemSettings <SingleSignOnSystemSettings> .Current.SamlServiceLocationURL);
                return(CreateFailureResponse(request, strRequestID, strIssuer, SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_REQUESTER, strStatusMessage,
                                             SAMLSecondLevelStatusCode.SAML_SECONDLEVEL_STATUSCODE_REQUESTUNSUPPORTED));
            }

            // Check Issuer
            if (!SingleSignOnConfiguration.IsRequestIssuerConfigured())
            {
                throw new Exception("SAMLAuthnResponse cannot be transmitted because there is no SamlRequestIssuer configured in the systemsettings.");
            }
            ValidateResult resultRequestIssuer = SingleSignOnConfiguration.IsValidRequestIssuer(strIssuer);

            if (!resultRequestIssuer.Valid)
            {
                return(CreateFailureResponse(request, strRequestID, strIssuer, SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_REQUESTER, resultRequestIssuer.Message));
            }

            if (UserContext.Current.IsAnonymous)
            {
                // No Single Sign On information found
                return(CreateFailureResponse(request,
                                             strRequestID,
                                             strIssuer,
                                             SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_RESPONDER,
                                             "SingleSignOn Authentication failed. No user information available from prior user authentication.",
                                             SAMLSecondLevelStatusCode.SAML_SECONDLEVEL_STATUSCODE_AUTHNFAILED));
            }

            // Validate Request Certificate
            ValidateResult result = ValidateAuthnRequest(request);

            if (!result)
            {
                return(CreateFailureResponse(request, strRequestID, strIssuer, SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_REQUESTER, result.Message, SAMLSecondLevelStatusCode.SAML_SECONDLEVEL_STATUSCODE_REQUESTDENIED));
            }

            return(CreateSuccessResponse(strRequestID, strIssuer, request.RelayState, additionalAttributes));
        }