Search code examples
c#asp.netvb.netwebformsroleprovider

Live testing ASP.NET custom Role Provider


Using ASP.NET Webforms + VB/C#

I've been tasked to restrict ASP.NET page access to users not in specific roles. And I need to be able to live test my solution (versus unit testing where I could use mocks or fakes). Our site is rather complex so I doubt I'd be able to find all the "gotchas" with just unit testing.

I have something on my development computer I'm pretty sure will work in Production: I have a custom Role Provider hooked into the web.config file. It's being initialized and called when I debug the website, so I'm reasonably sure it's working OK. I have a folder ("Administration") marked only for a specific role. Our roles are defined in our own database and are not tied to Microsoft or Windows roles/permissions.

The problem is: I cannot actually login as a user I wish to debug with. I can "simulate" this with a special development-only start page. That works OK for our menu/navigation items which are built from the roles database, but of course without restricting pages (with a Role Provider or something similar), you can still manually type in a page and it will be served up. This devel-only start page sets the username I pass in as a FormsAuthentation auth cookie.

FormsAuthentication.Initialize()
FormsAuthentication.SignOut()
FormsAuthentication.SetAuthCookie(simUserName, True)

It seems like when I first start debugging (usually after a reboot), the custom Role Provider will get called with the same username I'm simulating, but after a while, that suddenly stops and my local Windows name gets passed instead. (Cookie issue?) After that, it no longer works.

Anyway -- Is there a way I can test roles locally during development or will we just have to put this on Production and hope for the best.

I didn't know what code or settings would be useful at this time, so let me know what you need. Thanks!


Solution

  • I think I've found the solution to my problem. I decided to work with some of the samples in Ch. 7 of Beginning ASP.NET Security by Barry Dorrans (published by Wrox) in the hopes working with authentication and authorization in simple examples might lead to a solution, and it did.

    One of the examples of using Forms authentication (pp. 155-157) showed a simple login.aspx page similar to my development startup page. The code I had in my Development startup page (shown above) was incorrect. It should have been:

    FormsAuthentication.Authenticate(simUserName, simUserPassword)
    FormsAuthentication.RedirectFromLoginPage(simUserName, False)
    

    I also defined my simulated users in my Development web.config:

    <authentication mode="Forms">
      <forms defaultUrl="default.aspx" loginUrl="mystart.aspx">
        <credentials passwordFormat="Clear">
          <user name="GeorgeWashington" password="password"/>
          <user name="AndrewJackson" password="password"/>
          <user name="AbrahamLincoln" password="password"/>
          <user name="TeddyRoosevelt" password="password"/>
          <user name="JackKennedy" password="password"/>
        </credentials>
      </forms>
    </authentication>
    

    When FormsAuthentication.Authenticate is called and authenticates which ever of the simulated users I choose, it looks like it causes ASP.NET to now always use this username in calls to the Role Provider. At least, this appears to be working when debugging the website.

    I've set the project to always call my Development startup page (the login page -- mystart.aspx). This way I always start with a fresh authentication in case I need to work with a different role.

    Anyone wanting to use this solution, WARNING: Your Development startup page must NEVER be used for the Production website. Likewise, NEVER use usernames and passwords in a Production web.config. This is ONLY for debugging and testing. Depending how you version control your development and production code, you may have to manually merge certain changes going from development to production in order to avoid sending this debugging code to Production.

    I also understand Microsoft wants us to use a Membership Provider in place of the FormsAuthentication class. And in Production code, we should. But for my purposes (ensuring I can interact with the website in differing users/roles while debugging), this appears to be the simplest solution.

    EDIT -- one more piece of the puzzle: I was still getting strange method calls in my Custom Role Provider. A few times a method would be called with the username I logged in with on my login page (this is what I expected); most often it was my Windows username which led me to believe Windows authorization was still being used by ASP.NET somewhere. After more research (thanks SO!!!), I found in my applicationhost.config file for my project, Windows authentication was set to True which I guess was causing a conflict with my web.config file. Setting the values in applicationhost.config to:

    <location path="MyWebSite">
        <system.webServer>
            <security>
                <authentication>
                    <anonymousAuthentication enabled="true" />
                    <windowsAuthentication enabled="false" />
                </authentication>
            </security>
        </system.webServer>
    </location>
    

    seems to have solved that issue.

    If you have any questions, or need more information, please let me know.