Why can't override AuthorizeAttribute's OnAuthorization()? - asp.net-mvc

I've read the AuthorizeAttribute's source code, the code comment said:
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
Now i want to confirm this comment. Is it true? What's the 'worst case'? And how can i perform it?
Update:
I override OnAuthorization(), not filtered OutputCacheAttribute.
And then put a [OutputCache(Duration=30000,VaryByParam="*")] on an action which need be Authorized, but it does't work as expected, while a previously Authorized user was logged in, the latter user still need authorize. Or my question will be "How can i make the OutputCacheAttribute work"?
Update2:
After searching from the Internet, I found the reason. On .NET Framework 2.0.50727.4209 Or higher newer version, if the Page's Response contains cookies, the OutputCache will not work.
Obviously, ASP.NET MVC based on the newer version .NET Framework, with ASP.NET Forms Authenticate, the authorized page will response the authenticated ticket as cookie(HttpOnly) every time, and will not be cached.
That's weird, it seems the cache problem will never happen on authorized page in ASP.NET MVC Application. And why does the AuthorizeAttribute need to deal with it?
http://androidyou.blogspot.com/2012/10/aspnet-output-cache-not-working-and.html
Update3
My mistake, the normal Forms Authenticate doesn't response the authenticated ticket as cookie every time, but my custom AuthorizeAttribute does, so there's no doubt that the normal AuthrizeAttribute deal with the cache problem.

Related

ASP.NET MVC: A PreAuthorize-like event, Good throttle point for concurrent logons?

I want to allow a new login to 'kick' a prior login session by the same account, in ASP.NET MVC.
It seems pretty clear that I'll give each browser a cooking representing the session ID. I'll track the currently active session ID in a server-side cache. If an already-active user attempts to log in, I'll verify the business logic (username, password, has been at least 15 minutes since last activity), and then update the active session ID cached at the server.
Now my issue is, a browser is holding an invalid session ID. What is the best point for me to inject a rejection or redirect to sign-in for this scenario?
I could modify the AuthorizeAttribute, but it seems like there should be a cleaner place to do this that won't require me to search and replace all my Authorize attributes, for example via a Global.asax event, or a controller event (I've already extended Controller in my project).
For example, if PreAuthorize existed, I would write some code there to test the request's cookies for a valid user/session ID pair, and if it didn't exist, I could simply remove the authentication cookie from the request, which would result in a standard unauthorized redirection.
So after a bit of research, it seems that a custom AuthorizeAttribute would typically be the correct approach. However, in my case, since I already had a custom role provider implemented, it was just a line of code to do it there. This also benefited me because I only wanted session concurrency for a single role. A side effect is that any use of web.config to control access to static files by role is also in-effect for session concurrency.

Session not completely abandoned

I'm having an odd problem with my sessions. I haven't found a solution even after searching through the internet for a couple of days and I find it really strange that nobody else seems to be having this problem, which makes me think that it could be something I'm doing wrong.
If I log onto my website and visit a page decorated with the [Authorize] attribute (i.e. it requires the user to have logged on in order to access it), save the request with fiddler, log out and re-issue the request with fiddler one would expect that to fail (or re-direct me to the login page at least) but no, it returns the page as if I were still logged in.
When I'm logging out this is what I do (I'm using asp.net forms authentication)
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId",""));
That should work... but it doesn't.
In case anyone is wondering this is what I am using:
IIS 7.5
MVC 3.0
.NET 4.0
If I log onto my website and visit a page decorated with the [Authorize] attribute (i.e.
it requires the user to have logged on in order to access it), save
the request with fiddler, log out and re-issue the request with
fiddler one would expect that to fail
Why would you expect something like this? Forms authentication uses cookies to track logged in users. When you do FormsAuthentication.SignOut(); all that happens is that you remove the authentication cookie so that on subsequent requests from this browser the cookie is no longer sent and the server thinks that the user is not logged in. If on the other hand you have captured a valid cookie with Fiddler, you are perfectly capable of sending a valid request to the server (in the time for which this cookie is valid obviously). There is nothing on the server for it to know that you used fiddler, right? It's completely stateless.
If you wanted to avoid this behavior (which is by design) you will have to keep track somewhere on the server either a list of online users, or add some flag in the database about the user which indicates whether he is online or not. Then you will write a custom Authorize attribute that will check in this centralized store whether the user is allowed or not to login. When he logs out you will change this flag. Obviously if he closes his browser you won't be able to change the flag but if he signs out normally you will know that even if someone had captured the authentication cookie, he will not be able to use it to issue a valid request.

