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; } }
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); }
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); }
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)); }