为什么requestIdToken返回null?

27

我按照这个链接中的步骤进行了操作:

  1. 我将 google-services.json 下载到我的应用程序文件夹中。
  2. 我的项目级别 gradle 文件:

    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
        classpath 'com.google.gms:google-services:1.5.0-beta2'
    }
    
  3. 我的应用级别的gradle文件:

  4. apply plugin: 'com.android.application'
    apply plugin: 'com.google.gms.google-services'
    
    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        compile 'com.google.android.gms:play-services-identity:8.3.0'
        compile 'com.google.android.gms:play-services:8.3.0'
        compile 'com.google.android.gms:play-services-plus:8.3.0'
        compile 'com.google.android.gms:play-services-auth:8.3.0'
        ...
    }
    
  5. 我为我的后端服务器创建了OAuth 2.0客户端ID,并将此客户端ID传递到strings.xml文件中。

  6. 最后,我按照以下方式创建了GoogleSignInOptions和GoogleApiClient对象:

  7. GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestIdToken(getString(R.string.server_client_id))
            .build();
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();
    

    但问题是在handleSignInResult函数中,result.isSuccess()总是返回false。 我想也许我在第一步或第二步中做错了些什么。而且我的代码几乎与这个示例SignInActivity.java相似。非常感谢您的帮助。


你得到的 OAuth 2.0客户端ID,它的类型是 Web应用程序 还是 Android - BNK
1
我建议你阅读我的回答,网址为https://dev59.com/Fuk6XIcBkEYKwwoYEPzw#34146759,希望能对你有所帮助! - BNK
1
不要更新 google-services.json :) - BNK
1
我在创建凭据时将OAuth 2.0客户端ID Web应用程序名称更改为与我的Android客户端ID名称不同。现在它已经可以工作了,谢谢你。 - melomg
你能帮我解决下问题吗?我已经花费了几天时间去解决它... 我使用相同的代码,但是最终当我从google api检索tokenId时,我得到一个字符串tokenId = <857个字符> ... ?? 如果我尝试验证它https://www.googleapis.com/oauth2/v3/tokeninfo?access_token= <857个字符的响应>我得到的都是'error_description": "Invalid Value' ... 你是如何验证你的响应的?你也会得到一个字符串tokenId = <857个字符>? - Sirop4ik
显示剩余6条评论
4个回答

50

如我在以下问题中所回答的:

Google登录requestIdToken返回null

为了成功请求Id Token,您应该使用“Web应用程序”类型的客户端ID,而不是“Android”类型的客户端ID。

