App Flip für iOS

基于 OAuth 的 App Flip 关联 (App Flip) 会从 Google 应用打开你的 iOS 应用 以帮助 Google 应用用户更轻松地关联账号。您需要确保 对 iOS 应用稍作更改的代码以实现此功能。

在本文档中,您将学习如何修改 iOS 应用以支持 App Flip。

试用示例

App Flip 示例应用 演示了 iOS 上与 app flip 兼容的账号关联集成。 你可以使用此应用验证如何响应传入的通用 app flip 链接。

示例应用已预先配置为与应用快速关联测试工具 iOS 你可以用它来验证 iOS 应用与 App Flip 的集成,然后再 您需要配置与 Google 的账号关联。此应用可模拟通用链接 由 Google 移动应用在启用应用快速关联时触发。

工作原理

以下是 Google 应用和您的应用在以下情况下执行的流程步骤: 发生应用快速关联的情况:

  1. Google 应用会尝试打开您应用的通用链接。它能够 打开您的应用(前提是该应用已安装在用户设备上且与 通用链接如需了解详情,请参阅支持通用链接

  2. 您的应用会检查 client_idredirect_uri 参数是否已编码 与预期的 Google 通用链接相符。

  3. 您的应用从您的 OAuth2 服务器请求授权代码。末尾 则您的应用会向 Google 应用。为此,系统会打开 Google 通用链接,并在 参数(表示授权代码或错误)。

  4. Google 应用会处理传入的 Google 通用链接,并继续 流程的其余部分。如果提供了授权代码,则关联 立即完成令牌交换发生在服务器与服务器之间, 在基于浏览器的 OAuth 关联流程中的运作方式。如果错误代码为 关联流程即会继续,并采用备选选项。

修改 iOS 应用以支持 App Flip

如需支持 App Flip,请对 iOS 应用进行以下代码更改:

  1. 在应用委托中处理 NSUserActivityTypeBrowsingWeb
  2. 从网址中捕获 redirect_uristate 参数以供日后使用。
  3. 检查 redirect_uri 是否与以下格式匹配:
    https://oauth-redirect.googleusercontent.com/a/GOOGLE_APP_BUNDLE_ID
    https://oauth-redirect-sandbox.googleusercontent.com/a/GOOGLE_APP_BUNDLE_ID
  4. 验证客户端 ID 是否与预期值一致。请使用以下 代码示例:

    func application(_ application: UIApplication,
                     continue userActivity: NSUserActivity,
                     restorationHandler: @escaping ([Any]?) -> Void) -> Bool
    {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
            let incomingURL = userActivity.webpageURL,
            let components = URLComponents(url: incomingURL, resolvingAgainstBaseURL: false),
            let params = components.queryItems else {
                return false
        }
    
        if let clientId = params.filter({$0.name == "client_id"}).first?.value,
            let state = params.filter({$0.name == "state"}).first?.value,
            let redirectUri = params.filter({$0.name == "redirect_uri"}).first?.value {
    
            // Save the redirect_uri and state for later...
    
            // Verify the client id
            return (clientId == GOOGLE_CLIENT_ID)
        } else {
            // Missing required parameters
            return false
        }
    }
    
  5. 授权成功后,使用授权调用重定向 URI 代码。请使用以下代码示例:

    func returnAuthCode(code: String, state: String, redirectUri: String) {
        var redirectURL = URL(string: redirectUri)
        var components = URLComponents(url: redirectURL, resolvingAgainstBaseURL: false)
    
        // Return the authorization code and original state
        let paramAuthCode = URLQueryItem(name: "code", value: code)
        let paramState = URLQueryItem(name: "state", value: state)
        components?.queryItems = [paramAuthCode, paramState]
        if let resultURL = components?.url {
            UIApplication.shared.open(
                resultURL,
                options: [UIApplicationOpenURLOptionUniversalLinksOnly : true],
                completionHandler: nil)
        }
    }
    
  6. 如果发生错误,请改为将错误结果附加到重定向 URI 中。 请使用以下代码示例:

    func returnError(redirectUri: String) {
        var redirectURL = URL(string: redirectUri)
        var components = URLComponents(url: redirectURL, resolvingAgainstBaseURL: false)
    
        // Return the authorization code and original state
        let paramError = URLQueryItem(name: "error", value: "invalid_request")
        let paramDescription = URLQueryItem(name: "error_description", value: "Invalid Request")
        components?.queryItems = [paramError, paramDescription]
        if let resultURL = components?.url {
            UIApplication.shared.open(
                resultURL,
                options: [UIApplicationOpenURLOptionUniversalLinksOnly : true],
                completionHandler: nil)
        }
    }
    

Google 应用打开该应用后,它的通用链接将包含以下内容 查询参数:

  • client_id (String):通过您的应用注册的 Google client_id
  • scope (List of String):所请求的以空格分隔的范围列表。
  • state (String):Google 用于验证授权的 Nonce 结果会响应 Google 的传出请求。
  • redirect_uri (String):Google 的通用链接。“翻转”操作要打开的 URI Google 应用并传递结果。

成功返回授权结果时使用的参数:

  • code (String):授权代码的值(如果有)。
  • state (String):从传入的通用链接收到的确切值。

未成功返回授权结果时使用的参数:

  • error (String),替换为以下值:

    • cancelled:可恢复的错误。Google 应用将尝试登录账号 使用授权网址进行链接。例如,用户失败 登录、设备离线或连接超时。
    • unrecoverable:不可恢复的错误。例如,用户尝试关联已停用的账号。Google 应用将取消账号关联。
    • invalid_request:请求参数无效或缺失。此错误是可恢复的错误。Google 应用将尝试使用授权网址进行账号关联。
    • access_denied:用户拒绝了意见征求请求。此错误不可恢复;Google 应用中止关联。
  • error_descriptionString,可选):用户易于理解的错误消息。

对于所有错误类型,您必须将响应数据返回到指定的 REDIRECT_URI,以确保触发适当的回退。

修改授权端点以支持 App Flip

将您的平台配置为使用 Google 的 app flip 重定向网址来接受请求:

  • Google Home 应用
    https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast.dev
    https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast.enterprise
    https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast.dev
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast.enterprise
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast
    
  • Google 助理应用
    https://oauth-redirect.googleusercontent.com/a/com.google.OPA.dev
    https://oauth-redirect.googleusercontent.com/a/com.google.OPA.enterprise
    https://oauth-redirect.googleusercontent.com/a/com.google.OPA
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA.dev
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA.enterprise
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA
    

检查 client_id 以及 redirect_uri 参数指定的网址 与预期值相符。如果客户验证 失败,系统会将错误 invalid_request 返回给 redirect_uri