/// <summary> /// Adds the specified AuthnRequest to the collection of previously /// sent requests, maintaining the imposed limit as defined by /// MaximumRequestsStored. This collection is represented as a /// queue and is attached to the user's session. /// </summary> /// <param name="context"> /// HttpContext containing session, request, and response objects. /// </param> /// <param name="authnRequest">AuthnRequest to add to the collection.</param> internal static void AddSentAuthnRequest(HttpContextBase context, AuthnRequest authnRequest) { Queue authnRequests = GetSentAuthnRequests(context); if (authnRequests == null) { authnRequests = new Queue(MaximumRequestsStored); } if (authnRequests.Count == MaximumRequestsStored) { authnRequests.Dequeue(); } authnRequests.Enqueue(authnRequest); context.Session[AuthnRequestSessionAttribute] = authnRequests; ILogger logger = LoggerFactory.GetLogger(typeof(AuthnRequestCache)); if (logger.IsInfoEnabled) { var message = new StringBuilder(); message.AppendLine("AuthnRequestsCache:"); foreach (AuthnRequest a in authnRequests) { message.AppendLine(a.Id); } logger.Info(message.ToString()); } }
/// <summary> /// Adds the specified AuthnRequest to the collection of previously /// sent requests, maintaining the imposed limit as defined by /// MaximumRequestsStored. This collection is represented as a /// queue and is attached to the user's session. /// </summary> /// <param name="context"> /// HttpContext containing session, request, and response objects. /// </param> /// <param name="authnRequest">AuthnRequest to add to the collection.</param> internal static void AddSentAuthnRequest(HttpContext context, AuthnRequest authnRequest) { Queue authnRequests = AuthnRequestCache.GetSentAuthnRequests(context); if (authnRequests == null) { authnRequests = new Queue(AuthnRequestCache.MaximumRequestsStored); } if (authnRequests.Count == AuthnRequestCache.MaximumRequestsStored) { authnRequests.Dequeue(); } authnRequests.Enqueue(authnRequest); context.Session[AuthnRequestCache.AuthnRequestSessionAttribute] = authnRequests; StringBuilder message = new StringBuilder(); message.Append("AuthnRequestsCache:\r\n"); IEnumerator i = authnRequests.GetEnumerator(); while (i.MoveNext()) { AuthnRequest a = (AuthnRequest)i.Current; message.Append(a.Id + "\r\n"); } FedletLogger.Info(message.ToString()); }
/// <summary> /// Removes the AuthnRequest from the collection of previously /// sent requests based on the provided AuthnRequest.Id value. /// This collection is represented as a queue and is attached to /// the user's session. /// </summary> /// <param name="context"> /// HttpContext containing session, request, and response objects. /// </param> /// <param name="authnRequestId"> /// ID of the AuthnRequest to be removed from the cache. /// </param> internal static void RemoveSentAuthnRequest(HttpContext context, string authnRequestId) { Queue originalCache = AuthnRequestCache.GetSentAuthnRequests(context); if (originalCache != null) { Queue revisedCache = new Queue(); while (originalCache.Count > 0) { AuthnRequest temp = (AuthnRequest)originalCache.Dequeue(); if (temp.Id != authnRequestId) { revisedCache.Enqueue(temp); } } context.Session[AuthnRequestCache.AuthnRequestSessionAttribute] = revisedCache; } }
/// <summary> /// Sends an AuthnRequest to the specified IDP with the given /// parameters. /// </summary> /// <param name="context"> /// HttpContext containing session, request, and response objects. /// </param> /// <param name="idpEntityId">Entity ID of the IDP.</param> /// <param name="parameters"> /// NameValueCollection of varying parameters for use in the /// construction of the AuthnRequest. /// </param> public void SendAuthnRequest(HttpContext context, string idpEntityId, NameValueCollection parameters) { IdentityProvider idp = (IdentityProvider)this.IdentityProviders[idpEntityId]; if (idp == null) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdentityProviderNotFound); } if (parameters == null) { parameters = new NameValueCollection(); } AuthnRequest authnRequest = new AuthnRequest(idp, this.ServiceProvider, parameters); XmlDocument xmlDoc = (XmlDocument)authnRequest.XmlDom; StringBuilder logMessage = new StringBuilder(); logMessage.Append("AuthnRequest:\r\n").Append(xmlDoc.OuterXml); FedletLogger.Info(logMessage.ToString()); // Add this AuthnRequest for this user for validation on AuthnResponse AuthnRequestCache.AddSentAuthnRequest(context, authnRequest); // Send with Redirect or Post based on the 'reqBinding' parameter. if (parameters[Saml2Constants.RequestBinding] == Saml2Constants.HttpPostProtocolBinding) { string postHtml = this.GetAuthnRequestPostHtml(authnRequest, idpEntityId, parameters); context.Response.Write(postHtml); context.Response.End(); } else { string redirectUrl = this.GetAuthnRequestRedirectLocation(authnRequest, idpEntityId, parameters); context.Response.Redirect(redirectUrl.ToString(), true); } }
/// <summary> /// Gets the AuthnRequest location along with querystring parameters /// to be used for actual browser requests. /// </summary> /// <param name="authnRequest"> /// AuthnRequest to packaged for a redirect. /// </param> /// <param name="idpEntityId">Entity ID of the IDP.</param> /// <param name="parameters"> /// NameVallueCollection of additional parameters. /// </param> /// <returns> /// URL with query string parameter for the specified IDP. /// </returns> public string GetAuthnRequestRedirectLocation(AuthnRequest authnRequest, string idpEntityId, NameValueCollection parameters) { if (authnRequest == null) { throw new ServiceProviderUtilityException(Resources.AuthnRequestIsNull); } IdentityProvider idp = (IdentityProvider)this.IdentityProviders[idpEntityId]; if (idp == null) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdentityProviderNotFound); } string ssoRedirectLocation = idp.GetSingleSignOnServiceLocation(Saml2Constants.HttpRedirectProtocolBinding); if (ssoRedirectLocation == null) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdpSingleSignOnSvcLocNotDefined); } string packagedAuthnRequest = Saml2Utils.CompressConvertToBase64UrlEncode(authnRequest.XmlDom); string queryString = Saml2Constants.RequestParameter + "=" + packagedAuthnRequest; if (parameters != null && !string.IsNullOrEmpty(parameters[Saml2Constants.RelayState])) { string relayState = parameters[Saml2Constants.RelayState]; Saml2Utils.ValidateRelayState(relayState, this.ServiceProvider.RelayStateUrlList); queryString += "&" + Saml2Constants.RelayState; queryString += "=" + HttpUtility.UrlEncode(relayState); } if (this.ServiceProvider.AuthnRequestsSigned || idp.WantAuthnRequestsSigned) { if (string.IsNullOrEmpty(this.ServiceProvider.SigningCertificateAlias)) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilitySignFailedNoCertAlias); } else { queryString += "&" + Saml2Constants.SignatureAlgorithm; queryString += "=" + HttpUtility.UrlEncode(Saml2Constants.SignatureAlgorithmRsa); queryString = Saml2Utils.SignQueryString(this.ServiceProvider.SigningCertificateAlias, queryString); } } StringBuilder redirectUrl = new StringBuilder(); redirectUrl.Append(ssoRedirectLocation); redirectUrl.Append(Saml2Utils.GetQueryStringDelimiter(ssoRedirectLocation)); redirectUrl.Append(queryString); FedletLogger.Info("AuthnRequest via Redirect:\r\n" + redirectUrl); return redirectUrl.ToString(); }
/// <summary> /// Gets the HTML for use of submitting the AuthnRequest with POST. /// </summary> /// <param name="authnRequest"> /// AuthnRequest to packaged for a POST. /// </param> /// <param name="idpEntityId">Entity ID of the IDP.</param> /// <param name="parameters"> /// NameVallueCollection of additional parameters. /// </param> /// <returns> /// HTML with auto-form submission with POST of the AuthnRequest /// </returns> public string GetAuthnRequestPostHtml(AuthnRequest authnRequest, string idpEntityId, NameValueCollection parameters) { if (authnRequest == null) { throw new ServiceProviderUtilityException(Resources.AuthnRequestIsNull); } IdentityProvider idp = (IdentityProvider)this.IdentityProviders[idpEntityId]; if (idp == null) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdentityProviderNotFound); } string ssoPostLocation = idp.GetSingleSignOnServiceLocation(Saml2Constants.HttpPostProtocolBinding); if (ssoPostLocation == null) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdpSingleSignOnSvcLocNotDefined); } string relayState = null; if (parameters != null && !string.IsNullOrEmpty(parameters[Saml2Constants.RelayState])) { relayState = parameters[Saml2Constants.RelayState]; Saml2Utils.ValidateRelayState(relayState, this.ServiceProvider.RelayStateUrlList); } XmlDocument authnRequestXml = (XmlDocument)authnRequest.XmlDom; if (this.ServiceProvider.AuthnRequestsSigned || idp.WantAuthnRequestsSigned) { if (string.IsNullOrEmpty(this.ServiceProvider.SigningCertificateAlias)) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilitySignFailedNoCertAlias); } else { Saml2Utils.SignXml( this.ServiceProvider.SigningCertificateAlias, authnRequestXml, authnRequest.Id, true); FedletLogger.Info("Signed AuthnRequest:\r\n" + authnRequestXml.InnerXml); } } string packagedAuthnRequest = Saml2Utils.ConvertToBase64(authnRequestXml.InnerXml); string inputFieldFormat = "<input type=\"hidden\" name=\"{0}\" value=\"{1}\" />"; StringBuilder html = new StringBuilder(); html.Append("<html><head><title>OpenSSO - SP initiated SSO</title></head>"); html.Append("<body onload=\"document.forms[0].submit();\">"); html.Append("<form method=\"post\" action=\""); html.Append(ssoPostLocation); html.Append("\">"); html.Append("<input type=\"hidden\" name=\""); html.Append(Saml2Constants.RequestParameter); html.Append("\" value=\""); html.Append(packagedAuthnRequest); html.Append("\" />"); if (!string.IsNullOrEmpty(relayState)) { html.Append(string.Format( CultureInfo.InvariantCulture, inputFieldFormat, Saml2Constants.RelayState, HttpUtility.HtmlEncode(relayState))); } html.Append("</form>"); html.Append("</body>"); html.Append("</html>"); return html.ToString(); }
/// <summary> /// Sends an AuthnRequest to the specified IDP with the given /// parameters. /// </summary> /// <param name="context"> /// HttpContext containing session, request, and response objects. /// </param> /// <param name="idpEntityId">Entity ID of the IDP.</param> /// <param name="parameters"> /// NameValueCollection of varying parameters for use in the /// construction of the AuthnRequest. /// </param> public void SendAuthnRequest(HttpContextBase context, string idpEntityId, NameValueCollection parameters) { IIdentityProvider idp; if (!IdentityProviders.TryGetValue(idpEntityId, out idp)) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdentityProviderNotFound); } if (parameters == null) { parameters = new NameValueCollection(); } var authnRequest = new AuthnRequest(idp, ServiceProvider, parameters, _saml2Utils); var xmlDoc = (XmlDocument) authnRequest.XmlDom; _logger.Info("AuthnRequest:\r\n{0}", xmlDoc.OuterXml); // Add this AuthnRequest for this user for validation on AuthnResponse //AuthnRequestCache.AddSentAuthnRequest(context, authnRequest); // Send with Redirect or Post based on the 'reqBinding' parameter. if (parameters[Saml2Constants.RequestBinding] == Saml2Constants.HttpPostProtocolBinding) { string postHtml = GetAuthnRequestPostHtml(authnRequest, idpEntityId, parameters); context.Response.Write(postHtml); context.Response.End(); } else { string redirectUrl = GetAuthnRequestRedirectLocation(authnRequest, idpEntityId, parameters); context.Response.Redirect(redirectUrl, true); } }