从现有的用户身份验证代码中获取Google Refresh令牌

时间:2019-07-08 11:12:10

标签: android node.js google-cloud-functions google-oauth

我正在尝试获取Google Refresh令牌,问题是我在任何地方都没有看到我的当前情况,我要完成的工作是从google已经生成的用户身份验证令牌中获取刷新令牌。从本机android应用程序登录,基本上,我要求我在该应用程序上需要的所有google权限,并从登录中获取auth代码,然后将该身份验证代码发送至Firebase函数后端,在那里我尝试获取刷新令牌,但我总是从Google处获得invalid_grant,所以我不知道该在哪里搞砸

我看到离线请求oauth可能会解决问题,但是我正在android应用中登录,因此我无法从后端离线请求登录,我需要登录和身份验证仅在android应用程序,我需要它通过后端发出Google助手请求,为此,唯一缺少的是刷新令牌

我从Google云控制台获取了我的google oauth2密钥,并且客户端已初始化

var OAuth2 = google.auth.OAuth2;

var _client_id = require('./config/secrets/omni.json').installed.client_id; 
var _client_secret = require('./config/secrets/omni.json').installed.client_secret;
var redirect = require('./config/secrets/omni.json').installed.redirect_uris[1];

return new OAuth2(
        _client_id,
        _client_secret,
        redirect
        );

最后尝试获取令牌:

function getRefreshToken(authCode, idFBUser) {
    return new Promise((resolve, reject) => {
        getOAuthClient().getToken(authCode, function(err, token) {
            if (!err) {
                console.log(`Get Token success, token: ${token}`);
                getOAuthClient().setCredentials(token);
                saveRefreshFirebase(idFBUser, token)
                resolve(token);
            } else {
                console.log("Get Token error", err);
                reject(err);
            }
        });
    });
}

我得到的错误恰恰是这个错误:{error:'invalid_grant',error_description:'Bad Request'}

我在android应用中用来请求身份验证代码的方法是这样的:

创建GoogleSignIn实例

val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .requestId()
            .requestIdToken(getClientId())
            .requestServerAuthCode(getClientId())
            .requestScopes(ASSISTANT_SCOPE)
            .build()

googleSignInClient = GoogleSignIn.getClient(this, gso)

调用登录意图:

val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, RESULT_GOOGLE_SIGNIN)

处理登录结果:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK) {
            when (requestCode) {
                RESULT_GOOGLE_SIGNIN -> {
                    val task = GoogleSignIn.getSignedInAccountFromIntent(data)
                    try {
                        task.result?.let {  account ->
                            val id = account.id
                            val idToken = account.idToken
                            val authCode = account.serverAuthCode
                            Log.d("GoogleSignIn", "ID: $id")
                            Log.d("GoogleSignIn", "ID Token: $idToken")
                            Log.d("GoogleSignIn", "Auth code: $authCode")
                            btnLogin.text = "Sign Out"
                            loggedIn = true
                        } ?: Log.e("GoogleSignIn", "Exception: ${task.exception}")
                    } catch (e: Exception) {
                        Log.e("GoogleSignIn", "Catch Exception: $e")
                    }
                }
            }
        }
    }

而authCode是我用来尝试在后端获取Refresh Token的代码。

1 个答案:

答案 0 :(得分:0)

您需要致电

            .requestServerAuthCode(getClientId(),true)

代替

            .requestServerAuthCode(getClientId())

如果要获取刷新令牌。您发布的javascript代码可以使用刷新令牌。

这是认证应用程序的最简单方法,因为所有其他种类的令牌都将过期。刷新令牌不会过期。 Google登录库为您提供了用于获取刷新令牌的访问代码。您需要保存此刷新令牌并将其发送给Google,以获得访问令牌。然后,最终可以将访问令牌用于发出API请求。

顺便说一句,这实际上是“离线访问”所指的。还花了我一点时间来弄清楚这个问题。