private SAMLAuthnResponse CreateAuthnResponse(string strIssuer, string strResponseString, string strRelayState)
 {
     return(new SAMLAuthnResponse
     {
         // Response-String with SAML Assertion
         SAMLResponse = strResponseString,
         // RelayState as submitted in the AuthnRequest
         RelayState = strRelayState,
         // Target URL for the AuthnResponse
         SAMLAssertionConsumerServiceURL = SingleSignOnConfiguration.GetAssertionConsumerServiceURLByRequestIssuer(strIssuer)
     });
 }
        private XElement CreateResponseElement(string strRequestId, string strIssuerURN)
        {
            string strIssueInstantTimeStamp = UserContext.Current.Now.ToUniversalTime().ToString("O");

            /* <saml2p:Response Destination="https://feds.eiam.admin.ch/adfs/ls/"
             *					ID="Response_f21ccc44a172149d99dce0b83b059918808bf460"
             *					InResponseTo="id-6250a3ec-0a4a-4305-ab59-6397c0d93da4"
             *					IssueInstant="2015-01-12T17:34:26.875Z"
             *					Version="2.0"
             *					xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> */

            return(new XElement(SAML_PROTOCOL_NAMESPACE + "Response",
                                new XAttribute("Destination", SingleSignOnConfiguration.GetAssertionConsumerServiceURLByRequestIssuer(strIssuerURN)),
                                new XAttribute("ID", string.Format("Response_{0}", Guid.NewGuid())),
                                new XAttribute("InResponseTo", strRequestId),
                                new XAttribute("IssueInstant", strIssueInstantTimeStamp),
                                new XAttribute("Version", "2.0"),
                                new XAttribute(XNamespace.Xmlns + SAML_PROTOCOL_NAMESPACE_PREFIX, SAML_PROTOCOL_NAMESPACE)));
        }
        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));
        }
        private SAMLAuthnResponse CreateSuccessResponse(string strRequestId, string strIssuerURN, string strRelayState, params SAMLAssertionAttribute[] additionalAttributes)
        {
            string strIssueInstantTimeStamp = UserContext.Current.Now.ToUniversalTime().ToString("O");
            string strValidUntilTimeStamp   = UserContext.Current.Now.AddMinutes(5).ToUniversalTime().ToString("O");

            XNamespace nsXmlSchema         = "http://www.w3.org/2001/XMLSchema";
            XNamespace nsXmlSchemaInstance = "http://www.w3.org/2001/XMLSchema-instance";

            string strAssertionElementName = "Assertion";

            // Response - Root-Element
            XElement elementResponse = CreateResponseElement(strRequestId, strIssuerURN);

            // Response Issuer
            // <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.partnerweb.ch/AKXYZ/</saml2:Issuer>
            XElement elementResponseIssuer = new XElement(SAML_ASSERTION_NAMESPACE + "Issuer", SystemSettings <SingleSignOnSystemSettings> .Current.SamlServiceEntityId,
                                                          new XAttribute(XNamespace.Xmlns + SAML_ASSERTION_NAMESPACE_PREFIX, SAML_ASSERTION_NAMESPACE));

            elementResponse.Add(elementResponseIssuer);

            // Status Element
            elementResponse.Add(CreateStatusElement(SAMLTopLevelStatusCode.SAML_TOPLEVEL_STATUSCODE_SUCCESS));

            // Assertion Element
            string   strAssertionId           = string.Format("{0}_{1}", strAssertionElementName, Guid.NewGuid());
            XElement elementResponseAssertion =
                new XElement(SAML_ASSERTION_NAMESPACE + strAssertionElementName,
                             new XAttribute("ID", strAssertionId),
                             new XAttribute("IssueInstant", strIssueInstantTimeStamp),
                             new XAttribute("Version", "2.0"),
                             new XAttribute(XNamespace.Xmlns + SAML_ASSERTION_NAMESPACE_PREFIX, SAML_ASSERTION_NAMESPACE),
                             new XAttribute(XNamespace.Xmlns + "xs", nsXmlSchema),
                             new XElement(SAML_ASSERTION_NAMESPACE + "Issuer", SystemSettings <SingleSignOnSystemSettings> .Current.SamlServiceEntityId)
                             );

            // Subject Element
            XElement elementAssertionSubject =
                new XElement(SAML_ASSERTION_NAMESPACE + "Subject",
                             new XElement(SAML_ASSERTION_NAMESPACE + "NameID", UserContext.Current.Login,
                                          new XAttribute("Format", SAML_ASSERTION_SUBJECT_NAMEID_FORMAT)),
                             new XElement(SAML_ASSERTION_NAMESPACE + "SubjectConfirmation",
                                          new XAttribute("Method", SAML_ASSERTION_SUBJECT_CONFIRMATION_METHOD),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "SubjectConfirmationData",
                                                       new XAttribute("InResponseTo", strRequestId),
                                                       new XAttribute("NotOnOrAfter", strValidUntilTimeStamp),
                                                       new XAttribute("Recipient", SingleSignOnConfiguration.GetAssertionConsumerServiceURLByRequestIssuer(strIssuerURN)))));

            elementResponseAssertion.Add(elementAssertionSubject);

            // Conditions Element
            XElement elementAssertionConditions =
                new XElement(SAML_ASSERTION_NAMESPACE + "Conditions",
                             new XAttribute("NotBefore", strIssueInstantTimeStamp),
                             new XAttribute("NotOnOrAfter", strValidUntilTimeStamp),
                             new XElement(SAML_ASSERTION_NAMESPACE + "AudienceRestriction",
                                          new XElement(SAML_ASSERTION_NAMESPACE + "Audience", strIssuerURN)));

            elementResponseAssertion.Add(elementAssertionConditions);

            // AuthnStatement Element
            XElement elementAssertionAuthnStatement =
                new XElement(SAML_ASSERTION_NAMESPACE + "AuthnStatement",
                             new XAttribute("AuthnInstant", strIssueInstantTimeStamp),
                             new XElement(SAML_ASSERTION_NAMESPACE + "AuthnContext",
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AuthnContextClassRef", SAML_ASSERTION_AUTHNCONTEXTCLASSREF)));

            elementResponseAssertion.Add(elementAssertionAuthnStatement);

            // AttributeStatement Element
            XElement elementAssertionAttributeStatement =
                new XElement(SAML_ASSERTION_NAMESPACE + "AttributeStatement",
                             new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                          new XAttribute("Name", GIVEN_NAME_ASSERTION_ATTRIBUTE_NAME),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", UserContext.Current.FirstName,
                                                       new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                       new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                       )
                                          ),
                             new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                          new XAttribute("Name", SURNAME_ASSERTION_ATTRIBUTE_NAME),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", UserContext.Current.LastName,
                                                       new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                       new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                       )
                                          ),
                             new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                          new XAttribute("Name", NAME_ASSERTION_ATTRIBUTE_NAME),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", UserContext.Current.Login,
                                                       new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                       new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                       )
                                          ),
                             new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                          new XAttribute("Name", EMAIL_ADDRESS_ASSERTION_ATTRIBUTE_NAME),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", UserContext.Current.EMail,
                                                       new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                       new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                       )
                                          ),
                             new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                          new XAttribute("Name", COMPANY_SUBNR_ASSERTION_ATTRIBUTE_NAME),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", UserContext.Current.CompanySubNr,
                                                       new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                       new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                       )
                                          ),
                             new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                          new XAttribute("Name", SPCD_ASSERTION_ATTRIBUTE_NAME),
                                          new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", UserContext.Current.SpCd,
                                                       new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                       new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                       )
                                          )
                             );

            if (additionalAttributes != null)
            {
                // Add Attributes to the <AttributeStatement /> element
                foreach (SAMLAssertionAttribute samlAssertionAttribute in additionalAttributes)
                {
                    elementAssertionAttributeStatement.Add(
                        new XElement(SAML_ASSERTION_NAMESPACE + "Attribute",
                                     new XAttribute("Name", samlAssertionAttribute.Name),
                                     new XElement(SAML_ASSERTION_NAMESPACE + "AttributeValue", samlAssertionAttribute.Value,
                                                  new XAttribute(XNamespace.Xmlns + "xsi", nsXmlSchemaInstance),
                                                  new XAttribute(nsXmlSchemaInstance + "Type", "xs:string")
                                                  )
                                     )
                        );
                }
            }

            // Add AttributeStatement Element to Assertion Element
            elementResponseAssertion.Add(elementAssertionAttributeStatement);

            // Add Assertion Element to the Response Element
            elementResponse.Add(elementResponseAssertion);

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

            // Sign Assertion Element
            string strSignedXmlResponseString = CreateSignedDocumentString(samlResponseXml, strAssertionElementName, SAML_ASSERTION_NAMESPACE_PREFIX, SAML_ASSERTION_NAMESPACE.NamespaceName,
                                                                           "#" + strAssertionId);

            return(CreateAuthnResponse(strIssuerURN, strSignedXmlResponseString, strRelayState));
        }