14

I have an Endpoints API deployed on App Engine. I have no problem using the Google API Explorer to make requests to API methods that do NOT require being logged in. The URL I'm using for that is:

https://developers.google.com/apis-explorer/?base=https://[MY_APP_ID].appspot.com/_ah/api

Where I am stuck is calling API methods that require the user to be logged in, such as this one:

@ApiMethod(name = "config.get",
        clientIds = {"[MY_CLIENT_ID].apps.googleusercontent.com", "com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID"},
        audiences = {"[MY_APP_ID].appspot.com"},
        scopes = {"https://www.googleapis.com/auth/userinfo.email"})
public Config getConfig(User user) throws OAuthRequestException {
    log.fine("user: " + user);

    if (user == null) {
        throw new OAuthRequestException("You must be logged in in order to get config.");
    }

    if (!userService.isUserAdmin()) {
        throw new OAuthRequestException("You must be an App Engine admin in order to get config.");
    }
    ...

On the API Explorer there's a switch top right that, when clicked, allows me to specify scopes and authorise. I'm doing that with just the userinfo.email scope checked. It makes no difference. The response I get from my call is:

503 Service Unavailable

- Show headers -

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "backendError",
    "message": "java.lang.IllegalStateException: The current user is not logged in."
   }
  ],
  "code": 503,
  "message": "java.lang.IllegalStateException: The current user is not logged in."
 }
}

Back when Endpoints was in Trusted Tester phase, I remember there being a manual step in the OAuth2 Playground to get an ID token instead of an access token or some such thing. If that is still required, any mention of that seems to have disappeared from the Endpoints docs now and I see now way to swap out tokens in the API Explorer either.

Eliot
  • 2,349
  • 3
  • 28
  • 45
  • Oh, and I've also added the OAuth playground (https://developers.google.com/oauthplayground) to the list of redirect URIs in the API console. – Eliot Apr 21 '13 at 15:22

2 Answers2

12

I see you've got "com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID" in quotes. If that's not a typo in your transcription to Stack Overflow, that's a problem. The value is already a string, so you're just passing in the text com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID (not the actual client ID) as the whitelisted scope. That won't work. Try this instead:

@ApiMethod(name = "config.get",
        clientIds = {"[MY_CLIENT_ID].apps.googleusercontent.com", com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
        audiences = {"[MY_APP_ID].appspot.com"},
        scopes = {"https://www.googleapis.com/auth/userinfo.email"})

Edit: isUserAdmin is unsupported within Endpoints, and is likely a secondary cause of error. I'd suggest filing a feature request for supporting this method on the provided User object (we likely won't provide support for the user service itself, so it's separate from OAuth login.)

Dan Holevoet
  • 9,183
  • 1
  • 33
  • 49
  • Good spotting! Have fixed that and redeployed but it doesn't seem to have made any difference. Was certainly broken but there's something else broken too. – Eliot Apr 25 '13 at 01:04
  • I'm unable to reproduce this issue using nearly identical example code. Is the code in your initial question what you are using now? It's curious that you're getting a 503 instead of a 401, which is what OAuthRequestException should map to (I see a 401 when I test this myself). – Dan Holevoet Apr 25 '13 at 20:58
  • This is definitely what's deployed. If I hit this method without being logged in I get a 401 like you. If I then login using the OAuth2 button on the API Explorer and hit it again, I get a 503. However, if I hit *another* Endpoints method I've got which requires the user to be logged in but does NOT include any use of the App Engine UserService, it works fine. Can I not use stuff like UserService.isUserAdmin() in Endpoints? Presumably that stuff is still based on HTTP sessions rather than OAuth access tokens? – Eliot Apr 26 '13 at 14:36
  • 1
    Oh, wow, I'm blind. No, you can't use isUserAdmin in Endpoints. If you want admin-like functionality you'll need to manage it with your own ACL. – Dan Holevoet Apr 26 '13 at 17:54
  • 1
    OK. I guess that makes sense. Might be a good one for the docs though. Thanks for your help. – Eliot Apr 26 '13 at 21:28
0

I don't know when this was introduced, but if you use OAuth2, instead of UserService.isUserAdmin() you can use OAuthServiceFactory.getOAuthService().isUserAdmin(EMAIL_SCOPE) where EMAIL_SCOPE is "https://www.googleapis.com/auth/userinfo.email".

This makes it easy to use the old OpenId or OAUth2:

boolean isAdmin = false;
try {
  isAdmin = userService.isUserAdmin());
} catch (IllegalStateException e1) {
  try {
    isAdmin = OAuthServiceFactory.getOAuthService().isUserAdmin(EMAIL_SCOPE);
  } catch (Exception e2) {}
}

The original question was asked several years ago, but maybe this will help others.

rakensi
  • 1,437
  • 1
  • 15
  • 20