2

I'm currently migrating some components of a WebForms / MVP application into MVC. So far, everything is working except for authorization. No matter what, when I navigate to the MVC version of the Login page, I get redirected to the aspx page that is set in the Web.config:

    <authentication mode="Forms">
      <forms name=".MyWebSite" enableCrossAppRedirects="true" loginUrl="Login.aspx" timeout="60" path="/" defaultUrl="~/Pages/Landing.aspx"></forms>
    </authentication>

I've tried using AllowAnonymous but it appears that the webforms config are taking precedence. Here's my Login controller:

[RouteArea("User", AreaPrefix = "")]
public class AuthenticationController : Controller {
    [Route("Login")]
    [AllowAnonymous]
    public ActionResult Login() {
        return View();
    }
}

And my Directory structure looks like this:

> Web Project
   > Areas
      > User 
          > Controllers
              > AuthController
          > Views
              > Login.cshtml

In my web.config, I see the following to allow anonymous access to the Error pages:

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

However duplicating this for the Areas path isn't working (presumably because the cshtml files are not actually located there as aspx pages are?).

Now, if I am logged in (via the aspx version of login) and my user is authenticated, I can access the MVC implementation just fine. Routing and rendering are working wonderfully. It's just allowing unauthenticated users to access the MVC page (without redirecting to the aspx implementation) that seems to be a challenge. What am I doing wrong?

EDIT A really hacky partial solution I've found (based on Turning off ASP.Net WebForms authentication for one sub-directory) is the following:

    protected void Application_BeginRequest(object sender, EventArgs e) {
        // lots of existing web.config controls for which webforms folders can be accessed
        // read the config and skip checks for pages that authorise anon users by having
        // <allow users="?" /> as the top rule.
        // https://stackoverflow.com/questions/4616524/turning-off-asp-net-webforms-authentication-for-one-sub-directory

        // check local config
        var localAuthSection = ConfigurationManager.GetSection("system.web/authorization") as AuthorizationSection;

        // this assumes that the first rule will be <allow users="?" />
        var localRule = localAuthSection.Rules[0];
        if (localRule.Action == AuthorizationRuleAction.Allow && localRule.Users.Contains("?")) {
            // then skip the rest
            return;
        }

        // get the web.config and check locations
        var conf = WebConfigurationManager.OpenWebConfiguration("~");
        foreach (ConfigurationLocation loc in conf.Locations) {
            // find whether we're in a location with overridden config

            // get page name
            var currentPath = Path.GetFileName(this.Request.Path);
            if (currentPath.Equals(loc.Path, StringComparison.OrdinalIgnoreCase)) {
                // get the location's config
                var locConf = loc.OpenConfiguration();
                var authSection = locConf.GetSection("system.web/authorization") as AuthorizationSection;
                if (authSection != null) {
                    // this assumes that the first rule will be <allow users="?" />
                    var rule = authSection.Rules[0];
                    if (rule.Action == AuthorizationRuleAction.Allow && rule.Users.Contains("?")) {
                        // then skip the rest
                        return;
                    }
                }
            }
        }
    }

Which means I can specify "Login" like this:

  <location path="Login">
    <system.web>
      <authorization>
        <allow users="?" />
      </authorization>
    </system.web>
  </location>

But then all of the associated CSS/JS do not get rendered, unless I go through and add rules for those filetypes. There's got to be a more elegant fix to this.

Community
  • 1
  • 1
SB2055
  • 12,272
  • 32
  • 97
  • 202
  • I have a mixed environment and I use my old aspx login page for both. The auth flag is the same regardless of how the user got authenticated. Is there a reason to have both an aspx and an mvc login page? – tintyethan Jan 05 '15 at 21:11
  • @tintyethan - it's what was chosen as the first page to migrate to MVC, unfortunately out of my hands unless this turns out to be technically impossible. Eventually we will retire the ASPX implementation, but the ASPX auth needs to stay as is. – SB2055 Jan 05 '15 at 21:18

3 Answers3

1

I found what I think is the proper solution. In my web.config, I set the loginUrl to my MVC page:

    <authentication mode="Forms">
      <forms name=".MyWebSite" enableCrossAppRedirects="true" loginUrl="Login" timeout="60" path="/" defaultUrl="~/Pages/Landing.aspx"></forms>
    </authentication>

I then have to set the cookie from within my authController so that when I redirect to an aspx page, HttpContext.CurrentUser is defined as the logged-in user:

FormsAuthentication.SetAuthCookie(model.Username, true);

I don't know if this is indeed the correct way to go about this, but so far it seems to be working. I'll leave this open in case anyone has any feedback.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
SB2055
  • 12,272
  • 32
  • 97
  • 202
1

In the question, you are mixing two parts 1. Authentication and 2. Authorization.

  1. For Authentication: Forms authentication can be worked out.
  2. For Authorization: You have to implement custom Authorization filter in your MVC part of application. Ref: http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.118).aspx Also it can be used as custom attribute for ASP.NET forms.
Lalit Kale
  • 557
  • 6
  • 13
0

Take a look at the Microsoft's tutorial called "mvc music store". Part 7 is about configuration of Authentication and Authorization. 5-10 pages of read and you now a basic concept.

WholeLifeLearner
  • 455
  • 4
  • 19