Scenario
I develop an MVC application that will be hosted in Windows Azure. During development, I test against a local database and local user membership service. In production, the application hits off a SQL Azure database and a cloud-hosted user membership service.
Sometimes I'll log in to the local version of the site with a user account that only exists on my local machine. If I forget to log out but switch my machine out of test mode, things start to break.
The Problem
I set my hosts
file to point my application URL at 127.255.0.0
so that browser requests are handled by the Azure emulator locally. This also means my test application and the production application use the same host name - cookies for one are seen as valid cookies for the other.
If I log in to my local system, an ASPXAUTH
cookie is created for the domain and contains the credentials of the user from my local system. If I forget to log out and switch my hosts
file back to normal (browser requests go to the live application), it sends the same ASPXAUTH
cookie to the server.
Since this user doesn't exist on the server, only locally, any requests like Membership.GetUser().Email
return an object null exception.
What I'd Like to Do
Ideally, I could inject some code early in the request to check that the user exists. Something like:
MembershipUser user = Membership.GetUser();
if(user == null) {
FormsAuthentication.SignOut();
}
This will automatically remove the ASPXAUTH
cookie for invalid users. But where do I put it? I started looking at my controllers - all of them inherit from a BaseController
class, but even putting this code in the base controller's constructor isn't early enough. I also looked at Global.asax
, but I'm not sure which event would be best to tie this action to.
Also, I'm not even sure this is the right way to do things. If not, what is the best way to ensure that the authentication cookie is for a valid user before just depending on the membership class like I am currently?
You create a base controller that overrides the
OnActionExecuting
and place your code there. Have all your controller controllers inherit from him. This theOnActionExecuting
from a older project I hadI'm basically checking if the request is authenticated otherwise I redirect it to logout action. http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onactionexecuting.aspx
You may handle the below event in you global.aspx:
EDIT:
In the above method,
Membership.GetUser()
will returnnull
, since it takes the userName fromHttpContext.Current.User.Identity.Name
property and in this event the user has not yet been authenticated. The above method is invoked by FormsAuthenticationModule when it raised Authenticate even. You can handle this event like so:You can also consider to handle the AuthenticateRequest event by declaring the below method in the global.aspx.
NOTE: Application_AuthenticateRequest event is fired after the FormsAuthentication_OnAuthenticate event.
Hope this helps..