API はモバイル アプリのバックエンドです。ユーザー認証は必要ありません。この API へのアクセスを保護する方法が必要なだけです。現在、バックエンドが公開されています。
ドキュメントは、ユーザーの認証と承認についてのみ説明しているようですが、これはここで必要なものではありません。モバイル アプリだけがこのバックエンドと通信できるようにし、他のユーザーと通信できないようにする必要があります。
API はモバイル アプリのバックエンドです。ユーザー認証は必要ありません。この API へのアクセスを保護する方法が必要なだけです。現在、バックエンドが公開されています。
ドキュメントは、ユーザーの認証と承認についてのみ説明しているようですが、これはここで必要なものではありません。モバイル アプリだけがこのバックエンドと通信できるようにし、他のユーザーと通信できないようにする必要があります。
ドキュメントはクライアント専用です。私が必要としているのは、サーバー側でサービス アカウント機能を提供する方法に関するドキュメントです。
これはいくつかの異なることを意味する可能性がありますが、質問が求めていると思われることに対処したいと思います。サービス アカウントにサービスへのアクセスのみを許可する場合は、サービス アカウントの clientId を @Api/@ApiMethod アノテーションに追加し、GoogleCredential を作成して、通常どおりサービスを呼び出すだけです。具体的には...
Google 開発者コンソールで、新しいサービス アカウントを作成します。これにより、自動的にダウンロードされる .p12 ファイルが作成されます。これは、リンク先のドキュメントでクライアントによって使用されます。 .p12 を安全に保つことができない場合、これはパスワードよりもはるかに安全ではありません。 これが、Cloud Endpoints のドキュメントに明示的に記載されていない理由だと思います。
Google 開発者コンソールに表示される CLIENT ID を @Api または @ApiMethod アノテーションの clientIds に追加します。
import com.google.appengine.api.users.User
@ApiMethod(name = "doIt", scopes = { Constants.EMAIL_SCOPE },
clientIds = { "12345678901-12acg1ez8lf51spfl06lznd1dsasdfj.apps.googleusercontent.com" })
public void doIt(User user){ //by convention, add User parameter to existing params
// if no client id is passed or the oauth2 token doesn't
// match your clientId then user will be null and the dev server
// will print a warning message like this:
// WARNING: getCurrentUser: clientId 1234654321.apps.googleusercontent.com not allowed
//..
}
セキュリティで保護されていないバージョンと同じ方法でクライアントを構築します。唯一の違いは、サービスの MyService.Builder に渡す GoogleCredential オブジェクトを作成することです。
HttpTransport httpTransport = new NetHttpTransport(); // or build AndroidHttpClient on Android however you wish
JsonFactory jsonFactory = new JacksonFactory();
// assuming you put the .p12 for your service acccount
// (from the developer's console) on the classpath;
// when you deploy you'll have to figure out where you are really
// going to put this and load it in the appropriate manner
URL url = getClass().class.getResource("/YOURAPP-b12345677654.p12");
File p12file = new File(url.toURI());
GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder();
credentialBuilder.setTransport(httpTransport);
credentialBuilder.setJsonFactory(jsonFactory);
//NOTE: use service account EMAIL (not client id)
credentialBuilder.setServiceAccountId("12345678901-12acg1ez8lf51spfl06lznd1dsasdfj@developer.gserviceaccount.com"); credentialBuilder.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email"));
credentialBuilder.setServiceAccountPrivateKeyFromP12File(p12file);
GoogleCredential credential = credentialBuilder.build();
生成されたクライアントを、保護されていないバージョンと同じ方法で呼び出します。ただし、ビルダーは上記の Google 資格情報を最後の引数として取得します。
MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential);
builder.setApplicationName("APP NAME");
builder.setRootUrl("http://localhost:8080/_ah/api");
final MyService service = builder.build();
// invoke service same as unsecured version
申し訳ありませんが、Google はあなたの問題に対する解決策を提供していません (これは私の問題でもあります)。彼らの API キー メカニズムを使用できますが ( https://developers.google.com/console/help/new/#usingkeysを参照)、Google 独自の API エクスプローラー ( https:// developers.google.com/apis-explorer/#p/ ) は、API をテストするための優れた開発ツールですが、Google のサービス API だけでなく、すべての Cloud Endpoint API を公開しています。これは、API エクスプローラーが API キーのセキュリティを回避するため、プロジェクトの名前を知っている人なら誰でも自由に API を参照して呼び出すことができることを意味します。私は回避策を見つけました (この投稿に対する Bossylobster の素晴らしい反応に基づいています: Simple Access API (Developer Key) with Google Cloud Endpoint (Python))、クライアント API のメッセージ リクエスト定義の一部ではないリクエスト フィールドを渡し、API サーバーでそれを読み取ります。文書化されていないフィールドが見つからない場合は、許可されていない例外が発生します。これにより、API Explorer によって作成された穴が塞がれます。iOS (アプリに使用しています) では、次のように各リクエスト クラス (Google の API ジェネレーター ツールによって作成されたもの) にプロパティを追加します。
@property (copy) NSString *hiddenProperty;
その値を選択したキーに設定します。サーバーコード(私の場合はpython)で、その存在を確認し、サーバーとクライアントが同意する値に設定されていないか、表示されない場合はbarfを確認します。
mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
if mykey != 'my_supersecret_key':
raise endpoints.UnauthorizedException('No, you dont!')
これがあなたを正しい軌道に乗せることを願っています