Google+登录在跨客户端(Android版/网络)认证 [英] Google+ Sign In cross client(android/web) authentication

查看:256
本文介绍了Google+登录在跨客户端(Android版/网络)认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要的应用程序,有一个机器人和网络组件整合与谷歌登录。在Web组件一切工作正常使用以下步骤:
1.渲染带有防伪标记,客户端ID和应用程序名称的看法。

i'm trying to integrate 'Log in with Google' in app that have an android and web component. Everything in the web component is working fine with the following steps: 1. Rendering the view with an anti-forgery token, client id and app name.

$state = md5(rand());
Session::set('state', $state);
$this->view->render('login', array(
    'CLIENT_ID' => 'my_web_client_id',
    'STATE' => $state,
    'APPLICATION_NAME' => 'my_app_name'));

2。当用户点击谷歌的登入按钮,获得谷歌的服务器一次性code,并将其发送到我的服务器。
3.我的服务器收到后使用 HTTPS一次性code:// github上。 COM /谷歌/谷歌API的PHP客户端来与code中的用户进行身份验证。

2. When user clicks on the Google's SignIn button, obtain the one-time code from Google's servers and send it to my server. 3. After my server receives the one-time code using https://github.com/google/google-api-php-client to authenticate the user with that code.

if ($_SESSION['state'] != $_POST['state']) { // Where state is the anti-forgery token
  return 'some error';
}

$code = $_POST['code'];
$client = new Google_Client();
$client->setApplicationName("my_app_name");
$client->setClientId('my_web_client_id');
$client->setClientSecret('client_secret');
$client->setRedirectUri('postmessage');
$client->addScope("https://www.googleapis.com/auth/urlshortener");
$client->authenticate($code);

$token = json_decode($client->getAccessToken());
// Verify the token
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' . $token->access_token;
$req = new Google_Http_Request($reqUrl);          
$tokenInfo = json_decode($client->getAuth()->authenticatedRequest($req)->getResponseBody());

// If there was an error in the token info, abort.
if ($tokenInfo->error) {
  return 'some error';
}

// Make sure the token we got is for our app.
if ($tokenInfo->audience != "my_web_client_id") {
  return 'some error';
}

// Saving user in db
...
// Load the app view

现在,对于Android客户端应该是类似的东西,对不对?以下这些教程: https://developers.google.com/+/mobile/android /登入 HTTP ://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/

Now, for android client should be something similar, right? Following these tutorials:https://developers.google.com/+/mobile/android/sign-in and http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/

执行异步任务 onConnected

class CreateToken extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... voids) {
        oneTimeCode = getOneTimeCode();
        String email = getUserGPlusEmail();
        try {
            // Opens connection and sends the one-time code and email to the server with 'POST' request
            googleLogin(oneTimeCode, email);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return oneTimeCode;
    }
}

private String getOneTimeCode() {

    String scopes = "oauth2:server:client_id:" + SERVER_CLIENT_ID + ":api_scope:" + SCOPE_EMAIL;
    String code = null;
    try {
        code = GoogleAuthUtil.getToken(
                LoginActivity.this,                                // Context context
                Plus.AccountApi.getAccountName(mGoogleApiClient),  // String accountName
                scopes                                             // String scope
        );

    } catch (IOException transientEx) {
        Log.e(Constants.TAG, "IOException");
        transientEx.printStackTrace();
        // network or server error, the call is expected to succeed if you try again later.
        // Don't attempt to call again immediately - the request is likely to
        // fail, you'll hit quotas or back-off.
    } catch (UserRecoverableAuthException e) {
        Log.e(Constants.TAG, "UserRecoverableAuthException");
        e.printStackTrace();
        // Requesting an authorization code will always throw
        // UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
        // because the user must consent to offline access to their data.  After
        // consent is granted control is returned to your activity in onActivityResult
        // and the second call to GoogleAuthUtil.getToken will succeed.
        startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE);
    } catch (GoogleAuthException authEx) {
        // Failure. The call is not expected to ever succeed so it should not be
        // retried.
        Log.e(Constants.TAG, "GoogleAuthException");
        authEx.printStackTrace();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

    Log.e(Constants.TAG, "ONE TIME CODE: " + code);
    return code;
}

获得code成功,将它发送到我的服务器进行身份验证后。
而这里的服务器上的code:

After obtaining the code successfully, send it to my server for authentication. And here's the code on the server:

