Authentication on Google App Engine (web page)
Asked Answered
C

4

8

I would like to require the user to use a login/password when accessing some parts of my GAE (Google App Engine) application. I want to limit the access to the set of predefined users, e.g. on the page, where new data can be uploaded to the Datastore.

I found there are 3 ways on GAE how this can be solved, but it looks like only the last one (the most complicated) could be a solution for my issue:

  1. Use a deployment descriptor (<security-constraint> in web.xml). This is not nice, since those users have access, even as viewers to the GAE application's admin page, where they can see the billing history, browse Datastore, logs, etc. and this is something I have to avoid.

  2. Use the federated login (Open ID) (https://developers.google.com/appengine/articles/openid) and allow users to use their Google, Yahoo! or other identities to login. It is not a solution, since I want to limit the access to a small set of users (max. 5) and not allow everybody to use the application.

  3. The other option is to create simple custom login page accessible only via HTTPS and let the user send the username & password in a POST request (it can be plain since we have secure https connection) to a servlet, on the servlet generate some session identifier with specified validity and make it part of every subsequent request. It also needs to check each time the user sends a GET or POST request if the session identifier exists and does not expire meanwhile manually.

Any other/better proposals on how to maintain administrator accounts? Can HttpSession help with the last variant?

Kind Regards, STeN

Comedo answered 11/4, 2012 at 8:43 Comment(1)
You're conflating two completely separate issues here, authentication and authorization. You can combine either of the first two solutions (authentication) with your own solution to check for authorization. The easiest way to do this would be maintain a list of permitted users in the datastore, and look up users when they log in to check for permissions, as Peter and Adam suggest below.Instinct
T
2

I suggest the standard Google login page. Use something like this in you authentication controller (Java + Jersey Framework which is of course not necessary):

@Path("/login")
public Response login(@Context UriInfo ui) throws Exception {
  UserService userService = UserServiceFactory.getUserService();
  com.google.appengine.api.users.User user = userService.getCurrentUser();
  Response response;
  if (user == null) {
    URI uri = new URI(userService.createLoginURL(ui.getBaseUri().toString()));
    response = Response.seeOther(uri).build();
  } else {
    URI uri = new URI("/");
    response = Response.seeOther(uri).build();
  }
  return response;
}

@GET
@Path("/logout")
public Response logout(@Context UriInfo ui) throws Exception {
  UserService userService = UserServiceFactory.getUserService();
  com.google.appengine.api.users.User user = userService.getCurrentUser();
  Response response;
  if (user == null) {
    URI uri = new URI("/");
    response = Response.seeOther(uri).build();
  } else {
    URI uri = new URI(userService.createLogoutURL(ui.getBaseUri().toString()));
    response = Response.seeOther(uri).build();
  }
  return response;
}

The login method redirects you app to the Google login page if the user is missin (essentially not logged in). The logout method will logout the user.

Hope this helps

Town answered 11/4, 2012 at 12:14 Comment(0)
C
1

I use a combination of 2 and 3. I allow all users to login, but then I limit actions to particular e-mail addresses. These could be hard coded or (better) in the datastore and memcache (so that you don't have to query the datastore on every request). You could also cache this data in static variables in Java if you want to - just be aware that you might need to kill instances off manually if you change the users who have access. If, like me, you rarely / never change access then this shouldn't be a problem.

Allowing all users to login really gives them no access in my app - they see the admin pages but they're empty apart from a message saying "You do not have access to any of these administrative options".

Campeche answered 11/4, 2012 at 8:54 Comment(1)
Can anyone share some sample code for this on the Servlet side?Silvern
S
1

Some notes:

  1. AFAIK your assumption is not correct. Login to application has nothing to do with admin pages permission. You need to explicitly add users via "Permissions" page for them to have access to admin pages.

  2. You can still check user properties (email) after user logs in with OpenID and deny them access.

  3. This is of course doable. The natural way to track users are sessions. Google for examples.

In both cases 2. ' 3. it's advisable to have a servlet filter that checks session if there is user logged in and deny access (return 404) if user is not logged in.

Slate answered 11/4, 2012 at 9:4 Comment(0)
C
-1

Pay attention to the 3rd solution: instead of passing username & password my webapp asks username & apiSecret (generated automatically at the first login), so you can invalidate (and re-generate) quickly the apiSecret if something goes wrong.

There is another option: OAuth (https://developers.google.com/appengine/docs/java/oauth/). Here is my piece of code (UserAccount is my class to represent a User; User is "com.google.appengine.api.users.User", retrieveUser(..) is the function to retrieve my UserAccount from a logged "User"):

public UserAccount getUserLogged(HttpServletRequest request) {
    try {
        User loggedUser = oauthService.getCurrentUser();
        if(loggedUser!=null) {
            return super.userAB.retrieveUser(loggedUser);
        }
    } catch (OAuthRequestException e) {
        return null;
    }
    return null;
}
Colorfast answered 11/4, 2012 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.