从 GoogleAuthUtil 和 Plus.API 迁移

如果您之前使用 GoogleAuthUtil.getTokenPlus.API 与 Google 登录集成,则应迁移到最新的 Sign-In API 以提高安全性和更好的用户体验。

从访问令牌反模式迁移

您不应将通过 GoogleAuthUtil.getToken 获取的访问令牌作为身份断言发送到后端服务器,因为您无法轻松验证令牌是否已发送到后端,这会导致您容易遭到攻击者的访问令牌插入。

例如,如果您的 Android 代码如以下示例所示,您应该将应用迁移到当前的最佳做法。

Android 代码

在此示例中,访问令牌请求使用 oauth2: 以及范围字符串作为 GoogleAuthUtil.getToken 调用 (oauth2:https://www.googleapis.com/auth/plus.login) 的 scope 参数。

使用 ID 令牌流程或身份验证代码流程进行身份验证,而不要使用通过 GoogleAuthUtil.getToken 获取的访问令牌进行身份验证。

迁移到 ID 令牌流程

如果您只需要用户的 ID、电子邮件地址、姓名或个人资料照片网址,请使用 ID 令牌流程

如需迁移到 ID 令牌流程,请进行以下更改:

Android 客户端

  • 请根据需要移除 GET_ACCOUNTS(通讯录)权限
  • 使用 GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()AccountManager.newChooseAccountIntent() 将任何代码切换为具有 GoogleSignInOptions.Builder.requestIdToken(...) 配置的 Auth.GOOGLE_SIGN_IN_API

服务器端

迁移到服务器身份验证代码流程

如果您的服务器需要访问其他 Google API(例如 Google 云端硬盘、YouTube 或通讯录),请使用服务器身份验证代码流程

如需迁移到服务器身份验证代码流,请进行以下更改:

Android 客户端

  • 请根据需要移除 GET_ACCOUNTS(通讯录)权限
  • 使用 GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()AccountManager.newChooseAccountIntent() 将任何代码切换为具有 GoogleSignInOptions.Builder.requestServerAuthCode(...) 配置的 Auth.GOOGLE_SIGN_IN_API

服务器端

您仍然可以在新旧端点之间共享 API 访问逻辑。例如:

GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(...);
String accessToken = tokenResponse.getAccessToken();
String refreshToken = tokenResponse.getRefreshToken();
Long expiresInSeconds = tokenResponse.getExpiresInSeconds();

// Shared by your old and new implementation, old endpoint can pass null for refreshToken
private void driveAccess(String refreshToken, String accessToken, Long expiresInSeconds) {
   GoogleCredential credential = new GoogleCredential.Builder()
           .setTransPort(...)
           ...
           .build();
   credential.setAccessToken(accessToken);
   credential.setExpiresInSeconds(expiresInSeconds);
   credential.setRefreshToken(refreshToken);
}

从 GoogleAuthUtil ID 令牌流程迁移

如果您使用 GoogleAuthUtil 获取 ID 令牌,则应迁移到新的 Sign-In API ID 令牌流程

例如,如果您的 Android 代码如以下示例所示,您应进行迁移:

Android 代码

在此示例中,ID 令牌请求使用 audience:server:client_id 以及网络服务器的客户端 ID 作为 GoogleAuthUtil.getToken 调用 (audience:server:client_id:9414861317621.apps.googleusercontent.com) 的“范围”参数。

新的 Sign-In API ID 令牌流程具有以下优势:

  • 简化一键式登录体验
  • 您的服务器无需额外的网络调用即可获取用户个人资料信息

如需迁移到 ID 令牌流程,请进行以下更改:

Android 客户端

  • 请根据需要移除 GET_ACCOUNTS(通讯录)权限
  • 使用 GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()AccountManager.newChooseAccountIntent() 将任何代码切换为具有 GoogleSignInOptions.Builder.requestIdToken(...) 配置的 Auth.GOOGLE_SIGN_IN_API

服务器端

与使用已弃用的格式的 GoogleAuthUtil.getToken 不同,新的 Sign-In API 会颁发符合 OpenID Connect 规范的 ID 令牌。具体而言,发卡机构现在为 https://accounts.google.com,架构为 https

在迁移过程中,您的服务器需要验证来自新旧 Android 客户端的 ID 令牌。要验证令牌的两种格式,请根据您使用的客户端库进行更改(如果您使用的是一种):

  • Java(Google API 客户端库):升级到 1.21.0 或更高版本
  • PHP(Google API 客户端库):如果您使用的是 v1,请升级到 1.1.6 或更高版本;如果您使用的是 v2,请升级到 2.0.0-RC1 或更高版本
  • Node.js:升级到 0.9.7 或更高版本
  • Python 或您自己的实现:接受以下两个颁发者:https://accounts.google.comaccounts.google.com

从 GoogleAuthUtil 服务器身份验证代码流程迁移

如果您使用 GoogleAuthUtil 获取服务器身份验证代码,则应迁移到新的 Sign-In API 身份验证代码流程

例如,如果您的 Android 代码如以下示例所示,您应进行迁移:

Android 代码

在此示例中,服务器身份验证代码请求使用 oauth2:server:client_id + 您的 Web 服务器的客户端 ID 作为 GoogleAuthUtil.getToken 调用 (oauth2:server:client_id:9414861317621.apps.googleusercontent.com) 的 scope 参数。

新的 Sign-In API 身份验证代码流程具有以下优势:

  • 简化一键式登录体验
  • 如果您按照下面的迁移指南进行操作,您的服务器在执行身份验证代码交换时能够获得一个包含用户个人资料信息的 ID 令牌。

如需迁移到新的身份验证代码流程,请进行以下更改:

Android 客户端

  • 请根据需要移除 GET_ACCOUNTS(通讯录)权限
  • 使用 GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()AccountManager.newChooseAccountIntent() 将任何代码切换为具有 GoogleSignInOptions.Builder.requestServerAuthCode(...) 配置的 Auth.GOOGLE_SIGN_IN_API

服务器端

保留当前代码,但在构建 GoogleAuthorizationCodeTokenRequest 对象时指定 https://oauth2.googleapis.com/token 作为令牌服务器端点,这样您就可以在获取用户的电子邮件地址、用户 ID 和个人资料信息时获取 ID 令牌,而无需其他网络调用。此端点完全向后兼容,以下代码适用于从新旧 Android 客户端实现中检索到的服务器身份验证代码。

GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(
                transport,
                jsonFactory,
                // Use below for tokenServerEncodedUrl parameter
                "https://oauth2.googleapis.com/token",
                clientSecrets.getDetails().getClientId(),
                clientSecrets.getDetails().getClientSecret(),
                authCode,
                REDIRECT_URI)
               .execute();

...

// You can also get an ID token from auth code exchange.
GoogleIdToken googleIdToken = tokenResponse.parseIdToken();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
        .setAudience(Arrays.asList(SERVER_CLIENT_ID))
        .setIssuer("https://accounts.google.com")
        .build();
// Refer to ID token documentation to see how to get data from idToken object.
GoogleIdToken idToken = verifier.verify(idTokenString);
...