Google登录服务器实施返回401

时间:2015-11-06 19:13:51

标签: android google-play-services google-signin googlesigninaccount

在尝试从Play服务8.1中的Google+登录切换到Play服务8.3中的新Google登录时,服务器端组件停止工作,并开始在每次API调用到Google服务器上投放401

当Android应用使用Google Play Services 8.1:

的build.gradle:

compile 'com.google.android.gms:play-services-plus:8.1.0'

Android客户端:

mGoogleApiClient = new GoogleApiClient.Builder(this)
         .addApi(Plus.API)
         .addScope(Plus.SCOPE_PLUS_PROFILE)
         .addScope(new Scope("email"))
         .build();
String scopes = "oauth2:profile email";    
accessToken = GoogleAuthUtil.getToken(
        SignInActivity.this, 
        Plus.AccountApi.getAccountName(mGoogleApiClient), 
        scopes); // then send accessToken to the server

服务器端:

 // get user details from Google+ REST API
 GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
 Plus plusService = new Plus.Builder(new NetHttpTransport(), new JacksonFactory(), null)
         .setApplicationName("AppName")
         .setHttpRequestInitializer(credential)
         .build();
 Person person = plusService.people().get("me").execute();

切换到Google Play Services 8.3时:

的build.gradle:

 compile 'com.google.android.gms:play-services-auth:8.3.0'

Android应用

GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestServerAuthCode("GOOGLE_CLIENT_ID", false)
        .requestEmail()
        .build();
 mGoogleApiClient = new GoogleApiClient.Builder(this)
         .addApi(Auth.GOOGLE_SIGN_IN_API, googleSignInOptions)
         .build();

使用相同的服务器代码,get(" me")调用将返回:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
  "code" : 401,
  "errors" : [ {
    "domain" : "global",
    "location" : "Authorization",
    "locationType" : "header",
    "message" : "Invalid Credentials",
    "reason" : "authError"
  } ],
  "message" : "Invalid Credentials"
}

1 个答案:

答案 0 :(得分:2)

另请注意,使用新的Google登录Api,只要在Android客户端上请求基本配置文件范围,您就可以在交换服务器上的令牌代码时获取ID令牌。如果您要查找的只是全名,电子邮件地址和图片,那应该足够了。

您将结果从GoogleSignInAccount.getServerAuthCode()传递到您的服务器,然后使用以下代码:

HttpTransport transport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();

try {
  // Exchanges the code for tokens.
  GoogleTokenResponse response = new GoogleAuthorizationCodeTokenRequest(
      transport,
      jsonFactory,
      // Very important: Explicitly specify this new endpoint.
      "https://www.googleapis.com/oauth2/v4/token",
      SERVER_CLIENT_ID,
      SERVER_CLIENT_SECRET,
      serverAuthCodeFromAndroid,
      "" /* redirectUri, must be blank with auth code coming from Android */)
    .execute();

  // Get the id token from the exchange result
  // It will be non-null if basic profile scopes are requested 
  // when requesting the serverAuthCode on (Android) client side.
  GoogleIdToken googleIdToken = response.parseIdToken();

  // Verify the id token
  GoogleIdTokenVerifier verifier =
          new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
              // For some old version of libraries
              .setIssuer("https://accounts.google.com")
              .setAudience(Arrays.asList(SERVER_CLIENT_ID))
              .build();
  boolean verified = googleIdToken.verify(verifier);
  if (!verified) {
    // Spoofing!! This is not a legitimate id token issued by 
    // Google to your web application!
    return;
  }

  // Get the profile info.
  GoogleIdToken.Payload payload = googleIdToken.getPayload();
  String userId = payload.getSubject();
  String email = payload.getEmail();
  boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
  String name = (String) payload.get("name");
  String pictureUrl = (String) payload.get("picture");
  String locale = (String) payload.get("locale");
  String familyName = (String) payload.get("family_name");
  String givenName = (String) payload.get("given_name");
} catch (GeneralSecurityException | IOException e) {
  // error handling
}

不需要Google+ API!