/// <summary> /// Constructs a proxy callback URL containing a ProxyCallbackParameter /// (proxyResponse by default). This URL is sent to the CAS server during a proxy /// ticket request and is then connected to by the CAS server. If the 'CasProxyCallbackUrl' settings is specified, /// its value will be used to construct the proxy url. Otherwise, `ServerName` will be used. /// If the CAS server cannot successfully connect (generally due to SSL configuration issues), the /// CAS server will refuse to send a proxy ticket. /// </summary> /// <returns>the proxy callback URL to use</returns> public static string ConstructProxyCallbackUrl(bool gateway) { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; EnhancedUriBuilder ub = null; if (CasAuthentication.CasProxyCallbackUrl != null && CasAuthentication.CasProxyCallbackUrl.Length > 0) { ub = new EnhancedUriBuilder(CasAuthentication.CasProxyCallbackUrl); } else { ub = new EnhancedUriBuilder(CasAuthentication.ServerName); ub.Path = request.Url.AbsolutePath; } // Disallow dynamic parameters (see https://github.com/Jasig/dotnet-cas-client/issues/23) // ub.QueryItems.Add(request.QueryString); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName); if (gateway) { ub.QueryItems.Set(CasAuthentication.GatewayParameterName, "true"); } else { ub.QueryItems.Remove(CasAuthentication.GatewayParameterName); } return(ub.Uri.AbsoluteUri); }
/// <summary> /// Constructs the URL to use for redirection to the CAS server for login /// </summary> /// <remarks> /// The server name is not parsed from the request for security reasons, which /// is why the service and server name configuration parameters exist. /// </remarks> /// <returns>The redirection URL to use</returns> public static string ConstructLoginRedirectUrl(bool gateway, bool renew) { if (gateway && renew) { throw new ArgumentException("Gateway and Renew parameters are mutually exclusive and cannot both be True"); } CasAuthentication.Initialize(); EnhancedUriBuilder ub = new EnhancedUriBuilder(CasAuthentication.FormsLoginUrl); ub.QueryItems.Set(CasAuthentication.TicketValidator.ServiceParameterName, HttpUtility.UrlEncode(ConstructServiceUrl(gateway))); if (renew) { ub.QueryItems.Add("renew", "true"); } else if (gateway) { ub.QueryItems.Add("gateway", "true"); } string url = ub.Uri.AbsoluteUri; return(url); }
/// <summary> /// Determines whether the current request requires a Gateway authentication redirect /// </summary> /// <returns>True if the request requires Gateway authentication, otherwise False</returns> internal static bool GetRequestRequiresGateway() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; GatewayStatus status = CasAuthentication.GetGatewayStatus(); bool gatewayEnabled = CasAuthentication.Gateway; bool gatewayWasNotAttempted = (status == GatewayStatus.NotAttempted); bool requestDoesNotHaveGatewayParameter = !GetRequestHasGatewayParameter(); bool cookiesRequiredUrlIsDefined = !string.IsNullOrEmpty(CasAuthentication.CookiesRequiredUrl); bool requestIsNotCookiesRequiredUrl = !GetRequestIsCookiesRequiredUrl(); bool notAuthorizedUrlIsDefined = !String.IsNullOrEmpty(CasAuthentication.NotAuthorizedUrl); bool requestIsNotAuthorizedUrl = notAuthorizedUrlIsDefined && request.RawUrl.StartsWith(UrlUtil.ResolveUrl(CasAuthentication.NotAuthorizedUrl), true, CultureInfo.InvariantCulture); bool result = ( gatewayEnabled && gatewayWasNotAttempted && requestDoesNotHaveGatewayParameter && cookiesRequiredUrlIsDefined && requestIsNotCookiesRequiredUrl && !requestIsNotAuthorizedUrl ); return(result); }
/// <summary> /// Returns a copy of the URL supplied modified to remove CAS protocol-specific /// URL parameters. /// </summary> /// <param name="url">The URL to remove CAS artifacts from</param> /// <returns>The URL supplied without CAS artifacts</returns> public static string RemoveCasArtifactsFromUrl(string url) { CommonUtils.AssertNotNullOrEmpty(url, "url parameter can not be null or empty."); CasAuthentication.Initialize(); EnhancedUriBuilder ub = new EnhancedUriBuilder(url); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ServiceParameterName); ub.QueryItems.Remove(CasAuthentication.GatewayParameterName); ub.QueryItems.Remove(CasAuthentication.ProxyCallbackParameterName); // ++ NETC-28 Uri uriServerName; if (CasAuthentication.ServerName.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) || CasAuthentication.ServerName.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) { uriServerName = new Uri(CasAuthentication.ServerName); } else { // .NET URIs require scheme uriServerName = new Uri("https://" + CasAuthentication.ServerName); } ub.Scheme = uriServerName.Scheme; ub.Host = uriServerName.Host; ub.Port = uriServerName.Port; return(ub.Uri.AbsoluteUri); }
/// <summary> /// Resolves a relative ~/Url to a Url that is meaningful to the /// client. /// <remarks> /// Derived from: http://weblogs.asp.net/palermo4/archive/2004/06/18/getting-the-absolute-path-in-asp-net-part-2.aspx /// </remarks> /// </summary> /// <author>J. Michael Palermo IV</author> /// <author>Scott Holodak</author> /// <param name="url">The Url to resolve</param> /// <returns>The fullly resolved Url</returns> internal static string ResolveUrl(string url) { CommonUtils.AssertNotNullOrEmpty(url, "url parameter can not be null or empty."); if (url[0] != '~') { return(url); } CasAuthentication.Initialize(); string applicationPath = HttpContext.Current.Request.ApplicationPath; if (url.Length == 1) { return(applicationPath); } // assume url looks like ~somePage int indexOfUrl = 1; // determine the middle character string midPath = ((applicationPath ?? string.Empty).Length > 1) ? "/" : string.Empty; // if url looks like ~/ or ~\ change the indexOfUrl to 2 if (url[1] == '/' || url[1] == '\\') { indexOfUrl = 2; } return(applicationPath + midPath + url.Substring(indexOfUrl)); }
/// <summary> /// Constructs a URL used to check the validitiy of a service ticket, with or without a proxy /// callback URL, and with or without requiring renewed credentials. /// </summary> /// <remarks>See CAS Protocol specification, section 2.5</remarks> /// <param name="serviceTicket">The service ticket to validate.</param> /// <param name="renew"> /// Whether or not renewed credentials are required. If True, ticket validation /// will fail for Single Sign On credentials. /// </param> /// <param name="gateway"> /// whether or not to include gatewayResponse=true in the request (client specific). /// </param> /// <param name="customParameters">custom parameters to add to the validation URL</param> /// <returns>The service ticket validation URL to use</returns> public static string ConstructValidateUrl(string serviceTicket, bool gateway, bool renew, NameValueCollection customParameters) { if (gateway && renew) { throw new ArgumentException("Gateway and Renew parameters are mutually exclusive and cannot both be True"); } CasAuthentication.Initialize(); EnhancedUriBuilder ub = new EnhancedUriBuilder(EnhancedUriBuilder.Combine(CasAuthentication.CasServerUrlPrefix, CasAuthentication.TicketValidator.UrlSuffix)); ub.QueryItems.Add(CasAuthentication.TicketValidator.ServiceParameterName, HttpUtility.UrlEncode(ConstructServiceUrl(gateway))); ub.QueryItems.Add(CasAuthentication.TicketValidator.ArtifactParameterName, serviceTicket); if (renew) { ub.QueryItems.Set("renew", "true"); } if (customParameters != null) { for (int i = 0; i < customParameters.Count; i++) { string key = customParameters.AllKeys[i]; string value = customParameters[i]; ub.QueryItems.Add(key, value); } } return(ub.Uri.AbsoluteUri); }
/// <summary> /// Constructs a proxy callback URL containing a ProxyCallbackParameter /// (proxyResponse by default). This URL is sent to the CAS server during a proxy /// ticket request and is then connected to by the CAS server. If the 'CasProxyCallbackUrl' settings is specified, /// its value will be used to construct the proxy url. Otherwise, `ServerName` will be used. /// If the CAS server cannot successfully connect (generally due to SSL configuration issues), the /// CAS server will refuse to send a proxy ticket. /// </summary> /// <returns>the proxy callback URL to use</returns> public static string ConstructProxyCallbackUrl(bool gateway) { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; EnhancedUriBuilder ub = null; if (CasAuthentication.CasProxyCallbackUrl != null && CasAuthentication.CasProxyCallbackUrl.Length > 0) { ub = new EnhancedUriBuilder(CasAuthentication.CasProxyCallbackUrl); } else { ub = new EnhancedUriBuilder(CasAuthentication.ServerName); } ub.Path = request.Url.AbsolutePath; ub.QueryItems.Add(request.QueryString); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName); if (gateway) { ub.QueryItems.Set(CasAuthentication.GatewayParameterName, "true"); } else { ub.QueryItems.Remove(CasAuthentication.GatewayParameterName); } return(ub.Uri.AbsoluteUri); }
/// <summary> /// Determines whether the request is appropriate for CAS authentication. /// Generally, this is true for most requests except those for images, /// style sheets, javascript files and anything generated by the built-in /// ASP.NET handlers (i.e., web resources, trace handler). /// </summary> /// <returns>True if the request is appropriate for CAS authentication, otherwise False</returns> internal static bool GetRequestIsAppropriateForCasAuthentication() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; HttpResponse response = context.Response; string contentType = response.ContentType.ToLowerInvariant(); string fileName = request.Url.Segments[request.Url.Segments.Length - 1]; bool contentTypeIsEligible = false; bool fileNameIsEligible = true; foreach (string appropriateContentType in AppropriateContentTypes) { if (string.Compare(contentType, appropriateContentType, true, CultureInfo.InvariantCulture) == 0) { contentTypeIsEligible = true; break; } } foreach (string builtInHandler in BuiltInHandlers) { if (string.Compare(fileName, builtInHandler, true, CultureInfo.InvariantCulture) == 0) { fileNameIsEligible = false; break; } } // TODO: Should this be || instead of && ? return(contentTypeIsEligible && fileNameIsEligible); }
/// <summary> /// Public CasAuthenticationTicket constructor /// </summary> /// <param name="serviceTicket">CAS Service Ticket associated with this CasAuthenticationTicket</param> /// <param name="originatingServiceName">ServiceName used during CAS authentication/validation</param> /// <param name="clientHostAddress">IP address of the client initiating the authentication request</param> /// <param name="assertion">CAS assertion returned from the CAS server during ticket validation</param> public CasAuthenticationTicket(string serviceTicket, string originatingServiceName, string clientHostAddress, IAssertion assertion) { CasAuthentication.Initialize(); Proxies = new List <string>(); NetId = assertion.PrincipalName; ServiceTicket = serviceTicket; OriginatingServiceName = originatingServiceName; ClientHostAddress = clientHostAddress; Assertion = assertion; if (DateTime.MinValue.CompareTo(assertion.ValidFromDate) != 0) { ValidFromDate = assertion.ValidFromDate; } else { ValidFromDate = DateTime.Now; } DateTime localValidUntil = ValidFromDate.Add(CasAuthentication.FormsTimeout); if (DateTime.MinValue.CompareTo(assertion.ValidUntilDate) != 0) { ValidUntilDate = localValidUntil.CompareTo(assertion.ValidUntilDate) < 0 ? localValidUntil : assertion.ValidUntilDate; } else { ValidUntilDate = localValidUntil; } }
/// <summary> /// Determines whether the user's browser refuses to accept session cookies /// </summary> /// <returns>True if the browser does not allow session cookies, otherwise False</returns> internal static bool GetUserDoesNotAllowSessionCookies() { CasAuthentication.Initialize(); // If the request has a gateway parameter but the cookie does not // reflect the fact that gateway was attempted, then cookies must // be disabled. GatewayStatus status = CasAuthentication.GetGatewayStatus(); bool gatewayEnabled = CasAuthentication.Gateway; bool gatewayWasNotAttempted = (status == GatewayStatus.NotAttempted); bool requestHasGatewayParameter = GetRequestHasGatewayParameter(); bool cookiesRequiredUrlIsDefined = !string.IsNullOrEmpty(CasAuthentication.CookiesRequiredUrl); bool requestIsNotCookiesRequiredUrl = cookiesRequiredUrlIsDefined && !GetRequestIsCookiesRequiredUrl(); bool result = ( gatewayEnabled && gatewayWasNotAttempted && requestHasGatewayParameter && requestIsNotCookiesRequiredUrl ); return(result); }
/// <summary> /// Constructs a service URL using configured values in the following order: /// 1. if not empty, the value configured for Service is used /// - otherwise - /// 2. the value configured for ServerName is used together with HttpRequest /// data /// </summary> /// <remarks> /// The server name is not parsed from the request for security reasons, which /// is why the service and server name configuration parameters exist, per Jasig /// website. /// </remarks> /// <returns>the service URL to use, not encoded</returns> public static string ConstructServiceUrl(bool gateway) { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; StringBuilder buffer = new StringBuilder(); if (!(CasAuthentication.ServerName.StartsWith("https://") || CasAuthentication.ServerName.StartsWith("http://"))) { buffer.Append(request.IsSecureConnection ? "https://" : "http://"); } buffer.Append(CasAuthentication.ServerName); EnhancedUriBuilder ub = new EnhancedUriBuilder(buffer.ToString()); ub.Path = request.Url.AbsolutePath; ub.QueryItems.Add(request.QueryString); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ServiceParameterName); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName); if (gateway) { ub.QueryItems.Set(CasAuthentication.GatewayParameterName, "true"); } else { ub.QueryItems.Remove(CasAuthentication.GatewayParameterName); } return(ub.Uri.AbsoluteUri); }
/// <summary> /// Constructs a proxy callback URL containing a ProxyCallbackParameter /// (proxyResponse by default). This URL is sent to the CAS server during a proxy /// ticket request and is then connected to by the CAS server. If the CAS server /// cannot successfully connect (generally due to SSL configuration issues), the /// CAS server will refuse to send a proxy ticket. /// </summary> /// <remarks> /// This is a .NET implementation specific method used to eliminate the need for /// a special HTTP Handler. Essentially, if the client detects an incoming request /// with the ProxyCallbackParameter in the URL (i.e., proxyResponse), that request /// is treated specially and behaves as if it were handled by an HTTP Handler. In /// other words, this behavior may or may not short circuit the request event /// processing and will not allow the underlying page to execute and transmit back to /// the client. If your application does coincidentally make use of the key /// 'proxyResponse' as a URL parameter, you will need to configure a custom /// proxyCallbackParameter value which does not conflict with the URL parameters in /// your application. /// </remarks> /// <returns>the proxy callback URL to use</returns> public static string ConstructProxyCallbackUrl() { CasAuthentication.Initialize(); EnhancedUriBuilder ub = new EnhancedUriBuilder(ConstructProxyCallbackUrl(false)); ub.QueryItems.Set(CasAuthentication.ProxyCallbackParameterName, "true"); return ub.Uri.AbsoluteUri; }
/// <summary> /// Constructs the URL to use for redirection to the CAS server for single /// signout. The CAS server will invalidate the ticket granting ticket and /// redirect back to the current page. The web application must then call /// ClearAuthCookie and revoke the ticket from the ServiceTicketManager to sign /// the client out. /// </summary> /// <returns>the redirection URL to use, not encoded</returns> public static string ConstructSingleSignOutRedirectUrl() { CasAuthentication.Initialize(); // TODO: Make "logout" configurable EnhancedUriBuilder ub = new EnhancedUriBuilder(EnhancedUriBuilder.Combine(CasAuthentication.CasServerUrlPrefix, "logout")); ub.QueryItems.Set(CasAuthentication.TicketValidator.ServiceParameterName, HttpUtility.UrlEncode(ConstructServiceUrl(false))); return ub.Uri.AbsoluteUri; }
/// <summary> /// Constructs a proxy ticket request URL containing both a proxy granting /// ticket and a URL Encoded targetServiceUrl. The URL returned will generally only /// be executed by the CAS client as a part of a proxy redirection in /// CasAuthentication.ProxyRedirect(...) or CasAuthentication.GetProxyTicketIdFor(...) /// but may also be used by applications which require low-level access to the proxy /// ticket request functionality. /// </summary> /// <param name="proxyGrantingTicketId"> /// The proxy granting ticket used to authorize the request for a proxy ticket on the /// CAS server /// </param> /// <param name="targetService"> /// The target service URL to request a proxy ticket request URL for /// </param> /// <returns>The URL to use to request a proxy ticket for the targetService specified</returns> public static string ConstructProxyTicketRequestUrl(string proxyGrantingTicketId, string targetService) { CasAuthentication.Initialize(); // TODO: Make "proxy" configurable. EnhancedUriBuilder ub = new EnhancedUriBuilder(EnhancedUriBuilder.Combine(CasAuthentication.CasServerUrlPrefix, "proxy")); ub.QueryItems.Add("pgt", proxyGrantingTicketId); ub.QueryItems.Add("targetService", HttpUtility.UrlEncode(targetService)); return(ub.Uri.AbsoluteUri); }
/// <summary> /// Attempts to request a proxy ticket for the targetService specified and /// returns a URL appropriate for redirection to the targetService containing /// a ticket. /// </summary> /// <param name="targetService">The target service for proxy authentication</param> /// <param name="proxyTicketUrlParameter"> /// The name of the ticket URL parameter expected by the target service (ticket by /// default) /// </param> /// <returns>The URL of the target service with a proxy ticket included</returns> public static string GetProxyRedirectUrl(string targetService, string proxyTicketUrlParameter) { CasAuthentication.Initialize(); // Todo: Is ResolveUrl(...) appropriate/necessary? If the URL starts with ~, it shouldn't require proxy authentication string resolvedUrl = ResolveUrl(targetService); string proxyTicket = CasAuthentication.GetProxyTicketIdFor(resolvedUrl); EnhancedUriBuilder ub = new EnhancedUriBuilder(resolvedUrl); ub.QueryItems[proxyTicketUrlParameter] = proxyTicket; return ub.Uri.AbsoluteUri; }
/// <summary> /// Determines whether the User associated with the request has been /// defined and is authenticated. /// </summary> /// <returns>True if the request has an authenticated User, otherwise False</returns> private static bool GetUserIsAuthenticated() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; bool result = ( context.User != null && context.User.Identity.IsAuthenticated ); return(result); }
/// <summary> /// Determines whether the request has a CAS ticket in the URL /// </summary> /// <returns>True if the request URL contains a CAS ticket, otherwise False</returns> internal static bool GetRequestHasCasTicket() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; bool result = ( request[CasAuthentication.TicketValidator.ArtifactParameterName] != null && !String.IsNullOrEmpty(request[CasAuthentication.TicketValidator.ArtifactParameterName]) ); return(result); }
/// <summary> /// Determines whether the current request is unauthenticated /// </summary> /// <returns>True if the request is unauthenticated, otherwise False</returns> internal static bool GetRequestIsUnAuthenticated() { CasAuthentication.Initialize(); bool userIsNotAuthenticated = !GetUserIsAuthenticated(); bool responseIsCasLoginRedirect = GetResponseIsCasLoginRedirect(); bool result = ( userIsNotAuthenticated && responseIsCasLoginRedirect ); return(result); }
/// <summary> /// Intercepts the beginning of the request pipeline. This will detect SingleSignOut /// requests. SingleSignOut requests are posted back to the serviceName URL that /// was passed when the CAS session was established. Since the behavior of the script /// at that URL is unknown, a POST back by the CAS server could have unexpected /// consequences. We want to prevent this request from authenticating and from /// executing the HttpHandler typically associated with that URL. So we are handling /// this by sending back an HTTP 200 (OK) message with a blank body and short /// circuiting all event processing and firing EndRequest directly /// (via CompleteRequest()). /// </summary> /// <param name="sender">The HttpApplication that sent the request</param> /// <param name="e">Not used</param> private static void OnBeginRequest(object sender, EventArgs e) { // Validate the ticket coming back from the CAS server (NETC-55) if (!RequestEvaluator.GetRequestIsAppropriateForCasAuthentication()) { logger.Debug("BeginRequest bypassed for " + HttpContext.Current.Request.RawUrl); return; } CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; logger.Debug("Starting BeginRequest for " + request.RawUrl); // Cleanup expired ServiceTickets in the ServiceTicketManager if (CasAuthentication.ServiceTicketManager != null) { CasAuthentication.ServiceTicketManager.RemoveExpiredTickets(); } // Cleanup expired ProxyTicket mappings in the ProxyTicketManager if (CasAuthentication.ProxyTicketManager != null) { CasAuthentication.ProxyTicketManager.RemoveExpiredMappings(); } // Detect & process inbound Single SignOut Requests from the CAS server if (CasAuthentication.ServiceTicketManager != null && CasAuthentication.ProcessIncomingSingleSignOutRequests && RequestEvaluator.GetRequestIsCasSingleSignOut()) { logger.Info("Processing inbound Single Sign Out request."); CasAuthentication.ProcessSingleSignOutRequest(); return; } // Detect & process inbound proxy callback verifications from the CAS server if (CasAuthentication.ProxyTicketManager != null && RequestEvaluator.GetRequestIsProxyResponse()) { logger.Info("Processing Proxy Callback request"); CasAuthentication.ProcessProxyCallbackRequest(); return; } logger.Debug("Ending BeginRequest for " + request.RawUrl); }
/// <summary> /// Determines whether the request is for the CookiesRequiredUrl defined in web.config /// </summary> /// <returns>True if the request is to the CookiesRequiredUrl, otherwise False</returns> private static bool GetRequestIsCookiesRequiredUrl() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; bool cookiesRequiredUrlIsDefined = !String.IsNullOrEmpty(CasAuthentication.CookiesRequiredUrl); bool requestIsCookiesRequiredUrl = cookiesRequiredUrlIsDefined && request.RawUrl.StartsWith(UrlUtil.ResolveUrl(CasAuthentication.CookiesRequiredUrl), true, CultureInfo.InvariantCulture); bool result = ( requestIsCookiesRequiredUrl ); return(result); }
/// <summary> /// Determines whether the request contains the GatewayParameterName defined in /// web.config or the default value 'gatewayResponse' /// </summary> /// <returns>True if the request contains the GatewayParameterName, otherwise False</returns> internal static bool GetRequestHasGatewayParameter() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; bool requestContainsGatewayParameter = !String.IsNullOrEmpty(request.QueryString[CasAuthentication.GatewayParameterName]); bool gatewayParameterValueIsTrue = (request.QueryString[CasAuthentication.GatewayParameterName] == "true"); bool result = ( requestContainsGatewayParameter && gatewayParameterValueIsTrue ); return(result); }
/// <summary> /// Determines whether the request is a CAS Single Sign Out request /// </summary> /// <returns>True if the request is a CAS Single Sign Out request, otherwise False</returns> internal static bool GetRequestIsCasSingleSignOut() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; bool requestIsFormPost = (request.RequestType == "POST"); bool haveLogoutRequest = !string.IsNullOrEmpty(request.Params["logoutRequest"]); bool result = ( requestIsFormPost && haveLogoutRequest ); return(result); }
/// <summary> /// Determines whether the request is an inbound proxy callback verifications /// from the CAS server /// </summary> /// <returns>True if the request is a proxy callback verificiation, otherwise False</returns> internal static bool GetRequestIsProxyResponse() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; bool requestContainsProxyCallbackParameter = !String.IsNullOrEmpty(request.QueryString[CasAuthentication.ProxyCallbackParameterName]); bool proxyCallbackParameterValueIsTrue = (request.QueryString[CasAuthentication.ProxyCallbackParameterName] == "true"); bool result = ( requestContainsProxyCallbackParameter && proxyCallbackParameterValueIsTrue ); return(result); }
/// <summary> /// Determines whether the request is appropriate for CAS authentication. /// Generally, this is true for most requests except those for images, /// style sheets, javascript files and anything generated by the built-in /// ASP.NET handlers (i.e., web resources, trace handler). /// </summary> /// <returns>True if the request is appropriate for CAS authentication, otherwise False</returns> internal static bool GetRequestIsAppropriateForCasAuthentication() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; HttpResponse response = context.Response; string contentType = response.ContentType; string fileName = request.Url.Segments[request.Url.Segments.Length - 1]; bool contentTypeIsEligible = false; bool fileNameIsEligible = true; if (string.IsNullOrEmpty(contentType) && CasAuthentication.RequireCasForMissingContentTypes) { contentTypeIsEligible = true; } if (!contentTypeIsEligible) { foreach (string appropriateContentType in CasAuthentication.RequireCasForContentTypes) { if (string.Compare(contentType, appropriateContentType, true, CultureInfo.InvariantCulture) == 0) { contentTypeIsEligible = true; break; } } } foreach (string builtInHandler in CasAuthentication.BypassCasForHandlers) { if (string.Compare(fileName, builtInHandler, true, CultureInfo.InvariantCulture) == 0) { fileNameIsEligible = false; break; } } return(contentTypeIsEligible && fileNameIsEligible); }
/// <summary> /// Determines whether the current request will be redirected to the /// CAS login page /// </summary> /// <returns>True if the request will be redirected, otherwise False.</returns> private static bool GetResponseIsCasLoginRedirect() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpResponse response = context.Response; bool requestDoesNotHaveCasTicket = !GetRequestHasCasTicket(); bool responseIsBeingRedirected = (response.StatusCode == 302); bool responseRedirectsToFormsLoginUrl = !String.IsNullOrEmpty(response.RedirectLocation) && response.RedirectLocation.StartsWith(CasAuthentication.FormsLoginUrl); bool result = ( requestDoesNotHaveCasTicket && responseIsBeingRedirected && responseRedirectsToFormsLoginUrl ); return(result); }
/// <summary> /// Determines whether the current request is unauthorized /// </summary> /// <returns>True if the request is unauthorized, otherwise False</returns> internal static bool GetRequestIsUnauthorized() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpResponse response = context.Response; bool responseIsBeingRedirected = (response.StatusCode == 302); bool userIsAuthenticated = GetUserIsAuthenticated(); bool responseIsCasLoginRedirect = GetResponseIsCasLoginRedirect(); bool result = ( responseIsBeingRedirected && userIsAuthenticated && responseIsCasLoginRedirect ); return(result); }
/// <summary> /// Constructs a proxy ticket request URL containing both a proxy granting /// ticket and a URL Encoded targetServiceUrl. The URL returned will generally only /// be executed by the CAS client as a part of a proxy redirection in /// CasAuthentication.ProxyRedirect(...) or CasAuthentication.GetProxyTicketIdFor(...) /// but may also be used by applications which require low-level access to the proxy /// ticket request functionality. /// </summary> /// <param name="proxyGrantingTicketId"> /// The proxy granting ticket used to authorize the request for a proxy ticket on the /// CAS server /// </param> /// <param name="targetService"> /// The target service URL to request a proxy ticket request URL for /// </param> /// <returns>The URL to use to request a proxy ticket for the targetService specified</returns> public static string ConstructProxyTicketRequestUrl(string proxyGrantingTicketId, string targetService) { CasAuthentication.Initialize(); if (String.IsNullOrEmpty(proxyGrantingTicketId)) { throw new ArgumentException("For proxy ticket requests, proxyGrantingTicketId cannot be null and must be specified."); } if (String.IsNullOrEmpty(targetService)) { throw new ArgumentException("For proxy ticket requests, targetService cannot be null and must be specified."); } // TODO: Make "proxy" configurable. EnhancedUriBuilder ub = new EnhancedUriBuilder(EnhancedUriBuilder.Combine(CasAuthentication.CasServerUrlPrefix, "proxy")); ub.QueryItems.Add("pgt", proxyGrantingTicketId); ub.QueryItems.Add("targetService", HttpUtility.UrlEncode(targetService)); return ub.Uri.AbsoluteUri; }
/// <summary> /// Determines whether the request is a return request from the /// CAS server containing a CAS ticket /// </summary> /// <returns>True if the request URL contains a CAS ticket, otherwise False</returns> internal static bool GetRequestIsCasAuthenticationResponse() { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; int artifactIndex = request.Url.AbsoluteUri.IndexOf(CasAuthentication.TicketValidator.ArtifactParameterName); bool result = ( GetRequestHasCasTicket() && artifactIndex > 0 && ( request.Url.AbsoluteUri[artifactIndex - 1] == '?' || request.Url.AbsoluteUri[artifactIndex - 1] == '&' ) ); return(result); }
/// <summary> /// Constructs a service URL using configured values in the following order: /// 1. if not empty, the value configured for Service is used /// - otherwise - /// 2. the value configured for ServerName is used together with HttpRequest /// data /// </summary> /// <remarks> /// The server name is not parsed from the request for security reasons, which /// is why the service and server name configuration parameters exist, per Apereo /// website. /// </remarks> /// <returns>the service URL to use, not encoded</returns> public static string ConstructServiceUrl(bool gateway) { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; StringBuilder buffer = new StringBuilder(); if (!(CasAuthentication.ServerName.StartsWith("https://") || CasAuthentication.ServerName.StartsWith("http://"))) { buffer.Append(request.IsSecureConnection ? "https://" : "http://"); } buffer.Append(CasAuthentication.ServerName); EnhancedUriBuilder ub = new EnhancedUriBuilder(buffer.ToString()); ub.Path = request.Url.AbsolutePath; // Iterate through each of the name/value pairs in the query component of the service URL foreach (string name in request.QueryString.AllKeys) { // URL encode each name/value pair and then add it to the query items collection ub.QueryItems.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(request.QueryString[name])); } ub.QueryItems.Remove(CasAuthentication.TicketValidator.ServiceParameterName); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName); if (gateway) { ub.QueryItems.Set(CasAuthentication.GatewayParameterName, "true"); } else { ub.QueryItems.Remove(CasAuthentication.GatewayParameterName); } return(ub.Uri.AbsoluteUri); }
/// <summary> /// Empty constructor (to be used during Serialization/Deserialization) /// </summary> private CasAuthenticationTicket() { CasAuthentication.Initialize(); Proxies = new List <string>(); }