In an ASP.NET MVC 3 application, how can I save the post data in the where their session times out

I have an ASP.NET MVC 3 application. The site involves people writing lengthy responses using a textarea in a web form. Occasionally, users are complaining that they are getting redirected to the log in form after they post their data. I am not sure exactly why they are getting logged out because the users do not typically provide enough information on their errors. I believe it is due either to a session time out or the application has been restarted for some reason. This is on a shared web hosting site and it does not have its own app pool.
In any case, regardless of the reason, I would like to capture that post data and save it to a db or text file. How can I get the post data and save it while the controller redirects the user to the login screen.
I know the long term plan would be to identify why the timeout is occurring. But for now I want to be able to grab the post data and recover it at a later time.
First, in order to avoid timeouts, I would recommend using client-side heartbeat solution (like http://plugins.jquery.com/project/Heartbeat)
Second, assuming that you are using forms authentication, in order to save posted data, when Forms Authorization Module is redirecting your users, you will need to intercept redirects in EndRequest HttpApplication event handler in Global.asax or your own module.
The way to intercept those requests is not that straightforward, since on "EndRequest" pipeline step you will see 302 HTTP status code (redirect instruction), not 401 (Unauthorized error). So you may check if request is not authenticated (HttpContext.User.Identity.IsAuthenticated) and request is redirected - in this case you may save what you see in the request.
Otherwise you would need to disable forms authentication and use some solution, which is closer to ASP.NET MVC.
one solution can be to put a javasscript timer which keeps on hitting the server after specified interval to keep session alive until u figure out the cause of session time out (only i its the session timeout problem)
If you want to stop the session from timing out, you can add a hidden iframe on the page. For example, create a new page called KeepSessionAlive and do this:
<meta http-equiv="refresh" content="600">
where content = seconds.
I don't know about MVC 3, but the way you can get and store the post values is to catch them before redirecting the user to the Login page.

When does the .NET FormAuthentication ticket get checked and how do I tap into this event?

We are attempting to integrate an ASP.NET MVC site with our client's SSO system using PingFederate. I would like to use the built in FormsAuthentication framework to do this. The way I've gone about it so far is:
Set up my Web.config so that my FormsAuthentication LoginURL goes to my site's "BeginAuthentication" action on a "Security" controller. From this action, I set up some session variables (what URL was being accessed, for example, since Ping won't send this info back to me), and then redirect to our client's login page on an external site (www.client.com/Login for example).
From here, the authentication takes place and a cookie is generated on the same domain as the one that our application is running on which contains the unique identifier of the authenticated user, I've set it up so that once this happens, the Ping server will redirect to my "EndAuthentication" action on my "Security" controller.
In this action, I call my membership class's "ValidateUser" method which takes this unique identifier from the cookie and loads in the user on our application that this ID refers to. I save that logged in user in our Session (Session["LoggedInAs"], for example) and expire the cookie that contains the id of the authenticated user that the SSO system provided for me.
All of this works well. The issue I'm wondering about is what happens after our user has already authenticated and manually goes back to our client's login page (www.client.com/login) and logs in as another user. If they do that, then the flow from #2 above to number 3 happens as normal - but since there already exists an authenticated user on our site, it seems as though the FormsAuthentication system doesn't bother kicking off anything so I don't get a chance to check for the cookie I'm looking for to login as this new user. What I'd like to do is, somewhere in my Global.asax file (probably FormsAuthenticate_OnAuthenticate), check to see if the cookie that the SSO system sends to me exists, and if so, sign out of the application using FormsAuthentication.SignOut().
Another issue that seems to be related is that if I let my Session expire, the FormsAuthentication still seems to think I am authenticated and it lets me access a page even though no currently logged in user exists in my Session, so the page doesn't render correctly. Should I tap into the Session_End event and do FormsAuthentication.SignOut() here as well?
Basically, I want to know when the authentication ticket created by
System.Web.Security.FormsAuthentication.SetAuthCookie(..) gets checked in the flow of a request so that I can determine whether I need to SignOut() and force revalidation or not.
Thanks for any help. Sorry for the length of this message, trying to be as detailed as possible.
Mustafa
Welcome to the small section of Hades that is mixing session with formsauth.
If your needs are as complex as presented, you would get more sleep if you implement a full provider stack to share amongst the participating sites. Easier said than done, I know.
But to address your question:
from http://www.codeproject.com/Articles/39026/Exploring-Web-config-system-web-httpModules.aspx
On the way in....Check ticket and set identity #
app.AuthenticateRequest += System.Web.Security.FormsAuthenticationModule.OnEnter-->OnAuthenticate
On the way out... set the ticket and redirect as necessary
app.EndRequest += System.Web.Security.FormsAuthenticationModule.OnLeave
Reflector is your friend. ;-)
I don't know about a specific event for when the cookie is checked, but you could place the appropriate logic in Application_BeginRequest() and check the user's authentication state there.
Another issue that seems to be related
is that if I let my Session expire,
the FormsAuthentication still seems to
think I am authenticated and it lets
me access a page even though no
currently logged in user exists in my
Session, so the page doesn't render
correctly.
The life of the cookie (how long until ASP.NET feels it needs to ask for a password again) and how you are managing state are unrelated. The ASP.NET authentication is cookie based so that, should a developer want to, he could turn off viewstate, session, use no query strings or hidden fields and authentication still works.
If you want to tie the interval at which you request the password to how you are persisting data, then you will want your session expiration to be roughly the same as the cookie expiration, but they will never quite match up. It would be better to have two policies (one for how fast you throw away a users session data and one for how long you are willing to wait before you need to reask for a password)

