OAuth2 on gRPC - Objective-C

This example demonstrates how to use OAuth2 on gRPC to makeauthenticated API calls on behalf of a user.

By walking through it you’ll also learn how to use the Objective-C gRPC API to:

  • Initialize and configure a remote call object before the RPC is started.
  • Set request metadata elements on a call, which are semantically equivalent toHTTP request headers.
  • Read response metadata from a call, which is equivalent to HTTP responseheaders and trailers.

It assumes you know the basics on how to make gRPC API calls using theObjective-C client library, as shown ingRPC Basics:Objective-C and theoverview, and are familiar with OAuth2 concepts like accesstoken.

Example code and setup

The example code for our tutorial is ingprc/examples/objective-c/auth_samplev1.28.1/examples/objective-c/auth_sample). Todownload the example, clone this repository by running the following commands:

  1. $ git clone -b v1.28.1 https://github.com/grpc/grpc
  2. $ cd grpc
  3. $ git submodule update --init

Then change your current directory to examples/objective-c/auth_sample:

  1. $ cd examples/objective-c/auth_sample

Our example is a simple application with two views. The first view lets a usersign in and out using the OAuth2 flow of Google’siOS SignInlibrary. (Google’s libraryis used in this example because the test gRPC service we are going to callexpects Google account credentials, but neither gRPC nor the Objective-C clientlibrary is tied to any specific OAuth2 provider). The second view makes a gRPCrequest to the test server, using the access token obtained by the first view.

Note

OAuth2 libraries need the application to register and obtain an ID fromthe identity provider (in the case of this example app, Google). The app’s XCodeproject is configured using that ID, so you shouldn’t copy this project “as is”for your own app: it would result in your app being identified in the consentscreen as “gRPC-AuthSample”, and not having access to real Google services.Instead, configure your own XCode project following the instructionshere.

As with the other Objective-C examples, you also should haveCocoapods installed, as well as the relevanttools to generate the client library code. You can obtain the latter byfollowingthese setup instructions.

Try it out!

To try the sample app, first have Cocoapods generate and install the client library for our .protofiles:

  1. $ pod install

(This might have to compile OpenSSL, which takes around 15 minutes if Cocoapodsdoesn’t have it yet on your computer’s cache).

Finally, open the XCode workspace created by Cocoapods, and run the app.

The first view, SelectUserViewController.h/m, asks you to sign in with yourGoogle account, and to give the “gRPC-AuthSample” app the following permissions:

  • View your email address.
  • View your basic profile info.
  • “Test scope for access to the Zoo service”.

This last permission, corresponding to the scopehttps://www.googleapis.com/auth/xapi.zoo doesn’t grant any real capability:it’s only used for testing. You can log out at any time.

The second view, MakeRPCViewController.h/m, makes a gRPC request to a testserver at https://grpc-test.sandbox.google.com, sending the access token alongwith the request. The test service simply validates the token and writes in itsresponse which user it belongs to, and which scopes it gives access to. (Theclient application already knows those two values; it’s a way to verify thateverything went as expected).

The next sections guide you step-by-step through how the gRPC call inMakeRPCViewController is performed. You can see the complete code inMakeRPCViewController.m.

Create a call with access token

To make an authenticated call, first you need to initialize a GRPCCallOptions object and configureit with the access token.

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

Then you need to create and start your call with this call options object. Assume you have a protoservice definition like this:

  1. option objc_class_prefix = "AUTH";
  2. service TestService {
  3. rpc UnaryCall(Request) returns (Response);
  4. }

A unaryCallWithMessage:responseHandler:callOptions: method, with which you’re already familiar, isgenerated for the AUTHTestService class:

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

Use this method to generated the RPC object with your request options object:

  1. GRPCUnaryProtoRPC *rpc = [client unaryCallWithMessage:myRequestMessage
  2. responseHandler:myResponseHandler
  3. callOptions:options];

You can then start the RPC represented by this object at any later time like this:

  1. [rpc start];

An alternative way to provide access token

Rather than setting oauth2AccessToken option in GRPCCallOptions before the RPC object iscreated, an alternative approach allows users providing access token at call start time.

To use this approach, first create a class in your project that conforms toGRPCAuthorizationProtocol protocol.

  1. @interface TokenProvider : NSObject<GRPCAuthorizationProtocol>
  2. ...
  3. @end
  4. @implementation TokenProvider
  5. - (void)getTokenWithHandler:(void (^)(NSString* token))handler {
  6. ...
  7. }
  8. @end

When creating an RPC object, pass an instance of this class to call option authTokenProvider:

  1. GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
  2. options.authTokenProvider = [[TokenProvider alloc] init];
  3. GRPCUnaryProtoCall *rpc = [client unaryCallWithMessage:myRequestMessage
  4. responseHandler:myResponseHandler
  5. callOptions:options] start];
  6. [rpc start];

When the call starts, it will call the TokenProvider instance’s getTokenWithHandler: method witha callback handler and waits for the callback. The TokenProvider instance may call the handlerat any time to provide the token for this call and resume the call process.