在 iOS 应用中访问 Google API

某些 Google 服务(例如云端硬盘、Gmail 等)提供公共 API,您可以使用这些 API 创建应用,帮助用户在这些服务中处理其数据。如需访问这些服务,应用必须实现其中一个 OAuth 2.0 客户端流程,以征得用户同意并获取访问令牌,从而获得对 API 的访问权限。

您可以使用 Google 登录库(该库会为您实现 OAuth 2.0 流程)来获取已登录用户的访问令牌。

前提条件

在您的 iOS 应用可以调用 Google API 之前,请完成以下设置步骤:

1. 为您的项目启用 API

任何调用 Google API 的应用都需要在 Google Cloud 控制台中启用这些 API。

如需为您的项目启用该 API,请按以下步骤操作:

  1. 在 Google Cloud 控制台中打开 API 库。
  2. 如果系统提示您选择一个项目或创建一个新项目,请视需要选择相应选项。
  3. 选择您要启用的 API,然后点击启用。

2. 创建授权凭据

任何使用 OAuth 2.0 访问 Google API 的 iOS 应用都必须具有授权凭证,以便向 Google 授权服务器标识该应用。以下步骤介绍了如何为项目创建凭据:

  1. 前往 Google Cloud 控制台中的“凭据”页面。
  2. 点击创建客户端(或创建凭证 > OAuth 客户端 ID)。
  3. 选择 iOS 应用类型。
  4. 输入 OAuth 客户端的名称。此名称用于在项目的“凭据”页面中标识客户端。
  5. 输入应用的软件包标识符。软件包 ID 是应用的 Info.plist 中 CFBundleIdentifier 键的值。该值通常显示在 Xcode 项目编辑器的“General”(常规)窗格或“Signing & Capabilities”(签名和功能)窗格中,或显示在 Apple App Store Connect 的“App Information”(应用信息)页面中。确认您使用的是正确的软件包 ID,因为如果您使用 App Check,则无法更改软件包 ID。
  6. (可选)如果应用已在 Apple App Store 中发布,请输入应用的 App Store ID。商店 ID 是一个数字字符串,包含在每个 Apple 应用商店 网址中。
  7. (可选)输入您的团队 ID。请参阅 Apple 开发者账号文档中的查找您的团队 ID。如果您为客户端启用了 App Check,则必须提供团队 ID。
  8. (可选)为您的 iOS 应用启用 App Check。启用 App Check 后,系统会使用 Apple 的 App Attest 服务来验证源自 OAuth 客户端的 OAuth 2.0 请求是否真实且来自您的应用,从而帮助降低应用冒充风险。
  9. 点击创建。

系统会生成您的客户端 ID,并将其显示在 Google Cloud 控制台中。将倒序客户端 ID 网址协议(例如 com.googleusercontent.apps.1234567890-abcdef)添加到应用的 Info.plist,以处理授权重定向。

3. 完成基本的 Google 登录功能集成

在请求增量范围和调用 Google API 之前,请先完成基本的 Google 登录集成。

1. 查看已授予的范围

在调用 Google API 之前,请使用 GIDGoogleUser 的 grantedScopes 属性检查已向您的应用授予哪些范围:

Swift

let driveScope = "https://www.googleapis.com/auth/drive.readonly"
let grantedScopes = user.grantedScopes
if grantedScopes == nil || !grantedScopes!.contains(driveScope) {
  // Request additional Drive scope.
}

Objective-C

NSString *driveScope = @"https://www.googleapis.com/auth/drive.readonly";

// Check if the user has granted the Drive scope
if (![user.grantedScopes containsObject:driveScope]) {
  // request additional drive scope
}

根据用户是否已授予特定范围,您可能需要请求额外范围,以便支持特定互动。

2. 申请其他范围

如果您需要请求其他范围,请调用 addScopes:presentingViewController:completion 或 addScopes:presentingWindow:completion,让用户向您的应用授予其他访问权限。

例如,如需请求对用户云端硬盘文件的只读访问权限,请执行以下操作:

Swift

let additionalScopes = ["https://www.googleapis.com/auth/drive.readonly"]
guard let currentUser = GIDSignIn.sharedInstance.currentUser else {
    return ;  /* Not signed in. */
}

currentUser.addScopes(additionalScopes, presenting: self) { signInResult, error in
    guard error == nil else { return }
    guard let signInResult = signInResult else { return }

    // Check if the user granted access to the scopes you requested.
}

Objective-C

NSArray *additionalScopes = @[ @"https://www.googleapis.com/auth/drive.readonly" ];
GIDGoogleUser *currentUser = GIDSignIn.sharedInstance.currentUser;

[currentUser addScopes:additionalScopes
           presentingViewController:self
                         completion:^(GIDSignInResult * _Nullable signInResult,
                                      NSError * _Nullable error) {
    if (error) { return; }
    if (signInResult == nil) { return; }

    // Check if the user granted access to the scopes you requested.
}];

3. 使用新令牌进行 API 调用

为确保您的 Google API 调用始终附加未过期的访问令牌,请将调用封装在 refreshTokensIfNeededWithCompletion: 代码块中:

Swift

currentUser.refreshTokensIfNeeded { user, error in
    guard error == nil else { return }
    guard let user = user else { return }

    // Get the access token to attach it to a REST or gRPC request.
    let accessToken = user.accessToken.tokenString

    // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
    // use with GTMAppAuth and the Google APIs client library.
    let authorizer = user.fetcherAuthorizer()
}

Objective-C

[currentUser refreshTokensIfNeededWithCompletion:^(
                              GIDGoogleUser * _Nullable user,
                              NSError * _Nullable error) {
    if (error) { return; }
    if (user == nil) { return; }

    // Get the access token to attach it to a REST or gRPC request.
    NSString *accessToken = user.accessToken.tokenString;

    // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
    // use with GTMAppAuth and the Google APIs client library.
    id<GTMFetcherAuthorizationProtocol> authorizer = [user fetcherAuthorizer];
}];

使用访问令牌调用 API,方法是在 REST 或 gRPC 请求 (Authorization: Bearer ACCESS_TOKEN) 的标头中添加访问令牌,或者将提取器授权方与 Google API 客户端库搭配使用。