【问题标题】:Google Apps Marketplace SSO: offline accessGoogle Apps Marketplace SSO:离线访问
【发布时间】:2014-06-22 23:39:00
【问题描述】:

我们的应用程序与邮件、通讯录、日历等 Google 服务广泛集成。对于所有这些 Google 服务,我们需要永久访问用户的数据,而无需在每次需要拉取应用程序时征求用户的许可来自谷歌的数据。当我们同步联系人、日历或通过 Google IMAP 访问邮件时,即时访问用户数据非常重要。 我们还通过单点登录 (SSO) 提供从任何 Google 服务访问我们应用程序的权限。在这里我们遇到了麻烦。 我们要求安装我们应用程序的用户“离线”访问他们的数据。因此,当我们运行同步脚本等时,我们可以立即访问他们的数据。 第一次用户授予对我们应用程序的访问权限(通过 SSO,当它单击我们的应用程序图标时),它被要求授予对我们需要的所有数据 API 的访问权限 - 联系人、电子邮件、日历等。一切正常,用户登录我们的应用程序.但是当用户下次访问我们的应用程序(通过 SSO 相同)时,它会被要求授予“具有离线访问权限”。这很奇怪,因为第一次用户不会被要求这样做。而且每次都向用户询问“离线访问”也不好看。为什么我们认为这种行为很奇怪,因为一旦用户已经授予访问权限。那么为什么会一次又一次地被问到呢?

我们用于 SSO 的代码如下:

$clientId     = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com";
$clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$callback     = "https://our_domain/callback";
$scopes       = array(
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/userinfo.profile",
    "https://www.googleapis.com/auth/drive.readonly.metadata",
    "https://www.googleapis.com/auth/calendar",
    "https://www.google.com/m8/feeds",
    "https://www.googleapis.com/auth/tasks",
    "https://www.googleapis.com/auth/admin.directory.user.readonly",
    "https://mail.google.com/"
);

// $params is a list of GET and POST parameters

if (empty($params['code']))
{
    $_SESSION['GOOGLE_SSO_STATE'] = md5(uniqid(rand(), true));

    $client = new Google_Client();

    $client->setClientId($clientId);
    $client->setRedirectUri($callback);
    $client->setAccessType('offline');
    $client->setApprovalPrompt('force');
    $client->setState($_SESSION['GOOGLE_SSO_STATE']);
    $client->setScopes($scopes);

    $url = $client->createAuthUrl();

    echo "<script> top.location.href='" . $url . "'</script>";
    exit;
}

if (!empty($params['code']) && !empty($params['state']) && $params['state'] == $_SESSION['GOOGLE_SSO_STATE'])
{
    unset($_SESSION['GOOGLE_SSO_STATE']);

    $client = new Google_Client();
    $client->setClientId($clientId);
    $client->setClientSecret($clientSecret);
    $client->setRedirectUri($callback);

    $credentials = $client->authenticate();

    // we need refresh token so we can exchange it for new access token when the current ones expires
    if (!isset($credentials_['refresh_token']))
    {
        echo "Wrong credentials received";
        exit;
    }

    $client = new Google_Client();
    $client->setUseObjects(true);
    $client->setAccessToken($credentials);

    $userInfoService = new Google_Oauth2Service($client);

    $userInfo = $userInfoService->userinfo->get();

    echo $userInfo->getId();
}

谁能帮助我们理解这种行为?或者也许有人甚至知道如何让它在每次访问应用程序时都不要求用户“离线访问”?

【问题讨论】:

    标签: php single-sign-on google-apps google-apps-marketplace


    【解决方案1】:

    这是因为您的批准提示设置为“强制:

     $client->setApprovalPrompt('force');
    

    仅当您需要重新发出刷新令牌时才使用强制。有一个奇怪的副作用,会一次又一次地要求用户离线访问。

    【讨论】:

    • 非常感谢! $client-&gt;setApprovalPrompt('auto'); 按预期工作,我只是还将检查 "refresh_token" 移动到代码的另一部分(对于已经在数据库中保存凭据的用户跳过它 - 这是我的大错误)。
    【解决方案2】:

    我们使用服务帐户,为已安装域中的任何用户(针对所选组织单位)提供离线访问权限。根据您要执行的操作,这可能是您的一个选择。

    https://developers.google.com/drive/web/service-accounts

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多