OAuth2

OAuth2

この例では、ユーザーに代わって認証済み API 呼び出しを行うために gRPC で OAuth2 を使用する方法を説明します。

これを通して、Objective-C gRPC API を使用して以下のことも学習します。

  • RPC が開始される前に、リモート呼び出しオブジェクトを初期化および設定する。
  • 呼び出しでリクエストメタデータ要素を設定する。これは HTTP リクエストヘッダーと意味的に同等です。
  • 呼び出しからレスポンスメタデータを読み取る。これは HTTP レスポンスヘッダーおよびトレーラーと同等です。

Objective-C クライアントライブラリを使用した gRPC API 呼び出しの基本、基本チュートリアルおよびgRPC の紹介で示されている内容、またアクセス トークンのような OAuth2 の概念に精通していることを前提としています。

サンプルコードとセットアップ

例のソースについては、gprc/examples/objective-c/auth_sample を参照してください。例をダウンロードするには、次のコマンドを実行してこのリポジトリをクローンしてください。

git clone -b v1.74.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
cd grpc
git submodule update --init

次に、現在のディレクトリを examples/objective-c/auth_sample に変更します。

cd examples/objective-c/auth_sample

この例は、2 つのビューを持つシンプルなアプリケーションです。最初のビューでは、Google のiOS サインインライブラリの OAuth2 フローを使用してユーザーがサインインおよびサインアウトできるようにします。(この例では Google のライブラリを使用していますが、これは、呼び出すテスト gRPC サービスが Google アカウントの認証情報を期待しているためです。しかし、gRPC も Objective-C クライアントライブラリも特定の OAuth2 プロバイダーに依存しているわけではありません)。2 番目のビューは、最初のビューで取得したアクセス トークンを使用して、テストサーバーへの gRPC リクエストを行います。

他の Objective-C の例と同様に、CocoaPods がインストールされていること、およびクライアントライブラリコードを生成するための関連ツールがあることを確認してください。後者は、これらのセットアップ手順に従うことで取得できます。

試してみましょう!

サンプルアプリを試すには、まず CocoaPods で .proto ファイルのクライアントライブラリを生成してインストールします。

pod install

(これにより OpenSSL がコンパイルされる場合があります。CocoaPods がまだコンピューターのキャッシュに OpenSSL を持っていない場合、約 15 分かかることがあります)。

最後に、CocoaPods によって作成された XCode ワークスペースを開き、アプリを実行します。

最初のビューである SelectUserViewController.h/m では、Google アカウントでサインインするように求められ、「gRPC-AuthSample」アプリに次の権限を付与するように求められます。

  • メールアドレスを表示する。
  • 基本プロフィール情報を表示する。
  • 「Zoo サービスへのアクセス権限のテストスコープ」。

この最後の権限(スコープ https://www.googleapis.com/auth/xapi.zoo に対応)は、実際の機能を提供しません。テスト目的でのみ使用されます。いつでもログアウトできます。

2 番目のビューである MakeRPCViewController.h/m は、https://grpc-test.sandbox.google.comのテストサーバーに gRPC リクエストを送信し、アクセス トークンをリクエストと共に送信します。テストサービスは、トークンを検証し、そのユーザーが誰であるか、およびどのスコープへのアクセス権限があるかをレスポンスに書き込みます。(クライアント アプリケーションはこれらの 2 つの値を知っています。これは、すべてが期待どおりに進んだことを確認する方法です)。

次のセクションでは、MakeRPCViewController で gRPC 呼び出しがどのように実行されるかをステップバイステップで説明します。完全なコードは、MakeRPCViewController.m で確認できます。

アクセス トークンを使用した呼び出しを作成する

認証済み呼び出しを行うには、まず GRPCCallOptions オブジェクトを初期化し、アクセス トークンで設定する必要があります。

GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
options.oauth2AccessToken = myAccessToken;

次に、この呼び出しオプションオブジェクトを使用して呼び出しを作成し、開始します。次のような proto サービス定義があると仮定します。

option objc_class_prefix = "AUTH";

service TestService {
  rpc UnaryCall(Request) returns (Response);
}

AUTHTestService クラスには、unaryCallWithMessage:responseHandler:callOptions: メソッドが生成されており、これには既に慣れているはずです。

- (GRPCUnaryProtoRPC *)unaryCallWithMessage:(AUTHRequest *)message
                            responseHandler:(id<GRPCProtoResponseHandler>)responseHandler
                                callOptions:(GRPCCallOptions *)callOptions;

このメソッドを使用して、リクエスト オプション オブジェクトで RPC オブジェクトを生成します。

GRPCUnaryProtoRPC *rpc = [client unaryCallWithMessage:myRequestMessage
                                      responseHandler:myResponseHandler
                                          callOptions:options];

その後、このオブジェクトが表す RPC を、次のようにいつでも開始できます。

[rpc start];

アクセス トークンを提供する代替方法

RPC オブジェクトが作成される前に GRPCCallOptionsoauth2AccessToken オプションを設定する代わりに、代替アプローチにより、ユーザーは呼び出し開始時にアクセス トークンを提供できます。

このアプローチを使用するには、まずプロジェクト内に GRPCAuthorizationProtocol プロトコルに準拠するクラスを作成します。

@interface TokenProvider : NSObject<GRPCAuthorizationProtocol>
...
@end

@implementation TokenProvider

- (void)getTokenWithHandler:(void (^)(NSString* token))handler {
  ...
}

@end

RPC オブジェクトを作成する際に、このクラスのインスタンスを呼び出しオプション authTokenProvider に渡します。

GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
options.authTokenProvider = [[TokenProvider alloc] init];
GRPCUnaryProtoCall *rpc = [client unaryCallWithMessage:myRequestMessage
                                       responseHandler:myResponseHandler
                                           callOptions:options] start];
[rpc start];

呼び出しが開始されると、TokenProvider インスタンスの getTokenWithHandler: メソッドがコールバック handler と共に呼び出され、コールバックを待ちます。TokenProvider インスタンスは、いつでもハンドラを呼び出して、この呼び出しのトークンを提供し、呼び出しプロセスを再開できます。