Есть ли способ защитить облачное хранилище данных Proto в хранилище данных Google?

мои настройки:

  1. Python, движок приложения Google, использующий endpoints_proto_datastore
  2. iOS, конечная точка Генератор клиентской библиотеки Obj-C

Фон

Я настроил тестовый API-интерфейс облака Google и запустил его довольно быстро. Он отлично работает, используя тестовое приложение в симуляторе iOS и Google Explorer's Explorer. API в настоящее время открыт для всех без аутентификации.

Я хотел бы: настроить API-ключ или системные учетные данные, которые могут использоваться приложением, чтобы гарантировать, что оно само по себе может получить доступ к API - при этом всем остальным будет отказано.

Метод в документах Google Endpoints Auth (1) заключается в создании идентификатора клиента OAuth 2.0 с помощью консоли разработчиков Google (2). Итак, я создал идентификатор для установленного приложения типа: iOS. Все идет нормально.

В приложении объект GTLService выглядит следующим образом...

-(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;
 }

На GAE я указал (allow_client_ids и добавил проверку пользователя к методам...

@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.')

Проблема

current_user всегда None, поэтому метод всегда вызывает исключение. Похоже, что это известная проблема Проблема 8848: Google Cloud Enpoints API get_current_user не заполняет user_id (3) без возможности исправления в ближайшее время.

Опции?

  1. Подождите, пока Google исправит проблему 8848. Не могу, у нас есть продукт для выпуска!

РЕДАКТИРОВАТЬ: 15 мая 2015 года - Google сделал выпуск 8848 статус WontFix.

  1. Я видел, что можно использовать API-ключ, но, хотя я смог его создать, я не нашел способа включить его в бэкэнд. Я также отмечаю, что у этого метода есть большая дыра, в которой Google API Explorer может победить его, см. Вопрос (4).

  2. Предоставляет ли ответ @endpoints.api Аргумент: auth_level, описанный здесь (5)? Я пытался с помощью:

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

    Но был в состоянии использовать API-интерфейс из клиентского приложения без использования учетных данных. Так что явно не добавлялось никакой аутентификации.

  3. Добавьте hiddenProperty к клиентскому запросу, содержащему общий секретный ключ. Как описано здесь боссилобстером (6) и Карлосом здесь (7). Я пытался это, но не вижу, как получить в необработанном объекте запроса (предмет другого вопроса Как получить в объекте запроса при использовании 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!')
    

РЕДАКТИРОВАТЬ: появился еще один вариант:

  1. Создайте учетную запись службы с помощью консоли разработчиков Google (2). Используйте эту учетную запись для получения доступа к API без согласия пользователя (через пользовательский интерфейс). Тем не менее, похоже, что Google ограничивает количество приложений, которые могут быть добавлены этим способом, 15 или 20. См. Google OAuth2 doc (8). Мы, вероятно, превысим лимит.

Вопрос

Кто-нибудь знает, как я могу получить любой из этих вариантов работы? Или я должен подходить к этому по-другому?

Как видите, мне нужны руководство, помощь, идеи...


Поскольку мне нужно 10 репутации, чтобы опубликовать более 2 ссылок: вот ссылки, которые мне пришлось извлечь и добавить в качестве ссылок. Вроде как испортил ход вопроса действительно.

  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. stackru.com/a/26133926/4102061
  5. cloud.google.com/appengine/docs/python/endpoints/create_api
  6. stackru.com/a/16803274/4102061
  7. stackru.com/a/26133926/4102061
  8. developers.google.com/accounts/docs/OAuth2

1 ответ

Отличный вопрос и настоящая проблема. Я решил это, имея собственную таблицу базы данных "user". Long ключ (я использую Java) автоматически генерируется при записи, и это значение, которое я использую для уникальной идентификации пользователя с этого момента. В эту таблицу также записываются идентификатор Google (предоставляется при вызове через веб-страницу), адрес электронной почты и идентификатор iOS (при использовании приложения iOS без входа в учетную запись Google).

Когда вызывается моя конечная точка AppEngine, я использую информацию, которая присутствует в User параметр (только аутентифицированный адрес электронной почты для зарегистрированных клиентов) или отдельный, необязательный iosid Параметр для того, чтобы получить мой внутренний идентификатор пользователя из указанной таблицы и использовать его для уникальной идентификации моего пользователя.

Я использую ту же таблицу для хранения другой пользовательской информации, так что она на самом деле ничем не отличается от попытки использовать current_user в качестве первичного ключа, кроме меня, нужно было сделать три поля (googleid, email, iosid) проиндексированными для поиска.

Другие вопросы по тегам