I have a security constraint declared in web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>LoggedIn</web-resource-name>
<url-pattern>/screens/*</url-pattern>
</web-resource-collection>
<auth-constraint/>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
After logging in, when I make a GET request against the application I get the expected behavior e.g.
https://localhost:8443/Patrac/screens/user.xhtml --> results in access denied.
However, when I do a postback e.g.
<rich:menuItem submitMode="ajax" label="User" action="/screens/user"/>
I can view the screen. If I do a second identical postback, I get the access denied message. Each time I submit a postback the result alternates between displaying the screen and issuing a 403. The URL displayed in the browser alternates between the following:
https://localhost:8443/Patrac/screens/user.xhtml --> browser URL when access denied
https://localhost:8443/Patrac/public/403.xhtml --> browser URL when user screen is displayed
I understand the way the displayed browser URL in JSF lags behind the screen that is currently displayed, so that's no mystery. But I don't understand how I'm able to view the screen every other time the same postback is submitted. Again, GET requests are always denied.
EDIT :
I did try post-redirect-get and that made the strange behavior go away, as expected.
<rich:menuItem submitMode="ajax" label="User" action="/screens/user?faces-redirect=true"/>
However, I don't want to do PRG every time and besides PRG doesn't eliminate the security problem.
What am I missing here? Thanks for any insights!
The security constraint isn't checked on forwards, but on requests. This is by design.
So you definitely need the PRG pattern or, better, normal GET links. It'll instantly also make your webapp more SEO friendly and better bookmarkable. Using POST for page-to-page navigation is bad design anyway.
The "alternating behaviour" you're seeing is because the forward isn't checked, but any subsequent (postback) request on the same page is a fullworthy request and thus checked.
Related
I have an ASP.NET MVC 5 application where I'm trying to set a cookie. (Specifically, it's being done by a custom SessionIDManager.)
When I debug the code where the cookie gets set, it gets called as expected. When I look at the context after the controller action finishes, the cookie is in the response CookieCollection.
However, Fiddler & the browser show that the actual cookie is sometimes missing from the HTTP response headers.
It's consistent on a per-action basis; that is, some controllers/actions are fine, and others aren't, and it's always consistent as far as I can tell.
I don't see anything to distinguish the actions that succeed and those that don't - no difference in the attributes/filters/return type. (So it's not like the broken ones are trying to do Response.Redirect, etc.)
It's not a problem with the cookie setting code (trying to set it in the request instead of the response, etc.), or else it would never work. Does anybody have any suggestions for where else I could look to explain what's going on?
EDIT: While I can't recreate the success, I've recreated the failure in a new solution, which can be found here. My SessionIDManager gets called, I see the cookie in the response in the controller when I peek with the debug tools, but it doesn't actually make it into the HTTP response.
I have an ASP.MVC application. There are some sites in the application which are accesible only with certain user permissions. If user doesn't have required permissions I am redirecting to another controller and displaying page with Not authorized message.
When user without permission tries to visit restricted page using a link, browser caches destination. So always after clicking this link user will be redirected to Not Authorized page, even if permissions are granted. Browser skips directly to cached destination.
I have disabled caching on server side but, this doesn't seem to work in this case, any ideas how I can prevent browser from remembering links destination?
Thanks in advance,
Konrad
There's no logical reason for such a behavior to occur. First, check to make sure that the user is authorized like you think they are and that your redirect code is functioning properly (such that it only redirects if indeed the user is unauthorized). Short of that, make sure you're using a temporary redirect, and not redirect permanent. Although the browser shouldn't decide to just cache the resulting page indefinitely either way, it would perhaps have more cause to think it could if you're sending a permanent redirect.
Without seeing your code I'm not entirely sure there isn't something else going on, but here's a thought:
You can programmatically construct a hyperlink in your razor page to build a unique URL each time the page is refreshed. Just tack on a ?token=#uniqueVar onto the end of the url. The token need not be used in any place in your code, but if your uniqueVar is a timestamp or a Guid or something, your URL will be different every time.
I am running an MVC site along side Umbraco. The MVC site handles its own authentication completely separate to Umbraco, and ASP.NET Forms authentication for that matter. It sets a cookie and uses that internally to keep track of things.
Everything works fine for the most part, but if I am logged into my MVC site with the aforementioned cookie set, I try to login to the Umbraco admin section using the correct Umbraco credentials, it authenticates me and redirects me to the admin section but the WebAPI calls start to fail. The first is a call to: /umbraco/backoffice/UmbracoApi/UpdateCheck/GetCheck which returns a 417 Missing token null HTTP error response.
If I delete my custom cookie and refresh the page everything works fine.
I don't understand how my cookie can interfere with Umbraco's. It's not using ASP.NET Forms authentication or anything.
This error occurs because your request is not sending up the required angular CSRF headers + cookie. I'm not sure why this would be the case but it does seems strange if it is a fault of your custom cookie. Perhaps you can tell us some more information about your issue: Cookie name/value, steps to reproduce, specific version of Umbraco, hosting environment, etc....
Some info as to what is going on, the code that returns this error is here:
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs#L94
This is where the CSRF cookies are set:
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs
and this attribute is applied to two actions, one for login and one when we retrieve the current user data:
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Editors/AuthenticationController.cs#L103
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Editors/AuthenticationController.cs#L84
This is where the header is set in the JS:
https://github.com/umbraco/Umbraco-CMS/blob/5b9a98ad6ae9e63322c26f7b162204e34f7fcb54/src/Umbraco.Web.UI.Client/src/init.js#L11
Depending on your hosting environment/setup there has been strange reports of some firewalls stripping/changing data, for example:
http://our.umbraco.org/forum/umbraco-7/using-umbraco-7/47340-Umbraco-7-plus-ISA-Server-2006
Hopefully given the info above you might be able to pinpoint where the problem starts.
My initial thought is that you by accident used a key value for your cookie that is reserved by Umbraco, which could result in the wrong cookie being read, causing issues. The solution to this would be to simply rename your cookie.
If this is not the case I have another theory:
HTTP requests will always include all cookies which path/domain matches the domain of the resource you are requesting. They are sorted by path length primarily, and secondarily by creation time. If Umbraco backend for some reason finds the cookie used for authentication by its index number (wouldn't even be surprised) in the list, rather than key value, your custom cookie would cause the index to shift, thus making Umbraco look at the wrong cookie
So, if renaming the cookie didn't do anything, a fun thing to try could be to set path of the cookie to the shortest possible path, which would make your browser put the cookie further down the list, so the index won't shift.
It's just a theory though, so I'm interested in hearing how it goes :)
I'm recently facing the problem with last request url after login. Normally, everything works properly. But if I proceed following procedure I have troubles:
Open an App in one tab and log in
In this tab I go somewhere where AJAX request to the server are proceeded regularly
Open a new tab with the app (I'm still logged-in)
In this tab I log out
In the mean time the AJAX request from the 1st tab is proceeded automatically
with HTTP 401 (cause I've logged-out)
When I try to log in again in the 2nd tab than I receive the JSON of the AJAX request from the 1st tab because it was the last request.
I would suspect that Spring Security would neglect AJAX request for "last request url". Is it possible to set this somewhere? Or is there any good workaround to this?
Thanks,
Mateo
I don't think there is a general way to distinguish ajax requests from "regular" requests initiated by the user navigating a browser. If you can distinguish them in your application (e.g. by mapping ajax requests to specific urls that can be matched against some patterns), you could easily implement what you are looking for. (EDIT: An easier way to identify ajax requests is suggested by Sérgio in his below comment.)
The component that is responsible to perform redirection after a successful login is SavedRequestAwareAuthenticationSuccessHandler, therefore one possibile way to customize the framework's default behavior is to provide your own AuthenticationSuccessHandler, and inject it into the UsernamePasswordAuthenticationFilter. It should be possible to autowire the RequestCache in your class, and decide if you want to replay the last cached request or just ignore it in case it's known to be an ajax request.
so it is possible that form just shows validation error (like HTML is not allowed) instead of throwing an exception
A potentially dangerous Request.Form value was detected from the client
when I include HTML in input. I dont want to accept HTML, but I also dont like to get exception.
In ASP .NET 4.0, request validation is enabled for all requests by default.
http://www.asp.net/whitepapers/aspnet4/breaking-changes
You can still force your app to ignore this check.
See link for details:-
ValidateRequest="false" doesn't work in Asp.Net 4
However, I wouldn't advocate this strategy. It's much better to try to validate the text with Javascript before sending to the server to ensure it doesn't contain any characters that trip the ValidateRequest behaviour.
This question covers all of those characters:-
What characters or character combinations are invalid when ValidateRequest is set to true?
If your user does not have Javascript enabled, you'll still hit the error. In that (rare) case, you can fall back on customErrors so that you at least show something that is prettier than the yellow error page.
You can handle application behavior on errors in your web.config file:
</system.web>
…
<customErrors defaultRedirect="/ErrorPage" mode="RemoteOnly"></customErrors>
…
</system.web>
Moreover, beside specifying whether to show detailed errors or not you can also redirect user to a specific page to show him custom errors pages which you have designed.
For more information about this check msdn explanation for customErrors element