ASP.NET MVC FormsAuthentication.SignOut doesn't work

I'm trying to use forms.signout but sometimes it does not log out the user and he still can navegates through the website.
How can I resolve this? I also configured web.config forms authentication, but it's still not working.
I'm using FormsAuthentication to autenticate an user passing he's login.
Thanks!!
I don't know what the cause is but a few things you might consider/try
are they actually able to still visit pages generated by the server or are they just going back to locally cached versions? What happens when they cause a postback that has code to check if they are authenticated does that work or does it fail? I think the later meaning they are signed out but viewing cached versions of the logged in page in which case you want to instruct the client not to cache the pages using for instances:
Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
You can try manually setting the cookie to be expired but this is a hack
FormsAuthentication.SignOut();
Context.Response.Cookies.Item(FormsAuthentication.FormsCookieName).Expires = Date.Now;
Response.Redirect("~/Somewhere.aspx");
Does the user have the domain (or a parent domain) in their trusted sites or intranet sites? I've run into some issues recently where a user is authenticated, but anonymous under circumstances where this is true. In my case it could also be that a parent site was, at one time, configured to allow windows integrated authentication. I've removed since removed that, but it didn't seem to help the problem. I haven't yet restarted IIS to see if this would have an effect. I've resorted to checking both that the user is authenticated and non-anonymous to ensure that the proper parts of the view are rendered. This is actually more accurate even though my login code should prevent having an anonymous login.

Resources