I'm developing a GWT app running on the Google App Engine and wondering if I need to worry about Cross-site request forgery or is that automatically taken care of for me?
For every RPC request that requires authentication, I have the following code:
public class BookServiceImpl extends RemoteServiceServlet implements
BookService {
public void deleteInventory(Key<Inventory> inventoryKey) throws NotLoggedInException, InvalidStateException, NotFoundException {
DAO dao = new DAO();
// This will throw NotLoggedInException if user is not logged in
User user = dao.getCurrentUser();
// Do deletion here
}
}
public final class DAO extends DAOBase {
public User getCurrentUser() throws NotLoggedInException {
currentUser = UserServiceFactory.getUserService().getCurrentUser();
if(currentUser == null) {
throw new NotLoggedInException();
}
return currentUser;
}
I couldn't find any documentation on how the UserService checks authentication. Is it enough to rely on the code above or do I need to to more? I'm a beginner at this, but from what I understand to avoid CSRF attacks some of the strategies are:
adding an authentication token in
the request payload instead of just
checking a cookie
checking the HTTP
Referer header
I can see that I have cookies set from Google with what look like SID values, but I can't tell from the serialized Java objects in the payloads if tokens are being passed or not. I also don't know if the Referer header is being used or not.
So, am I worrying about a non-issue? If not, what is the best strategy here? This is a common enough problem, that there must be standard solutions out there...
If you were to put the same code in a regular servlet, you'd surely be vulnerable to XSRF. But since you are using GWTs RemoteServiceServlet - the answer depends on the version of GWT you are using.
Starting with the yet-to-be-release GWT 2.1, the RPC mechanism adds request headers and validates the presence of these headers in RemoteServiceServlet. This has its limitations - in particular, older versions of flash allow you to send the request headers from a different domain, but it does make things more difficult for a potential attacker.
If you want to adequately protect yourself from XSRF, refer to Lombardi's Development blog. The blog discusses two techniques. The first is a simple change that ports 2.1 changes to older versions of GWT. The second approach requires duplicating the session identifier as a request parameter, and is the recommended way to protect against XSRF.
References
GWT RPC - Does it do enough to protect against CSRF?
Lombardi development blog on GWT RPC and XSRF
Security for GWT Applications
Related
We have a java web app, which contains a lot of wars. We have an Oauth2 server(written by us) and we will have a lot clients( around 8). All of this will be under the same domain. Except of this we have another app( running on completely different tomcat. There a Liferay is used). The idea is that that the user will use them as they are using one app and they should not see big difference.
This is way now what I need is that when I log out from one place in some way to say the oauth2 server and all other clients to log out, too.
Because for client should be : I already logged out why in some parts I'm still logged in?
Currently I'm not sure how to do it.
And to a lot of places I read that normally this is not the practice.
Can you give me hints and explain me from where I can start? Maybe to use Oauth2 in my case in not the best choice?
For your requirement, you can implement OAuth2 using JDBC Token Store from Spring Security. For this to work once user logs out, all client should invoke your Delete token API where you can remove the Access Token
#FrameworkEndpoint
public class RevokeTokenEndpoint {
#Resource(name = "tokenServices")
ConsumerTokenServices tokenServices;
#RequestMapping(method = RequestMethod.DELETE, value = "/oauth/token")
#ResponseBody
public void revokeToken(HttpServletRequest request) {
//Delete the Token
}
}
Also, you should delete the refresh token.This way, the token would be invalidated once user logs-out and subsequent client can no longer use the same token
I've a requirement to build a Java based web application where a resource should be available only when all the authorized users of that resource are logged in. Also, if any authorized user logs out, the resource should no longer be available to any of them.
The resource could be of any type(html pages, pdf documents, spread sheets etc.,)
Is there any existing authentication standards/protocols that supports this type of requirement or I've to build this from scratch?
the resource should be available only when all the authorized users of that resource are logged in. Also, if any authorized user logs out, the resource should no longer be available to any of them.
Once you have given access to the resource to an user, this user will be able to download / take screenshots / save / record the resource, no matter if it's a PDF document, an image, an audio file. I don't know the context and the goal of what you're trying to build, but you should know that it will be insecure in any case.
Even putting this consideration aside, you'll need a real-time solution. Once the user has loaded the page containing the resource, you need to be able to hide or deny modification rights to him. This means you have to use something like WebSockets or Ajax Polling on the client side to have the frontend know when your server considers that not all the required users are online, and that the access to the resource should be "denied". But once more since this is client-side code it can easily be changed or altered, the requests it is sending can easily be blocked by the user, so it is once again inherently insecure.
I'd suggest giving a little bit of context here and describing what is the problem you're trying to solve, because most likely there's a more reasonable solution to solve it.
If what you need to do is to deny modification rights if not all the "resource owners" are online, it is more easily doable since the modifications will happen on the server side. In this case, a solution using WebSockets could quite easily be implemented but I don't know a library or framework that does such a thing. Most likely you will have to build it yourself.
If you're not constrained to use a specific web framework, feel free to try the following filter based implementation for jersey. Note that you still need to add a fair amount of custom code for handling the logic of "Collective authentication" as jersey only provides the basic tools required for this, and it doesn't explicitly implement the whole concept. Here's how you could do it, on a high level:
class AuthorizationProvider {
public void authenticate(ContainerRequestContext requestContext) {
// Here you would need to query your database to get the Collection of Users belonging
// to the "Collective" Role. You would then check if they are all logged in.
// A really abstract version would look like this, assuming you've already queried the DB
// and have a reference to the above mentioned Collection.
if (collectiveUsers.size == collectiveUsers.stream().filter(User::isLoggedIn).count()) {
return true;
}
return false;
}
}
class AuthorizationRequestFilter implements ContainerRequestFilter {
private final AuthorizationProvider authorizationProvider;
#Override
public void filter(ContainerRequestContext requestContext) {
if (authorizationProvider.authenticate(requestContext)) {
// serve whatever it is you want to serve if all required users are logged in
} else {
// otherwise reject the request
requestContext.abortWith(Response
.status(Response.Status.UNAUTHORIZED)
.entity("Resource available only after collective login")
.build());
}
}
}
#ApplicationPath("/")
class MyApplication extends ResourceConfig {
public MyApplication() {
// Register the filter
register(AuthorizationRequestFilter.class);
}
}
Apart from this, you would also need to handle the Login part.
You would assign these specific users the Collective role, and you would mark them as logged in, whenever they successfully pass through login authentication.
If all the above conditions are met, you should be able to successfully serve your "Collective only" page, only when all "Collective" users are logged in.
This also covers the part where if either one of these users logs out, you store the state in your database (mark the Collective user with isLoggedIn = false). So from this point on, whenever somebody requests the page, it will return Unauthorized.
Conversely, you can also attempt to implement SSE (Server sent events) to actively update the frontend part, if somebody logs out. With this, the page will actively be disabled even if somebody has already managed to get it previously.
Container request filter source and example, for reference, jersey docs
I'm trying to build a login screen for my GWT app. When you click the login button, the credentials (username & password) need to be sent to the server for authentication. I'm wondering what server communication method is a best fit for this: GWT-RPC or RequestFactory.
My understanding is the RequestFactory is more efficient and recommended over GWT-RPC, but it's more of a data/entity/persistence framework than a request-response framework like RPC. So although many GWT afficionados recommend using RequestFactory over GWT-RPC, I don't think RequestFactory can be used for this scenario. After all, I don't want to CRUD a login request, I want to send credentials to a server, perform secured authentication, and return a response to the client.
Am I correct? Is GWT-RPC my only option? or
Can RequestFactory be used. If so, how (need to see a code example of both client and server code)?
You can use either, although RF is very used with EntityProxy, it also is thought to work with ValueProxy which mean transmit any type. RF facilitates as well execution of remote procedures passing Proxy types or primitive types.
Said that, I would use the technology used primarily in my app. If you are using RPC send your login/password in a RPC request, but if you are using RF use it, so as you dont mix things, although you can mix RF, RPC, and plain Ajax without problems.
What you have to be aware of, is that normally, in applications requiring authentication you have to use a filter to check whether the user has a valid session when requesting RPC or RF, so in the case of sending a request for login, you have to jump somehow the auth filter.
Related with security, both scenarios are the same, you have to do the request in an https enabled environment.
[EDIT]
This could be the interface for the client and the remote implementation of a RF call for login, as you can see it is really easy, you can add any method you need to these classes:
#Service(value = LoginUserService.class)
public interface LoginUserRequest extends RequestContext {
Request<Boolean> login(String username, String password);
}
public class LoginUserService {
// Using static you dont need to provide a Locator for the service
static Boolean login(String username, String password) {
return true;
}
}
Related with auth filters for RF, you can take a look to this: GWT RequestFactory authentication functions
With both technology you can send such information to server side, but as already you pointed out the RequestFactory is dedicated to entity management. In your case is better to use GWT-RPC because in order to only send the credentials server side, and eventually retrieve the authentication result, you don't need the RequestFactory surplus (delta transmission, entity management).
For authentication, I would (almost) always use RequestBuilder, i.e. a simple HTTP(S!) POST. Why? Because this way you can implement a general authentication mechanism, that can not only be used by GWT apps. You gain the flexibility to add a simple HTML login page, single sign-on, standard server-side mechanisms (e.g. Spring security), etc.
A simple GWT re-login dialog is also no problem with RequestBuilder - to submit just username/password, GWT-RPC or RF is simply not necessary.
This question is only to confirm that I'm clear about this concept.
As far as I understand, Google Cloud Endpoints are kind of Google's implementation of REST services, so that they can't keep any "session" data in memory, therefore:
Users must send authentication data with each request.
All the data I want to use later on must be persisted, namely, with each API request I receive, I have to access the Datastore, do something and store the data again.
Is this correct? And if so, is this actually good in terms of performance?
Yes you can use session, only put another Paramether in your API method with HttpServlet:
#ApiMethod
public MyResponse getResponse( HttpServletRequest req, #Named("infoId") String infoId ) {
// Use 'req' as you would in a servlet, e.g.
String ipAddress = req.getRemoteAddr();
...
}
The datastore is pretty quick especially if you do a key lookup (as apposed to query). if you use NDB then you will have the benefit of auto memache your lookups.
Yes, your Cloud Endpoints API backend code (Java or Python) is still running on App Engine, so you have the same access to all resources you would have on App Engine.
Though you can't set client-side cookies for sessions, you still can obtain a user for a request and store user-specific data in the datastore. As #Shay Erlichmen mentioned, if you couple the datastore with memcache and an in-context cache (as ndb does), you can make these lookups very quick.
To do this in either Python or Java, either allowed_client_ids or audiences will need to be specified in the annotation/decorator on the API and/or on the method(s). See the docs for more info.
Python:
If you want to get a user in Python, call
endpoints.get_current_user()
from within a request that has been annotated with allowed_client_ids or audiences. If this returns None, then there is no valid user (and you should return a 401).
Java:
To get a user, on an annotated method (or method contained in an annotated API), simply specify a user object in the request:
import com.google.appengine.api.users.User;
...
public Model insert(Model model, User user) throws
OAuthRequestException, IOException {
and as in Python, check if user is null to determine if a valid OAuth 2.0 token was sent with the request.
I have following problem:
I have JAX-RS service which has a get operation:
#Path("/unsecure/")
#Produces("application/json")
public class MyUnsecureService {
public MyUnsecureService() {
}
#GET
#Path("/get/{id}")
#Produces("application/json")
public User get(#PathParam("id") String id) {
return User.get(id);
}
}
now, I'm going to open this API for mobile devices and I need authentication and authorization mechanism to access the API.
My problem is that I have trusted apps (internal jobs, a website which runs on my hosting) which should be able to expose this API as they want, with no limitation, and mobile devices, which should be able to expose this API only if they have a token, formed using real User's encrypted login/pass, which can be used on service-side to determine:
If the request to that method is allowed.
If the parameters are correct (so, the user can't get other user's info).
Is this possible to do using OAuth1 or OAuth2?
This is a very valid question to raise.
You might want to have a look at Oz (backgroud), which AFAIU will go a long way towards your use cases. Personally, I have interest to solve the issue for Java and track Eran's work with Java implementations ( jiron, hawkj ). To finally do Oz (or something like it) in Java.
Much is not ripe for publishing right now, but get in touch for details if you like.
Specific problem with JAX-RS right now seems to be SecurityContext.
The answer is found:
Using Client Credentials and Resource Owner authorization grants, which are implemented in OAuth2 implementation of Apache CXF.