Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I protect my API that was built using Google Cloud Endpoints?

Tags:

The API is a backend to a mobile app. I don't need user authentication. I simply need a way to secure access to this API. Currently, my backend is exposed.

The documentation seems to only talk about user authentication and authorization, which is not what I need here. I just need to ensure only my mobile app can talk to this backend and no one else.

like image 278
mixmasteralan Avatar asked Jun 03 '13 04:06

mixmasteralan


People also ask

Is API endpoint is encrypted?

The only suggested option is asymmetric (or “one-way”) encryption algorithms for storing passwords. That way, neither an attacker nor any developer or sysadmin within the company will get to read customer passwords. Now, almost every API has a form of authentication, but in my opinion, the OAuth2 system works the best.

What is Endpoint in Google Cloud?

Endpoints is an API management system that helps you secure, monitor, analyze, and set quotas on your APIs using the same infrastructure Google uses for its own APIs.


2 Answers

Yes, you can do that: use authentication to secure your endpoints without doing user authentication.

I have found that this way of doing it is not well documented, and I haven't actually done it myself, but I intend to so I paid attention when I saw it being discussed on some of the IO13 videos (I think that's where I saw it):

Here's my understanding of what's involved:

  • Create a Google API project (though this doesn't really involve their API's, other than authentication itself).
  • Create OATH client ID's that are tied to your app via its package name and the SHA1 fingerprint of the certificate that you will sign the app with.

You will add these client ID's to the list of acceptable ID's for your endpoints. You will add the User parameter to your endpoints, but it will be null since no user is specified.

@ApiMethod(
   name = "sendInfo",
   clientIds = { Config.WEB_CLIENT_ID, Config.MY_APP_CLIENT_ID, Config.MY_DEBUG_CLIENT_ID },
   audiences = { Config.WEB_CLIENT_ID } 
   // Yes, you specify a 'web' ID even if this isn't a Web client.
)
public void sendInfo(User user, Info greeting) {

There is some decent documentation about the above, here: https://developers.google.com/appengine/docs/java/endpoints/auth

Your client app will specify these client ID's when formulating the endpoint service call. All the OATH details will get taken care of behind the scenes on your client device such that your client ID's are translated into authentication tokens.

HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience( ctx, Config.WEB_CLIENT_ID );
//credential.setSelectedAccountName( user );  // not specify a user
Myendpoint.Builder builder = new Myendpoint.Builder( transport, jsonFactory, credential );  

This client code is just my best guess - sorry. If anyone else has a reference for exactly what the client code should look like then I too would be interested.

like image 163
Tom Avatar answered Sep 30 '22 07:09

Tom


I'm sorry to say that Google doesn't provide a solution for your problem (which is my problem too). You can use their API key mechanism (see https://developers.google.com/console/help/new/#usingkeys), but there is a huge hole in this strategy courtesy of Google's own API explorer (see https://developers.google.com/apis-explorer/#p/), which is a great development tool to test API's, but exposes all Cloud Endpoint API's, not just Google's services API's. This means anyone with the name of your project can browse and call your API at their leisure since the API explorer circumvents the API key security. I found a workaround (based on bossylobster's great response to this post: Simple Access API (Developer Key) with Google Cloud Endpoint (Python) ), which is to pass a request field that is not part of the message request definition in your client API, and then read it in your API server. If you don't find the undocumented field, you raise an unauthorized exception. This will plug the hole created by the API explorer. In iOS (which I'm using for my app), you add a property to each request class (the ones created by Google's API generator tool) like so:

@property (copy) NSString *hiddenProperty;

and set its value to a key that you choose. In your server code (python in my case) you check for its existence and barf if you don't see it or its not set to the value that your server and client will agree on:

mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
        if mykey != 'my_supersecret_key':
            raise endpoints.UnauthorizedException('No, you dont!')

Hope this puts you on the right track

like image 33
Carlos Guzman Avatar answered Sep 30 '22 08:09

Carlos Guzman