Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
332 views
in Technique[技术] by (71.8m points)

python - Is there a way to secure Google cloud endpoints proto datastore?

my setup:

  1. Python, google app engine using endpoints_proto_datastore
  2. iOS, endpoints Obj-C client library generator

Background

I've setup a test Google cloud endpoints api and had it running pretty quickly. It works great, using the test app in the iOS simulator, and using Google's APIs Explorer. The API is currently open to all with no authentication.

I'd like to: setup an API-key or system-credential that can be used by the app to ensure it alone can access the api - with all others being refused.

The method in the Google Endpoints Auth docs (1) is to create an OAuth 2.0 client ID using the Google Developers Console (2). So I have created an ID for an Installed Application of type: iOS. So far so good.

In the app the GTLService Object looks like this...

-(GTLServiceDemogaeapi *)myApiService {
    GTMOAuth2Authentication *auth = [[GTMOAuth2Authentication alloc] init];
    auth.clientID = @"10???????????????????ie.apps.googleusercontent.com";
    auth.clientSecret = @"z????????????3";
    auth.scope = @"https://www.googleapis.com/auth/userinfo.email";

    static GTLServiceDemogaeapi *service = nil;
    if (!service) {
        service = [[GTLServiceDemogaeapi alloc] init];
        service.authorizer = auth;
        service.retryEnabled = YES;
        [GTMHTTPFetcher setLoggingEnabled:YES];
    }
    return service;
 }

On GAE I've specified the (allowed_client_ids and added a user check to the methods...

@endpoints.api(name='demogaeapi', version='v1',
               allowed_client_ids=['10?????????????ie.apps.googleusercontent.com',
               endpoints.API_EXPLORER_CLIENT_ID],
               scopes=[endpoints.EMAIL_SCOPE],
               description='My Demo API')
class MyApi(remote.Service):

    @TestModel.method(path='testmodel/{id}', name='testmodel.insert', http_method='POST')
    def testModelInsert(self, test_model):

        current_user = endpoints.get_current_user()
        if current_user is None:
            raise endpoints.UnauthorizedException('Invalid token.')

The issue

current_user is always None so the method will always raise an exception. It appears that this is a known problem Issue 8848: Google Cloud Enpoints get_current_user API doesn't fill user_id (3) with no prospect of a fix soon.

Options?

  1. Wait until google fix Issue 8848. Can't really, we have a product to release!

EDIT: 15 May 2015 - Google made Issue 8848 status WontFix.

  1. I saw that it may be possible to use an API Key but while I have been able to create one - I have not found a way to enable it on the backend. I also note this method has a big hole where Google's APIs Explorer can defeat it see SO question (4).

  2. Does the @endpoints.api Argument: auth_level, described here (5), provide an answer? I tried using:

    @endpoints.api(name='demogaeapi', version='v1',
           auth_level=endpoints.AUTH_LEVEL.REQUIRED,
           scopes=[endpoints.EMAIL_SCOPE],
           description='My Demo API')
    

    But was able to use the api from the client app without using credentials. So it clearly did not add any authentication.

  3. Add a hiddenProperty to the client query holding a shared secret key. As described by bossylobster here (6) and Carlos here (7). I tried this but cannot see how to get at the raw request object (subject of another question How to get at the request object when using endpoints_proto_datastore.ndb?).

    @TestModel.method(path='testmodel/{id}', name='testmodel.insert', http_method='POST')
    def testModelInsert(self, test_model):
    
        mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
        if mykey != 'my_supersecret_key':
            raise endpoints.UnauthorizedException('No, you dont!')
    

EDIT: Another option has surfaced:

  1. Create a Service Account using the Google Developers Console (2). Use this account to gain access to the API without the need for user consent (via UI). However, Google appear to limit the number of apps that can be added this way to 15 or 20. See Google OAuth2 doc (8). We will likely exceed the limit.

The Question

Does anyone know how I can get any of these options working? Or should I be approaching this in a different way?

As you can see I'm in need of guidance, help, ideas...


As I need 10 reputation to post more than 2 links: here are the links I had to extract and add as references. Sort of ruined the flow of the question really.

  1. cloud.google.com/appengine/docs/python/endpoints/auth
  2. console.developers.google.com/
  3. code.google.com/p/googleappengine/issues/detail?id=8848
  4. stackoverflow.com/a/26133926/4102061
  5. cloud.google.com/appengine/docs/python/endpoints/create_api
  6. stackoverflow.com/a/16803274/4102061
  7. stackoverflow.com/a/26133926/4102061
  8. developers.google.com/accounts/docs/OAuth2
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...