$code = $_POST['code'];
$client = new Google_Client();
$client->setApplicationName("my_app_name");
$client->setClientId('my_web_client_id');  // Web component's client id
$client->setClientSecret('client_secret'); // Web component's secret
$client->addScope("email");
$client->setAccessType("offline");
$client->authenticate($code);
...

和问题是,认证只能每隔10-15分钟。当试图获得一次性code不止一次在10-15分钟,我得到同样的code作为最后一个(显然有些不妥。这仅发生在Android客户端和我' m到处这个错误:错误获取的OAuth2访问令牌,留言:invalid_grant:我)。找不到这里的SO同样的问题的人。大概是我做错了什么,但无法弄清楚什么是它...任何帮助将是AP preciated。

And the problem is that authentication works only once every 10-15 minutes. When trying to obtain the one-time code more than once in 10-15 minutes, i get the same code as the last one(Clearly there is something wrong. This happens only with the android client and i'm getting this error: Error fetching OAuth2 access token, message: 'invalid_grant: i'). Couldn't find anyone with the same problem here in SO. Probably i'm doing something wrong, but can't figure out what is it...Any help would be appreciated.

推荐答案

您不应该每次发送code。在网络上,这是一种不错的方法,当你第一次同意,你会得到一个code,让你离线访问(你会看到一个刷新令牌的响应,当你交流一下),但在今后的案件,你不会。在Android上,你会得到一个code,让你每次刷新令牌,这意味着你将需要每次都展现同意,你就可能碰到的每用户限制或高速缓存的问题(如你似乎是)。

You shouldn't be sending the code each time. On the web this is kind of OK as when you first consent you'll get a code that gives you offline access (you'll see a refresh token in the response when you exchange it) but in future cases you wont. On Android, you get a code that gives you a refresh token every time, which means you'll need to show the consent every time, and you're likely to run into per-user limits or cache issues (as you seem to be).

您所需要的额外的魔法成分是一种称为一个ID令牌的事情。这可以在两个平台上轻松获得,并告诉你的人是谁。看看这个博客帖子更多:的http://www.riskcompletefailure.com/2013/11/client-server-authentication-with-id.html

The magic extra component you need is a thing called an ID token. This you can get easily on both platforms and tells you who the person is. Take a look at this blog post for more: http://www.riskcompletefailure.com/2013/11/client-server-authentication-with-id.html

一个ID令牌的限制是,你不能用它调用谷歌的API。它所做的就是给你的谷歌用户ID,正在使用的应用程序的客户端ID和(如果使用电子邮件的范围)的电子邮件地址。这种做法的好处是,你可以得到一个真正轻松的以较少的用户交互的所有平台,他们正在加密签名所以大部分的时间,你可以不使服务器上的任何进一步的网络调用中使用它们。如果你不需要让谷歌API调用(因为你只是用它来验证),这是迄今为止用的最好的事情 - 因为你刚刚的电子邮件,我会倾向于到此为止。

The limitation with an ID token is that you can't use it to call Google APIs. All it does is give you the Google user ID, the client ID of the app being used and (if email scope is used) the email address. The nice thing is that you can get one really easily on all platforms with less user interaction, and they're cryptographically signed so most of the time you can use them without making any further network calls on the server. If you don't need to make Google API calls (because you're just using it for auth) this is the best thing to use by far - given that you're just getting the email, I would be inclined to stop here.

如果你需要从你的服务器谷歌的API调用,虽然,那么你应该使用code - 但只有一次。当你交换吧,你保存在键入对用户ID数据库中刷新令牌。然后,当用户回来你查找刷新令牌,并用它来生成新的访问令牌。这样的流动将是:

If you need to make Google API calls from your server though, then you should use the code - but just once. When you exchange it, you store the refresh token in a database keyed against the user ID. Then, when the user comes back you look up the refresh token and use it to generate a new access token. So the flow would be:

第一次:


  1. Android的 - >服务器:ID令牌

  2. 服务器 - >我没有刷新令牌

  3. Android的 - >服务器:code

其他时间:


  1. Android的 - >服务器:ID令牌

  2. 服务器 - 我有一个code,并能拨打电话。

有关网页,你可以使用相同的流或进行发送$ C $每次C,但你还是应该保持刷新令牌在数据库中,如果响应包含之一。

For the web, you can use the same flow or carry on sending the code each time, but you should still keep the refresh token in the database if the response contains one.

这篇关于Google+登录在跨客户端(Android版/网络)认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