OAuth2

OAuth2

本示例演示了如何在 gRPC 上使用 OAuth2,以代表用户进行经过身份验证的 API 调用。

通过本指南,您还将学习如何使用 Objective-C gRPC API 来:

  • 在 RPC 启动前初始化并配置远程调用对象。
  • 在调用上设置请求元数据元素,这些元素在语义上等同于 HTTP 请求头。
  • 从调用中读取响应元数据,这等同于 HTTP 响应头和 Trailer。

本教程假设您了解如何使用 Objective-C 客户端库进行 gRPC API 调用(如基础教程gRPC 简介中所述),并且熟悉诸如访问令牌(access token)之类的 OAuth2 概念。

示例代码和设置

有关示例源代码,请参阅 gprc/examples/objective-c/auth_sample。要下载此示例,请通过运行以下命令克隆此仓库:

git clone -b v1.78.1 --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

我们的示例是一个包含两个视图的简单应用程序。第一个视图允许用户使用 Google 的 iOS 登录库 的 OAuth2 流程进行登录和注销。(此示例使用 Google 的库是因为我们要调用的测试 gRPC 服务需要 Google 帐户凭据,但 gRPC 本身和 Objective-C 客户端库并不绑定到任何特定的 OAuth2 提供商)。第二个视图使用第一个视图获得的访问令牌向测试服务器发起 gRPC 请求。

与其他 Objective-C 示例一样,您还应该安装 CocoaPods,以及生成客户端库代码的相关工具。您可以按照这些设置说明获取后者。

尝试一下!

要尝试此示例应用,请先让 CocoaPods 为我们的 .proto 文件生成并安装客户端库:

pod install

(如果您的计算机缓存中尚未包含 OpenSSL,此过程可能需要编译它,耗时约 15 分钟)。

最后,打开 CocoaPods 创建的 XCode 工作区并运行应用。

第一个视图 SelectUserViewController.h/m 会要求您使用 Google 帐户登录,并授予“gRPC-AuthSample”应用以下权限:

  • 查看您的电子邮件地址。
  • 查看您的基本个人资料信息。
  • “用于访问 Zoo 服务的测试范围”。

这最后一个权限对应于范围 https://www.googleapis.com/auth/xapi.zoo,它不授予任何实际能力,仅用于测试。您可以随时注销。

第二个视图 MakeRPCViewController.h/m 向位于 https://grpc-test.sandbox.google.com 的测试服务器发起 gRPC 请求,并随请求发送访问令牌。测试服务仅验证令牌,并在其响应中写入该令牌所属的用户以及它授予访问权限的范围。(客户端应用已知道这两个值;这是一种验证一切是否按预期进行的方法)。

接下来的章节将逐步指导您如何执行 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 对象之前在 GRPCCallOptions 中设置 oauth2AccessToken 选项外,还有一种替代方法允许用户在调用开始时提供访问令牌。

要使用此方法,请先在项目中创建一个符合 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 实例可以在任何时候调用该处理程序以提供此调用的令牌并恢复调用过程。