Prevent XmlHttpRequest redirect response on .Net MVC WS-Federation site

I use WS Federated authentication (Claims Aware) on the MVC 3 site, and I am having problems maintaining some of my API controllers that send JSON to return a redirect when authentication fails. I have an Area called an API with several controllers that simply return JSON, these controllers inherit from the same base class. I want to send legitimate 401 error responses instead of the 302 redirects that happen by default.

I followed some instructions that I found to create a custom WSFederationAuthenticationModule , combined with a filter that I imposed on the actions of the API controller:

 public class WSFederationServiceAuthenticationModule : WSFederationAuthenticationModule { private static Log4NetLoggingService logger = new Log4NetLoggingService(); public const string IsServiceIndicator = "ROIP.IsService"; protected override void OnAuthorizationFailed(AuthorizationFailedEventArgs e) { base.OnAuthorizationFailed(e); var isService = HttpContext.Current.Items[IsServiceIndicator]; if (isService != null) { logger.Info("WSFedService: Found IsService"); e.RedirectToIdentityProvider = false; } else { logger.Info("WSFedService: Did not find IsService"); } } } public class WSFederationServiceAuthAttribute : ActionFilterAttribute { private static Log4NetLoggingService logger = new Log4NetLoggingService(); public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); // Set an item that indicates this is a service request, do not redirect. logger.Info("WSFedService: Setting IsService"); HttpContext.Current.Items[WSFederationServiceAuthenticationModule.IsServiceIndicator] = 1; } } 

But my log shows that I never find the IsService element in Items:

 {INFO}02/29 03:39:21 - WSFedService: Setting IsService {INFO}02/29 03:39:32 - WSFedService: Setting IsService {INFO}02/29 03:39:32 - WSFedService: Setting IsService {INFO}02/29 03:50:39 - WSFedService: Did not find IsService {INFO}02/29 03:53:16 - WSFedService: Did not find IsService {INFO}02/29 03:53:29 - WSFedService: Did not find IsService 

I think this may be a problem when HttpContext.Current does not match the filter and module, but I'm not sure.

Another option I tried was to subscribe to the FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider event in the Application_Start event of my Global.asax.cs object, but while WSFederationAuthenticationModule is null.

 private void ConfigureWSFederationAuthentication() { bool hasFederatedAuthentication = false; try { if (FederatedAuthentication.WSFederationAuthenticationModule != null) { hasFederatedAuthentication = true; } } catch { hasFederatedAuthentication = false; } if (hasFederatedAuthentication) { Logger.Info("WSFederation: Registering for Event Handler"); FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider += (s, e) => { var msg = string.Empty; try { if (HttpContext.Current.Request.Headers["X-Requested-With"] == "XMLHttpRequest") { e.Cancel = true; msg = "Found XMLHttpRequest header"; } else { msg = "Did not find XMLHttpRequest header"; } } catch (Exception ex) { msg = "WSFederation: Event Handler Error: " + ex.Message; } Logger.Info("WSFederation: Redirecting from Event Handler: " + msg); }; } else { Logger.Info("WSFederation: Null WSFederationAuthenticationModule"); } } 

I would like to know how to get the first work option, or where I should subscribe to the RedirectingToIdentityProvider event.

+4
source share
2 answers

I think I have found the answer to this problem and want to go back and leave an answer for anyone else in the world who may run into this.

My problem was that the HttpContext.Current.Items did not match between my ActionFilterAttribute and WSFederationAuthenticationModule , so I ended up checking the context and adding some checks similar to Phil Haax Forms Redirect Suppress Example

Here's what my updated custom WSFederationAuthenticationModule looks like:

 public class WSFederationServiceAuthenticationModule : WSFederationAuthenticationModule { private static Log4NetLoggingService logger = new Log4NetLoggingService(); protected override void OnAuthorizationFailed(AuthorizationFailedEventArgs e) { base.OnAuthorizationFailed(e); var context = HttpContext.Current; var req = context.Request; var resp = context.Response; if (req == null || resp == null) { logger.Info("WSFedService: Did not find Request or Response"); return; } if ((resp.StatusCode == 302 || resp.StatusCode == 401) && req.Headers["X-Requested-With"] == "XMLHttpRequest") { logger.Info("WSFedService: Found Redirect and Header"); e.RedirectToIdentityProvider = false; } else { logger.Info(string.Format("WSFedService: Did not find redirect status code or XMLHttpRequest Header: {0}", resp.StatusCode)); } } } 

And, of course, you need to add this to your web.config instead of the default authentication module:

 <system.web> <httpModules> <!-- Old and Busted... <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> --> <!-- New Hotness... --> <add name="WSFederationAuthenticationModule" type="MyApp.Web.Authentication.WSFederationServiceAuthenticationModule, MyApp.Web" /> </httpModules> </system.web> <system.webServer> <modules> <!-- Old and Busted... <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler"/> --> <!-- New Hotness... --> <add name="WSFederationAuthenticationModule" type="MyApp.Web.Authentication.WSFederationServiceAuthenticationModule, MyApp.Web" preCondition="managedHandler"/> </modules> </system.webServer> 
+7
source

I understand that this branch is ancient, but I ran into it trying to solve the same problem (I have a web apis that I want to use with active clients, and I want to send 401 if authentication goes south instead of redirecting.)

.. And, depending on your situation, it may be easier / less involved to process the event with an authorization error in Global.asax and perform your check there.

This link is what I am following: http://msdn.microsoft.com/en-us/library/system.identitymodel.services.wsfederationauthenticationmodule.authorizationfailed.aspx

.. And it seems simple.

+2
source

Source: https://habr.com/ru/post/1398908/


All Articles