HTTP Referer header in Struts 2 - struts2

How can I get the Referer header under Struts2? Right now I'm using an ActionSupport class and I can't seem to get a ServletActionContext object or implement the ServletRequestAware interface? (Where is ServletRequestAware in Struts2? which jar?)
I'm trying to set up an automatic redirect to a page's referer, stored in a session variable. When someone requests OAuth authentication, I store the referer in session and then send them to twitter. When they click allow, twitter sends them to my OAuth callback url. I do work there (persist access token) and then would like to send them to the referer I've stored in their session.
As I'm sure you can tell, I'm very new to Struts. I did spent over three hours reading Java docs, googling and otherwise trying to avoid wrath against me the noob cringe
Thanks!

Its considered "uncool" to reference HTTP elements in actions, but it becomes necessary so....
org.apache.struts2.interceptor.
ServletRequestAware.setServletRequest(HttpServletRequest request);
implement the interface, create a HttpServletRequest member variable and then set your member variable to the request in the implemented setter above. Now you have the request and you can do your request.getHeader("referer").
Some people also use the static method org.apache.struts2.ServletActionContext.getRequest() to get the request. Its considered bad form because it can make unit testing more difficult, but I see it all the time.

Related

MVC public ActionResults accessiblity from URL - is it safe?

I have being programing in MVC for a couple of months, recently I've been requested to revisit our authorization mechanism.
There is an attribute that checks weather a user can access an action result, but this attribute doesn't appear above all the public actions. There are plenty of JsonResults and other ActionResult actions which can be accessed from the URL bar.
My question is weather its worth adding that attribute to all the action results
or make some sort of attribute that won't allow access to the action unless its an ajax request or a post?
There is no functional difference between a browser request and an ajax request, they both come through the same http pipeline. Matter of a fact, sometimes executed outside of the forms authentication scheme, so adding [Authorize] attribute could block valid requests as well.
I would create some sort of authorization that requires the use of a header value of some sort to distinguish access to your Json methods.
You could add the header to every ajax request that was passed, but that would be easily visible in a program such as Fiddler or Firebug. You could use constantly changing authorization keys, but I think the headache of overhead would be at a higher cost than the data you're likely trying to protect.
You could decorate your methods with [AcceptVerbs(HttpVerbs.Post)] but again, those can be easily remedied using a program like Fiddler or Postman (chrome add-on)
You can use Request.IsAjaxRequest to ensure that the request came from an AJAX request. This will verify that the X-Requested-With header is present in the request, which is not present in a request that is made via the address bar.
What is the threat that are you trying to guard against? Checking the above is good to stop casual users from reading your JsonResults but ultimately you cannot protect public ActionResults or JsonResults because if someone wants to capture your response they can simply make their own request using curl:
curl --header "X-Requested-With: XmlHttpRequest" www.example.com/controller/method

How to write a Jax-Rs handler to authenticate the Requests

I want to write a Jax-Rs handler which should get all the REST calls given from a REST client and validate the OAuth access token and forward the http request to the respective resource classes.
I meant to say that, Jax-Rs handler will be the central place to handle all the request by validating the value passed by Authorization header.
I am expecting an urgent reply.
Take a look at how it's done in rexsl-page. Take a look at two classes, one for Google OAuth and another one for Facebook OAuth. You can also use the entire framework, or just copy given classes.
In a nutshell, you create a common parent class for all your JAX-RS resources. In this class you parse incoming HttpHeaders and tries to find a cookie with an encrypted authentication token (user identity). If found, you do nothing. If not found, you throw a WebApplicationException that redirects the user to the "please login" page.

How to make WebAPI actions accessible only from my app?

