Is it possible to have multiple authentication methods for a java servlet? For example, have form based authentication in addition to open id based authentication so users can choose how they log in.
Yes.
However, I would suggest doing this using servlet filters instead of on the servlet itself.
http://brendangraetz.wordpress.com/2010/06/17/use-servlet-filters-for-user-authentication/
Follow the steps in that post, and override the isAuth() method such that it performs the authentication in however many modes you wish. In (very rough, untested) code:
#Override protected boolean isAuth()
{
String authMode = (String)(getSession(true).getAttribute("authMode"));
if (authMode == null) { return false; }
if (authMode.equals("open id") {
//do open id authentication steps here
//return true if authentication passes
}
else if (authMode.equals("some other authentication") {
//do some other authentication steps here
//return true if authentication passes
}
...
return false;
}
I am assuming of course that you already know how to implement the authentication steps in each mode individually.
The "trick" is to store a value in the HTTP session, immediately after the user performs the log in authentication, in the HTTP session. Based on this value, the filter will know what it should check or query whatever you specify before loading the servlet.
Another way of performing multiple authentication is with JAAS, the Java Authentication and Authorization service. Using JAAS, you can stack various authentication modules on top of each other, and you can configure which authentication module to run and which not to. This is called PAM (pluggable authentication module). Search for "J2SE JAAS" on Google or take a look at http://server.pramati.com/docstore/1270002/index.htm. These should help you to get started if you decide to go this route.
Yes it is possible, but it tends to be a bit tricky to implement.
For example, out-of-the-box SpringSecurity has support for local authentication, OpenId, X509 and other schemes, but combining them so that the user has alternative ways of logging in requires custom classes and custom wiring.
Related
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 using the Spring Security plugin in Grails. I have a controller which uses annotations for some of the secure actions but not for non-secure content. And sure enough, the sec:isLoggedIn and other sec:loggedInUserInfo tags work for the secured actions, but they always show up as non logged in even when the user is logged in for the non-secure views. Here's what my controller looks like:
class ContentController {
def anonymousContent() {
getContent(params, 'pages')
}
#Secured(['ROLE_USER', 'ROLE_ADMIN'])
def secureContent() {
getContent(params, 'secure')
}
private getContent(params, path) {
def viewPath = "${path}/${params.view}"
render(view: viewPath, model: params)
}
}
I should mention that I am using some custom authentication as part of a SSO solution which basically has me overriding a couple classes like AuthenticationProvider, AbstractAuthenticationToken, LoginUrlAuthenticationEntryPoint, AbstractAuthenticationProcessingFilter, but I wouldn't think it should be causing this issue.
Any ideas would be appreciated. Thanks
For anyone else running in to this problem, I managed to find the issue was related to mod_proxy. I was using it to hide my context path which was in turn causing the servlet to have trouble reading the session cookie for my app. For unauthenticated pages this would mean it created a whole new session each time. For authenticated pages, it would create a new session as well, but thanks to our SSO authentication mechanism it would actually re-authenticate with each request. Probably good we caught it as that's an expensive operation. The answer was really to set the cookie path (setCookiePath) to root ('/') in our tomcat configuration. Hope that helps someone else :)
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.
I went through a similar question here. But I am yet not clear over concepts. Here is my scenario...
My client (a mobile device app) has a login screen to enter username, password. After submission, he should see the list of books in the database plus the list of books subscribed by that user.
I am having a /LoginService which accepts username, password & checks a mysql database for credential validation. Only after authorization....I have a /BookService ; GET on which returns all the books in database.
Should I use GET, POST or PUT on my loginservice ? Since a login request is a read-only operation, I should use GET - but this sounds stupid for browser(as the submitted data is visible).
What are accesstokens (mentioned in the linked answer above), and how to generate them using Java ? I am using Jersey for development. Are they a secure way of authorization ?
Thanks !
As far as I understand you are trying to implement stetefull communication between client and server. So you login with first request and then use some kind of token to make further requests.
Generally I can recommend you to have stateless communication. This means, that you authenticate and authorize each request. In this scenario you don't need LoginRestService. Important points here are:
Client can provide userName and password through HTTP Headers (non-standard, something like UserName: user and Password: secret).
At the server side you can use
Use AOP: just wrap you BooksService with AuthAdvice (which you should write yourself). In advise you access somehow (with Jersey functionality) HTTP request, take correspondent headers from it, authenticate and authorize user (that you load from DB), put user in ThreadLocal (so that it would be available to the rest of your app) if needed and just invoke correspondent method or throw exception if something wrong with credentials.
Use Jersey functionality: (sorry I'm not very familliar with Jersey, I'm using CXF, but conceptually it should be the same) just create some kind of AuthHendler and put it in request pre-processing pipeline. In this handler you need tho make exactly the same as in AuthAdvice
Now each of your request would be authenticated and authorized when it reaches BooksService. Generally stateless implementation is much better for scalability.
If you want to go statefull way, than you can just use HttpSession. LoginService.login() should be POST request because you actually making some side-effects at the server. Service will perform authentication of your user according to provided username and password and put loaded User object to session. At this point, the server side session is created and client has session ID in the cookies. So further requests should automatically send it to the server. In order to authorize requests to BooksService you still need some kind of Advice of Handler (see stateless solution). The only difference: this time user is taken from the HttpSession (you should check that you are logged in!).
Update: And use HTTPS! :)
I've got nothing to dispute in Easy Angel's answer, but got the impression you'd like some additional comment on the concepts too.
The problem is clearer if you think in terms of resources rather than services. Think of your proposed login as generating a new authorization resource, rather than querying a login service. Then you see that POST makes perfect sense.
The authorization token would be a key for your user into the session object (as explained in EA's answer). You'd probably want to generate it by concatenating some information that uniquely identifies that user and hashing it. I certainly agree that a stateless authentication method would be preferable, if you're aiming to get all the benefits of REST.
Use what is available in HTTP: HTTP AUTH over SSL.
Protect all your resources with HTTP AUTH and the browser will take care of providing a login for the user.
If you need session information on top of that, use cookies or a session parameter.
Cookies were made for exactly these kinds of purposes and usually work well.
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