您还可以在Google文档中找到以下信息(请注意#3):

为后端服务器创建OAuth 2.0客户端ID

如果您的应用程序与后端服务器进行身份验证或从后端服务器访问Google API,则必须为您的服务器创建OAuth 2.0客户端ID。要创建OAuth 2.0客户端ID:

  1. 打开凭据页面。
  2. 单击添加凭据> OAuth 2.0客户端ID。
  3. 选择Web应用程序
  4. 单击创建。

在创建GoogleSignInOptions对象时将此客户端ID传递给requestIdTokenrequestServerAuthCode方法。


更新于3月26日:

Android开发者博客-注册Google登录的OAuth客户端


1
@neobie 这是用于后端身份验证的令牌,请参阅 http://android-developers.blogspot.com/2016/03/registering-oauth-clients-for-google.html,但我从未尝试过使用 GoogleIdTokenVerifier,您可以在 http://android-developers.blogspot.com/2016/01/using-google-sign-in-with-your-server.html 找到更多信息。关于访问 Google API 的访问令牌,同样在该链接中,您将找到另一个链接 http://android-developers.blogspot.com/2016/02/using-credentials-between-your-server.html。 - BNK
1
@neobie 另一个好的链接是 https://developers.google.com/identity/sign-in/android/migration-guide#migrate_to_the_id_token_flow,请注意 如果您只需要用户的ID、电子邮件地址、姓名或个人资料图片URL,请使用ID令牌流程。如果您的服务器需要访问其他Google API,如Google Drive、Youtube或Contacts,请使用服务器授权代码流程。,在那里您将找到2个其他链接和一些示例代码。 - BNK
我能否将授权码用于通用目的?我已经弄清如何在后端PHP中使用授权码,但尚未了解ID令牌的使用方法。如果有示例代码,那就更好了。 - neobie
1
你救了我的命。谢谢 @BNK - user3734429
1
没事了,我查看了文档并意识到了我的错误。无论如何还是谢谢你。 - Ari
显示剩余8条评论

21

在我的情况下,之前我已经......

 GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

我通过添加requestToken方法来解决了这个问题,

 GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestIdToken(getString(R.string.default_web_client_id))
            .build();

现在它对我有效。希望这可以帮助像我一样遇到问题的人。


我曾经遇到过同样的问题,这个方法解决了它。这个修复方法在发布版apk上也能正常工作吗? - wick.ed
1
是的,它可以工作。但是在发布时不要忘记放置您的发布SHA1密钥。 - yubaraj poudel
在Google API控制台中对吧?我会在API控制台中更新。那么我是否还需要将发布SHA码放到代码中呢? - wick.ed
1
是的,如果您正在使用Firebase,则在创建项目时或仅添加发布SHA1密钥时。@wick.ed - yubaraj poudel
我现在面临的同样问题,已经两天了。我将我的应用程序发布到Google Play商店,但现在我想删除注册并简单地添加Google登录,但它给了我一个错误。在实施调试或发布时应该使用哪个sha1密钥?我将在哪里指定此密钥?我正在Firebase中使用发布sha1密钥。 - M Umer

2
我们可以使用 requestServerAuthCode 方法,结合 "WebApplication ClientID" 来创建一个获取访问令牌的方法,如下所示;
 new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)

                    .requestServerAuthCode("WEBAPPLICATION CLIENT ID")

                    .requestEmail()

                    .build())

我们需要一个WEB应用程序客户端ID,可以从https://console.developers.google.com获取;
如下所示获取Web应用程序客户端ID:obtain web application client id as follows
void fetchGoogleAuthToken(){

    OkHttpClient okHttpclient = new OkHttpClient();
    RequestBody requestBody = new FormEncodingBuilder()
            .add("grant_type", "authorization_code")
            .add("client_id", "812741506391-
              h38jh0j4fv0ce1krdkiq0hfvt6n5amrf.apps.googleusercontent.com")
            .add("client_secret", "{clientSecret}")
            .add("redirect_uri","")
            .add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8")
            .build();

    final Request request = new Request.Builder()
            .url("https://www.googleapis.com/oauth2/v4/token")
            .post(requestBody)
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(final Request request, final IOException e) {
            Log.e(LOG_TAG, e.toString());                
        }

        @Override
        public void onResponse(Response response) throws IOException {
            try {
                JSONObject jsonObject = new 
                             JSONObject(response.body().string());
                final String message = jsonObject.toString(5);
                Log.i(LOG_TAG, message);                    
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });
}

请使用compile 'com.squareup.okhttp:okhttp:2.6.0'(版本3-RC1将有不同的类),或者您可以使用任何网络框架来进行上述调用。
成功响应后,您将在log-cat中获得以下信息:
I/onResponse: {
          "expires_in": 3600,

          "token_type": "Bearer",

          "refresh_token": "1\/xz1eb0XU3....nxoALEVQ",

          "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjQxMWY1Ym......yWVsUA",

     **"access_token": "ya29.bQKKYah-........_tkt980_qAGIo9yeWEG4"**
     }

可以看到,访问令牌(acces_token)可以进一步使用。


使用GoogleSignInAccount.getServerAuthCode()获取授权码并将其传递给上述调用中的.add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8")。 - coder-at-risk
你是一个救命恩人。 - Subhrajyoti Sen

0
我曾经遇到过同样的问题。我所做的就是重新下载 google-services.json 文件,替换旧文件,然后问题就解决了。 不知道为什么会出现这种情况,我猜测可能是有些东西发生了变化,在覆盖之前我忘记进行比较了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接