Suppress login redirects for API clients in WIF with Thinktecture IdentityModel
The FAM (federated authentication module) can be configured to automatically redirect http requests to the STS for authentication when a user is unauthorized. This is a common setting and is configured with the passiveRedirectEnabled attribute in web.config as such:
<system.identityModel.services> <federationConfiguration> <cookieHandler requireSsl="true" /> <wsFederation requireHttps="true" passiveRedirectEnabled="true" realm="http://localhost/rp" issuer="https://localhost/sts/issue/wsfed" /> </federationConfiguration> </system.identityModel.services>
The above configuration will force all unauthorized requests to be redirected, but for active API clients like Ajax and WebAPI the redirect is not useful and the unauthorized status code of 401 is preferred. The FAM supports disabling the redirect with the AuthorizationFailed event and it could be handled like this in global.asax:
void WSFederationAuthenticationModule_AuthorizationFailed( object sender, AuthorizationFailedEventArgs e) { e.RedirectToIdentityProvider = false; }
The hard part about implementing the above event handler is to logic to determine which requests are browser requests (and should be redirected) and which requests are API requests (and should not be redirected). APIs calls can be detected by checking for either the “X-Requested-With” http header (for Ajax requests) or if the http handler being used on the server is the HttpControllerHandler class (which is used by WebAPI).
Fortunately this logic has been implemented for you in Thinktecture IdentityModel. This feature is enabled with a SuppressLoginRedirectsForApiCalls API which should be invoked from the Init method in global.asax:
public override void Init() { PassiveModuleConfiguration.SuppressLoginRedirectsForApiCalls(); }
The redirect mentioned above will also be issued for other resource requests such as CSS and JavaScript files. If it is desirable to not redirect those requests, then the FAM http module can be configured to only run for requests that execute .NET code on the server (and not for static file requests). This is done by setting the preCondition attribute to “managed” for the FAM’s http module registration in web.config:
<system.webServer> <modules> <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managed" /> </modules> </system.webServer>
HTH
Hi, for some reason the WSFederationAuthenticationModulemodule in my mvc website redirects to my IDP also when a role based access control fails, even though the user is authenticated (This causes a redirect loop between the RP and the IDP). I even tried to set the e.RedirectToIdentityProvider to false when the user is authenticated (which is what seems to be done in the WSFederationAuthenticationModule itself. But it didn’t help. The WSFederationAuthenticationModulemodule seems to ignore the value of e.RedirectToIdentityProvider and perform the redirect. Any ideas what can cause this kind of behaviour?
A little update: It seems that PassiveModuleConfiguration.SuppressLoginRedirectsForApiCalls() causes this behavior. After removing it, the expected behavior returned, getting a 401 response when a user tries to access a controller that requires a role the user does not belong to. I guess that a consideration whether the user is authenticated should be added to the SuppressLoginRedirectsForApiCalls() logic.
Another update: I worked around this problem using:
void SFederationAuthenticationModule_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e)
{
e.Cancel = User.Identity.IsAuthenticated;
}
I’d suggest submitting an issue over on github so we can track this. https://github.com/thinktecture/Thinktecture.IdentityModel.45/issues
Hi There, is there any equivalent of preCondition=”managed”
in
to
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule
(WIF 3.5)? Thanks
It’s the same in 4.5 as in WIF in 4.0/3.5.
Hi! Anyway to do the same using katana/web api? I’ve tried with no luck… =/
Thanks!!
Did this not help? https://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
Hi BrockAllen,
We have a claim aware application created using Windows Identity foundation and working with ADFS.
Now we want to use windows integrated login(Windows authentication) in this application. We tried to set authentication type to windows in web.config, but application is not using it(ignoring the tag). I believe that is because WSFederationModule bypasses WindowsAuthentication Module.
If i am correct ,Is there some way by which i can enable windows authentication in a WIF application, so that the Enterprise user can seemlessly login using Windows Integrated authentication without any further prompt.
As you have overridden wsfederation module, so it raises my hope.
Kindly advise the best way to implement windows integrated login in WIF claim aware application.
Regards
TicArch
I’m confused why you need or want integrated windows auth if you’re already using ADFS, since ADFS (deployed in the intranet) should already provide the integrated windows authentication flow. But to your question — If you want integrated windows auth in your app, then disable the WSFereratedAuthenticationModule.
Hi Brockallen,
Let me clarify your doubt. I am trying to put windows authentication and claim aware both in my application because i am using my own login page in my application instead of ADFS login page.
Our users are both enterprise user and external users. So i need both windows integrated and claim aware. As you said i can have only one.
So my query here is – Is there some way by which i can check in incoming request whether user has domain credentials or not. Can i override WSfederationmodule to get the windows credentials first , if they don’t exist, pass on to WSfederationmodule for creating claimprincipal.
Does it make sense, as i am not sure where exactly in the pipeline can I get the windows/non-windows user identification.
Hope i am clear now.
Cheers
Ticarch
So you can use claims in an app with windows auth — you don’t need to use ADFS. See this to get a little more info — it’s not exactly what you’re asking but it might help understand that claims are just built into ,NET 4.5:
https://brockallen.com/2013/01/17/adding-custom-roles-to-windows-roles-in-asp-net-using-claims/
Hi BrockAllen,
Using ADFS is a necessity for me as i have to interact with other SPs as well which are in my domain and external SPs like Amazon console and LinkedIn. I have succcessfully integrated those.
However, this integrated windows authentication use case is causing issue for me. That’s where i needed your help. If at all I add WIF related WSfederationmodule in my application, all windows users identity is gone. It is not available anywhere. I tried to plug-in my custom module but hard luck.
Regards
TicArch
If you’re doing ADFS then your app is not logging the user in and you’re externalizing it with ADFS. Yet you say you want integrated windows auth in your app which is not using WIF, so I’m confused on which you really want.
Hi! I found this post very helpful. Thanks.
Hi Brock,
Thanks for your article! I think it’s pointed me in the right direction. However, I have a WebAPI application where I want to protect certain routes with WIF and allow others through.
My Web API application is a proxy providing WIF integration for another non IIS application. I’ve implemented a DelegatingHandler to process all requests and have implemented a generic “catch all” route in the following manner:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(name: “Proxy”, routeTemplate: “{*path}”, handler: HttpClientFactory.CreatePipeline
(
innerHandler: new HttpClientHandler(), // will never get here if proxy is doing its job
handlers: new DelegatingHandler[] { new HttpHandler() }
),
defaults: new { path = RouteParameter.Optional },
constraints: null
);
}
As a result there are no physical Web API controllers as all requests go through the DelegatingHandler (HttpHandler) and on to the 3rd party application.
My problem is that when I bypass WIF I’m hit with a Windows Authentication (WA) login screen. I have WA enabled on my web application configuration through its Authentication options on IIS. For this type of scenario what kind of authentication should be enabled for my web application in IIS?
Any help would be very much appreciated!!!
Regards.
Mick
If you have a WA screen, then your app in IIS is configure to issue those challenge headers. I guess I don’t know the real requirements, so it’s hard to say how it should be configured.