User Authorization for Cloud Endpoints

2020-06-24 08:30发布

问题:

I'm working on a cloud endpoints backend and want to restrict certain operations to admin users.

My current code works like this:

@ApiMethod(httpMethod = "PATCH", name = "item.update", path = "items")
public Item update(Item newObject, User user)
        throws UnauthorizedException, OAuthRequestException {
    OAuthService oAuthService = OAuthServiceFactory.getOAuthService();
    if (!oAuthService.isUserAdmin()) {
        throw new UnauthorizedException("Only admin users can modify content.");
    }
    ...
}

I know app engine has a concept of user roles, but I'm curious if Endpoints do. I've tried using the OAuthService.isUserAdmin() call but that doesn't seem to be working out very well and the docs have a big old warning saying

Note: You should not confuse Endpoints auth with the auth for non-Endpoints App Engine web apps described in the article on configuration settings https://developers.google.com/appengine/articles/auth in the Admin Console, where you also specify the user login requirement in your web.xmlhttps://developers.google.com/appengine/docs/java/config/webxml#Security_and_Authentication file. That approach is not used with Endpoints."

Do I have to create some sort of authorization myself that uses the User object that's passed into the update method? Any thoughts?

回答1:

I had similar issues. Indeed OAuth user service has nothing to do with AppEngine user service. What I ended up doing was having a dedicated user type entity in my datastore where I store a specific flag (regular/admin) for each user. This flag is updated when I use AppEngine user service (i.e. so that the administrators I specified in the console get the proper admin flag).

In my endpoints API I get the current user authDomain and id, look up in my datastore to check whether it has the admin flag. The key of my user entity is composed of "authDomain:userId" and as I only support google user for now, it looks like (gmail.com:123456789)

This means that an administrator has to login once using the AppEngine UserService (i.e. a dedicated webpage in my case) so that the flag is properly updated



回答2:

I needed to do the same thing and validate some endpoint to grant access only to admin members listed in the project console and used the same implementation presented above, but the oAuthService.isUserAdmin() accept one or more string parameters, this parameters are scopes that you specify and the Oauth uses to get user informations, in my case i just set this parameter and it works like the code bellow.

OAuthService authService = OAuthServiceFactory.getOAuthService();
User user;
try {
  com.google.appengine.api.users.User currentUser =
      authService.getCurrentUser(Constants.EMAIL_SCOPE);
  if (currentUser != null && authService.isUserAdmin(Constants.EMAIL_SCOPE)) {
    user = new User(currentUser.getEmail());
    return user;
  }
...

The EMAIL_SCOPE constant is defined by

public static final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";

In my case i implemented an authenticator, to pass user information to endpoint only if it's admin user, you can read more about the authenticators if you want. https://cloud.google.com/appengine/docs/java/endpoints/javadoc/com/google/api/server/spi/config/Authenticator