A common use case for WebAPI would be to have shell views rendered by MVC controllers, which contain javascript that then hit your API to access data.
But let's say you have some expensive API operations and you don't want people remotely accessing those endpoints -- you only want your MVC views, delivered by your application, to access them. How could you go about protecting them?
In this case Request.IsLocal doesn't work, because javascript is invoking it from the client's browser on their machine. Even if it did work, you need to dig to get the real HttpContext in order to find this property -- and that solution wouldn't work in self-hosted WebAPI.
For API endpoints that require a valid IPrincipal, you could protect them with the [Authorize] attribute. But what about API endpoints that you want your app to be able to access for anonymous users?
I have tried a solution and will post it separately as an answer, because I'm not sure if it's the best (or even a good) approach.
If your MVC site uses authentication, you could enable forms authentication for your Web API methods. You could write a custom [Authorize] attribute that will check for the presence of a forms authentication cookie which will be sent from the AJAX call and if present construct the principal.
Another possible solution is to protect your API with tokens which is a more RESTful style. The idea here is that when a user authenticates on your MVC website you could generate and pass a token to the view which will be used when sending the AJAX request to the Web API which in turn will verify the validity of the token and its signature.
If on the other hand your site doesn't use authentication, then things will get very complicated because you have no way of knowing whether the request comes from a trusted client since you are using javascript to call your API methods.
Before you go harping about "what have you tried", here is what I have tried. It works. Just not sure if there is a better way.
Create an MVC action filter and add it as a global filter during Application_Start.
Create an Http (WebAPI) action filter and use it on actions that should reject remote requests.
The global MVC filter does this:
Looks for a specific cookie in the request. If the cookie is there, its value is decrypted. The decrypted value should be a string representation of a DateTime, so use DateTime.TryParse to get it out. If the value is correctly parsed to a DateTime, and that DateTime is less than a day old, STOP HERE and do nothing else.
If the cookie is not there, or cannot be decrypted / parsed, or is older than a day, write a new cookie to the browser. Use the current DateTime.UtcNow.ToString() as the value, encrypt it, and write it with HttpOnly = false.
The WebAPI filter does this:
Looks for a specific cookie in the request. If the cookie is there, decrypt its value and try to parse it out as a DateTime.
If the value is a valid DateTime and is less than 2 days old, STOP HERE and do nothing else.
Otherwise, throw a 403 Forbidden exception.
A couple of notes about my current implementation of this. First of all, I use AES encryption with a shared secret and a salt. The shared secret is stored as an appSetting in web.config. For the salt, I enabled anonymous identification and used Request.AnonymousID as the salt. I'm not entirely fond of the salt because it's tricker to get at in a WebAPI controller, but not impossible as long as it is not self-hosted.

asp.net mvc authentication when call from client app

I use asp.net mvc controller instead of Web Service in my project.
When I call the controller from my client app,there will be a authentication problem. If I use Web Service ,I can use SOAP Header , but now in asp.net mvc, There is no soap header.
Please help.
I am really know a little about the web security.
Normal way of doing this when you come to http services is to pass it in authorization header in following format (if you are doing request from fiddler)
Authorization: Basic user123:pass123
user123:pass123 string is normally base64 encoded and you have to decode it on server side, check it against user store and authenticate the user. One example can be found here
You have several options.
Use a request header to contain some security token.
Include security tokens in the message that you send in the request body.
If your application uses something like Forms Authentication, you can ask consumers to call a login action, then grab the Forms Auth cookie and include that cookie in subsequent calls.
Since you are not using soap. You may use a simple http way. Which means you start a HttpRequest and handle result via HttpResponse. Thus you have to simulate a authenticate action as signing in from web browser.
You need to get the security token or cookie from the reponse. And put them into your following request. Thus your controller will recognize the request's identity.

ASP MVC 3 RequireHttps attribute change all links to https

I have an ASP MVC 3 website that has a Feedback form and should require SSL.
Now, I have an action called Feedback inside a controller called 'ContactUs' that is responsible for viewing and processing the feedback.
When I used the [RequireHttps] attribute on that action, it works nice and it changes the URL to "https". However, I noticed that all the links inside my page are now pointing to "https"! As if this attribute had forced the routing engine to apply the same to all links!!!
Of course, the SSL is only required for this single action and all the rest need to have normal http.
Could anyone tell me how to solve this?
In your case [RequireHttp] attribute might be OK if you clear out the login cookie - or you'll be sending it in clear-text across the wire. It might be more work than it's worth to avoid the slight cost of further HTTPS calls. SO is all about recycling questions and other users reading your question might think it's OK to drop down to HTTP after login, when it's usually the wrong thing to do.
The [RequireHttps] attribute can be used on a controller type or action method to say "this can be accessed only via SSL." Non-SSL requests to the controller or action will be redirected to the SSL version (if an HTTP GET) or rejected (if an HTTP POST). You can override the RequireHttpsAttribute and change this behavior if you wish. There's no [RequireHttp] attribute built-in that does the opposite, but you could easily make your own if you desired.
There are also overloads of Html.ActionLink() which take a protocol parameter; you can explicitly specify "http" or "https" as the protocol. Here's the MSDN documentation on one such overload. If you don't specify a protocol or if you call an overload which doesn't have a protocol parameter, it's assumed you wanted the link to have the same protocol as the current request.
The reason we don't have a [RequireHttp] attribute in MVC is that there’s not really much benefit to it. It’s not as interesting as [RequireHttps], and it encourages users to do the wrong thing. For example, many web sites log in via SSL and redirect back to HTTP after you’re logged in, which is absolutely the wrong thing to do. Your login cookie is just as secret as your username + password, and now you’re sending it in clear-text across the wire. Besides, you’ve already taken the time to perform the handshake and secure the channel (which is the bulk of what makes HTTPS slower than HTTP) before the MVC pipeline is run, so [RequireHttp] won’t make the current request or future requests much faster.
You can create another custom filter attribute to move back to http. Try solution from this question...
Why once SSL is enabled with [RequireHttps] at action level, it remains enabled forever?

Resources