0

How can you lock down the API Explorer in Cloud Endpoints so that it only works with a specific Gmail account (e.g. your console.developers.google.com email for example)?

Someone told me I could use a security-constraint in my web.xml file of my Cloud Endpoints project like so:

<security-constraint>
        <web-resource-collection>
           <web-resource-name>admin</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

But in the Using Auth with Endpoints docs it says:

"You must specify Endpoints auth following the directions provided on this page. Note that you cannot set a user login requirement following the instructions provided under Security and Authentication to configure the web.xml file, because this will result in a deployment failure."

So you can't do that...

Anyone know how you can restrict the Oauth2 authentication to a specific gmail account in the API Explorer? Because be default, you can sign in with any gmail account which will make you Oauth2 authenticated and then you can execute any API methods that use Oauth2 with the com.google.appengine.api.users.User user parameter in their methods.

Micro
  • 10,303
  • 14
  • 82
  • 120
  • You can probably get the email from the request and then restrict usage through your own code? – Patrice Aug 17 '15 at 18:00
  • @Patrice How would you get the email from the request? – Micro Aug 17 '15 at 18:39
  • sorry was typing a quick suggestion while going to lunch :P. If you have your user signed in with Oauth, you can get the email from this, no? – Patrice Aug 17 '15 at 18:40
  • @Patrice I see. That does indeed work. I just added `if(!user.getEmail().equals("myemail@gmail.com"))throw new UnauthorizedException("User is Not myemail!");` inside my cloud endpoints method and it did work as you said! However, that also means anyone accessing the API via android/ios won't be able to use it unless they have that same email. Which is actually answering a different question I had. =D – Micro Aug 17 '15 at 19:14

3 Answers3

1

You should be able to retrieve the auth token of a user and verify that its client ID is or isn't the API Explorer client ID. The client id is in com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID. The auth token will be passed through the Authorization header or the access_token or bearer_token query parameter. Either the header or the query parameters can be accessed by adding an HttpServletRequest parameter to an API method.

To verify an ID token, you need to use Google's API client library:

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(
    Client.getInstance().getHttpTransport(),
    Client.getInstance().getJsonFactory()).build();
GoogleIdToken token = verifier.verify(stringToken);
String clientId = token.getPayload().getAuthorizedParty();
saiyr
  • 2,575
  • 1
  • 11
  • 13
  • I'm a little confused. How do I retrieve the auth token of a user? – Micro Aug 19 '15 at 21:12
  • Updated my answer a bit. – saiyr Aug 19 '15 at 21:36
  • I'm sorry. I'm kind of a noob. How can you pass an auth token through `Authorization` header? Do you happen to have some sample code of a Cloud Endpoints API method doing just what you described? – Micro Aug 19 '15 at 23:59
  • If you have auth enabled for a method, API explorer will automatically send the correct header when you flip the auth switch, which is labeled "Authorize requests with OAuth 2.0". – saiyr Aug 20 '15 at 18:21
  • By "if you have auth enabled for a method" do you mean specifying the clientIds in the @API notation? – Micro Aug 20 '15 at 19:17
  • See "Adding a user parameter to methods for auth" in your question's link. The client ID may be specified at the API level rather than the method level, but you should specify a User parameter to enable auth on a method. – saiyr Aug 20 '15 at 19:47
  • I see. How can you access "`access_token` or `bearer_token` query parameters"? – Micro Aug 21 '15 at 15:17
  • Add an `HttpServletRequest` parameter to your method. Updated my answer again. – saiyr Aug 21 '15 at 16:24
  • To get the `Authorization` from the `HttpServletRequest` I know you can do this in your Api method `req.getHeader("Authorization")` - but how can I exactly get the `access_token` or `bearer_token`? – Micro Aug 21 '15 at 16:36
  • Ok so I got the `access_token` but how do I "verify that its Client ID is or isn't the api explorer client ID"? The `access_token` string is this very long string that looks nothing like the `132456789465123.apps.googleusercontent.com` format. – Micro Aug 25 '15 at 14:05
  • 1
    Added more detail to my answer. – saiyr Aug 25 '15 at 16:39
  • Question: how secure is it to pass in some secret via the `Authorization` header? Cloud Endpoints sends all requests over SSL. Is this enough? Or is it worth it to hash whatever custom `Authorization` string you are passing between requests? – Micro Sep 10 '15 at 14:50
1

See Cloud Endpoints: Control who can execute API through API Explorer for ways to limit who can execute your API through API Explorer.

Community
  • 1
  • 1
sam
  • 777
  • 2
  • 6
  • 19
0

If you really want to stop block it except for one email, using the "Users API" will let you get the authenticated user's email in your code.

After that, checking if the email is the only one you authorize, this will literally block it to everyone else.

Patrice
  • 4,641
  • 9
  • 33
  • 43
  • But what about using your Cloud Endpoints API inside of android or ios? It wouldn't work for all other users unless they had your one email... – Micro Aug 17 '15 at 19:49