12

We have successfully configured windows identity foundation (WIF) in our ASP.NET 4.5 MVC 4 project with the help of the Identity and Access... extension for Visual Studio 2012. But are unable to exclude a specific path from authorization to allow anonymous access.

When we access our default route (i.e. /Home), the passive redirection will redirect us to the configured issuer Uri. This is currect. But now assume we want to exclude Path /Guest from STS Authentication so that everybody can access http://ourhost/Guest without beeing routed to the STS issuer. Only static documents are located there.

Snippets from Web.config:

<system.identityModel>
  <identityConfiguration>
    <audienceUris>
      <add value="http://ourhost/" />
    </audienceUris>
    <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <trustedIssuers>
        <add thumbprint="9B74****40D0" name="OurSTS" />
      </trustedIssuers>
    </issuerNameRegistry>
    <certificateValidation certificateValidationMode="None" />
  </identityConfiguration>
</system.identityModel>
<system.identityModel.services>
  <federationConfiguration>
    <cookieHandler requireSsl="false" />
    <wsFederation passiveRedirectEnabled="true" issuer="http://oursts/Issue" realm="http://ourhost/" reply="http://ourhost/" requireHttps="false" />
  </federationConfiguration>
</system.identityModel.services>

Further we have...

<system.webServer>
  <!-- ... -->
  <modules runAllManagedModulesForAllRequests="true">
    <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    <remove name="FormsAuthentication" />
  </modules>
</system.webServer>

and finally:

<system.web>
  <!-- ... -->
  <authentication mode="None" />
</system.web>

We tried the following without success:

<location path="~/Guest"> <!-- also "/Guest" is not working -->
  <system.web>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>
</location>

We also tried to put a small Web.config file into this folder, without success. No matter which Uri we locate to in the browser, we're always redirected.

What is the proper way to accomplish this?

EDIT

Removed the previous "accepted answered", set "accepted answer" to Eugenios answer as this is the more useful reply.

Community
  • 1
  • 1
thmshd
  • 5,729
  • 3
  • 39
  • 67

5 Answers5

12

In an MVC app you typically define access through the [Authorize] attribute in controllers and actions.

Just remove from web.config:

<system.web>
     <authorization>
        <deny users="?" />
      </authorization>

Note: this is usually added automatically by the "Add STS Reference" wizard in VS2010

It seems that the behaviour is exactly the same on VS2012 and the new tools. I just created a brand new MVC4 app. Ran the "Identity and Access..." tool with a local config STS (left all defaults).

It did add this fragment to the web.config:

<authorization>
  <deny users="?" />
</authorization>

I removed it and added [Authorize] to the About controller action:

[Authorize]
public ActionResult About()
{
    ViewBag.Message = "Your app description page.";

    return View();
}

When I click on the "About" link, then I get redirected to the STS. Everything else works with anonymous access.

Note:

You have some control on this too in the wizard (see the "Configuration" page of the wizard).

Eugenio Pace
  • 14,094
  • 1
  • 34
  • 43
  • Thanks Eugenio, we are using Visual Studio 2012 and "Add STS Reference" is not available there anymore, you have to use the "Identity and Access..." tool instead. I think i am close to the solution, looks like the `passiveRedirectEnabled="true"` was redirecting me to the STS regardless of any attribute usage. Setting to `false` and redirecting using some redirection helpers inside a custom Authentication Attribute seems pretty good right now. Gonna post my solution when I'm done, Thank you! – thmshd Nov 08 '12 at 22:42
  • I see. It should work with passiveRedirectEnabled=true too. I'll check on my system as well. – Eugenio Pace Nov 09 '12 at 17:53
  • since I really had problems achiving this with the passiveRedirectEnabled option enabled, I want to accept my own answer as solution, but I really appreciate your help on this topic and I believe that it's probably also working, but maybe the solution lies somewhere buried within my `web.config` settings in combination with the IIS setup. Thanks for your time, really appreciated! – thmshd Nov 11 '12 at 16:53
  • Is there a way to do this `[Authorize]` method in WebForms? I didn't think it was, but I'm not finding any alternatives. I was hoping there would be a solution to this in the web.config. – itslittlejohn Jun 28 '17 at 13:35
4

I can not get [Authorize] to work - it is not doing the redirect to my STS, and I am sure it is something I am missing. I did discover how to solve for the original ask, though.

In global.asax:

    protected void Application_Start()
    {
        ... config stuff ...
        FederatedAuthentication.WSFederationAuthenticationModule.AuthorizationFailed += WSFederationAuthenticationModule_AuthorizationFailed;
    }

and then:

    void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e)
    {
        // Do path/file detection here
        if (Request.Path.Contains("/Content/") || Request.Path.Contains("/Scripts/"))
        {
            e.RedirectToIdentityProvider = false;
        }
    }
Andrew Barnett
  • 5,066
  • 1
  • 22
  • 25
  • 1
    Thanks, Andrew, I would like to point out however that this approach creates a security hole, because I can now access whichever controller and action I want, because I can add something like this to the end of the url: "#/Content/" and that will not change the initial routing, but it will give me access to the controller. – Krasimir Kalinov Kostadinov Sep 23 '16 at 10:02
  • This didn't work for me, while the accepted answer worked without any additional changes. I was still getting the 401 response. – itslittlejohn Jun 28 '17 at 15:08
2

What finally pointed me into the right direction was an older blog post which explains how to protect a specific controller or area of the page. In combination with global filters I'm almost there.

It seems like the key is not to use the passiveRedirectEnabled="true" option but set it to false. Only then you have the full control over the authentication process, but would need to trigger the passive redirection yourself then, using the SignInRequestMessage class (which is not a big deal).

Better solutions with less code required are welcome.

EDIT

Removed "accepted answered" state for this, set "accepted answer" to Eugenios anwer as this is the more useful reply.

thmshd
  • 5,729
  • 3
  • 39
  • 67
2

I was in the same situation as Thomas. In my case, I was testing/using IISExpress locally.

Eugenio's answer almost got me working, with one added requirement. I had to set the "Anonymous Authentication" in my MVC Project Property to "Enabled."

This was either disabled by default or possibly set that way when using the VS 2012 "Identity and Access..." tooling.

So, to recap, there was no code or special attributes to write/maintain.

My csproj file contains:

<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>

My web.config contains:

<system.web>
    <authentication mode="None" />
</system.web>

<system.web>
    <authorization>
        <allow users="*" />
    </authorization>
</system.web>

<system.webServer>
    <modules>
        <remove name="FormsAuthentication" />
        <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
        <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
</system.webServer>

<system.identityModel.services>
    <federationConfiguration>
        <wsFederation passiveRedirectEnabled="true" issuer="https://REMOVED.accesscontrol.windows.net/v2/wsfederation" realm="urn:REMOVED" requireHttps="false" />
    </federationConfiguration>
</system.identityModel.services>

And, I add the standard [Authorize] attribute to controller actions that I want to be defended by WIF:

[Authorize]
public ActionResult About()
{
....
}
Nate Jackson
  • 549
  • 4
  • 15
0

I solved this in the web.config, the firts line Allow all unauthorized users and the second line disabled redirection

 <wsFederation passiveRedirectEnabled="false" issuer="xxx" realm="xxx"/>

<authentication mode="Windows" />
  <authorization>
      <allow users="*" />
  </authorization>