【问题标题】:How to renew access token with OAuth Refresh token?如何使用 OAuth 刷新令牌更新访问令牌?
【发布时间】:2016-08-13 04:03:31
【问题描述】:

我正在为 Uber 创建简单的应用程序。
我已经通过这个 API 解决了 3 个步骤:https://developer.uber.com/docs/authentication
但现在我想刷新令牌(第 5 步)。
我收到 access_token、refresh_token、expires_in 值,但我不明白如何设置计时器以在 expires_in 时间到期时用 refresh_token 刷新用户的令牌。
这里我提供了我的代码示例,我想用 refresh_token 更新访问令牌。

<?php
session_start();

require_once 'uber_b.php';
require_once 'config.php';


if(isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://login.uber.com/oauth/token';

/* 
* Create row for function setPostData (uber_b.php)
* All of this rows will be used to build our request
*/
$params = array(
    "code" => $code,
    "client_id" => $client_id,
    "client_secret" => $client_secret,
    "redirect_uri" => $redirect,
    "grant_type" => "authorization_code"
);
//create example of class
$request = new HttpPost($url);
//Connect this class with our settings
$request->setPostData($params);
//Send our request to Uber
$request->send(); 
//Receive response
$responseObj = json_decode($request->getHttpResponse());
//Execute parameters from answer
$user_token = $responseObj->access_token;
//Refresh token 
$refresh_token = $responseObj->refresh_token;
//Time for token
$expires_in = $responseObj->expires_in;

echo "User's token: " . $user_token;
echo "<br>";
echo "Refresh token is: " .$refresh_token ;
echo "<br>";
echo "Time: ".$expires_in;
echo "<br>";
echo "<a href='order.php'>Order a car</a>";
}

//Refresh token
if(isset($responseObj))
{
        $exp_time = time()+2592000;
        try {
            //insert into database
            $stmt = $db->prepare('INSERT INTO token2 (exp_time)
                                      VALUES (:exp_time)
                                    ');
            $stmt->execute(array(
                ':exp_time' => $exp_time
            ));             
        } catch(PDOException $e) {
            echo $e->getMessage();
        }
}
if(time() >= $exp_time)
{
//Parameters for Uber refresh token request(step 5)
$r_params = array(
    "client_id" => $client_id,
    "client_secret" => $client_secret,
    "redirect_uri" => $redirect,
    "grant_type" => "refresh_token",
    "refresh_token" => $refresh_token
    );
 $r_request = new RefreshToken($url);

 $r_request->setPostData($r_params);
 $r_request->send(); 
 $refresh = $refresh_token;
 $r_responseObj = json_decode($r_request->Refresh());

echo "New Refresh token: " . $r_responseObj->refresh_token;
echo "<br>";
}
?>

如您所见,我不提供计时器功能,因为我不明白如何使它正确。
那么,您能解释一下如何使用 refresh_token 正确更新 access_token 吗?
也许我必须使用 setcookie() 或其他方法来解决这个任务?

【问题讨论】:

    标签: php oauth uber-api


    【解决方案1】:
    • 首先,根据STEP FIVE: REFRESHING TOKENS中的Authentication docs,刷新访问令牌需要HTTP POST以下参数:

      client_secret=YOUR_CLIENT_SECRET
      client_id=YOUR_CLIENT_ID
      grant_type=refresh_token
      redirect_uri=YOUR_REDIRECT_URI
      refresh_token=REFRESH_TOKEN

      https://login.uber.com/oauth/v2/token API 端点

      您还发送了 code 参数,这意味着您将收到一个错误,因为此附加参数无法在 Uber 的服务器上验证。 你得到的错误将是

      HTTP/1.1 401 UNAUTHORIZED
      {"error": "invalid_grant"}  
      
    • 为了能够检查令牌的有效性,在您与访问令牌交换代码后,您需要:

      • 在某处保留“access_token”、“expires_in”、“refresh_token”和一个以秒为单位的 UNIX 时间戳,表示当前时间和日期,我们称之为“itime”。

      • 您可以存储此信息的位置多种多样:会话、文件、数据库、内存缓存等,具体取决于您希望如何处理令牌过期和自动用户登录(如果您已经保存了他们的令牌)并且没有过期,就不用让用户重新登录了。

      • 在您向 Uber API 发出每个 HTTP 请求之前,您首先通过从用户访问令牌的存储位置检索“itime”和“expires_in”来检查访问令牌是否未过期,然后确保 time() 如果条件为假,则需要刷新访问令牌。

      • 请记住,刷新访问令牌也会更改刷新令牌,因此您需要为 uuid 标识的当前用户替换当前的“access_token”、“refresh_token”和“expires_in”。

      • 鉴于访问令牌的当前到期时间是 30 天(2592000 秒),我建议您将访问令牌数据存储在数据库表中,因为 PHP 会话是短暂的(默认 session.gc_maxlifetime 为 1440 php.ini 中的秒/24 分钟),用户也不会一直停留在您的应用/网站上。
      • 此外,如果您允许用户从多个设备/地点登录优步,检查过期时间是不够的,因为在每个用户登录后,所有先前的访问/刷新令牌都将失效。因此,在用户在第二台设备上登录后,您可能在第一台设备上拥有无效的访问权限/令牌和有效的过期时间。 在这种情况下,要确定访问令牌是否仍然有效,我建议您使用访问令牌向 GET /v1/me 端点发出额外的 HTTP 请求。如果有效,则令牌仍然有效,否则令牌已过期/失效,您需要在第一台设备上请求用户重新登录。

    tl;dr 您不需要计时器,您需要在每次向 Uber API 发出 HTTP 请求之前检查访问令牌是否仍然有效。
    为此,您需要保留令牌详细信息 + UNIX 时间戳。

    【讨论】:

    • 感谢您的回答。我有一个小问题,如何在 MySQL 中实现“itime”,我的意思是,我必须创建什么行以及在 php 文件中写入什么命令?我这样做, if(isset($responseObj)) { $exp_time = time()+2592000; try { //插入数据库 $stmt = $db->prepare('INSERT INTO token2 (exp_time) VALUES (:exp_time) '); $stmt->execute(array( ':exp_time' => $exp_time )); } catch(PDOException $e) { echo $e->getMessage(); } } 但它没有在我的 SQL 表中设置。
    • itime 是您从 API 获得访问令牌的时间,您已经在此处使用 time() 调用添加了它:$exp_time = time()+2592000,但您应该获得秒数 (2592000)来自响应对象,因为该值将来可能会更改。在每个请求之前,您需要检查 time()
    • 不好意思问了这么傻的问题,但是如果我把access_token和refresh_token存到表里,以后怎么用呢?或者,如果我有特殊的刷新功能,我为什么需要这个?
    • 我已根据您的建议更改了代码,请检查一下 :) 非常感谢您的帮助。你是最棒的:)
    • 因为如果您将 access_token 和 refresh_token 存储在数据库中,您就不必让用户在每次使用您的应用/网站时重新登录优步(您可以防止糟糕的用户体验)。您只需从数据库中获取 Uber 详细信息,检查令牌是否有效,如果不是,则刷新它,然后您可以安全地代表用户发出 Uber API 请求。此外,如果您不将令牌详细信息存储在数据库中,如果用户离开您的应用程序/网站,您将不再知道该用户是否曾经登录过,因此您必须让他再次登录,您不能刷新。
    猜你喜欢
    • 2012-07-11
    • 2014-09-13
    • 2015-04-01
    • 2020-07-12
    • 2013-09-05
    • 2015-11-26
    • 2017-06-09
    • 2021-09-13
    • 1970-01-01
    相关资源
    最近更新 更多