在 OAuth 2.0 令牌更新后重定向用户的最佳做法是什么?

What are the best practices when redirecting users after OAuth 2.0 token renew?

我在一个网站上实现了 Mautic API。我使用 OAuth 2.0 来验证两者之间的通信。我遇到的问题是我必须不时更新令牌,为此我必须提供回调 URL,我想我只需要使用 http://$_SERVER[ HTTP_HOST]$_SERVER[REQUEST_URI] 作为我的回调 URL,这样,当身份验证或更新完成后,用户将被重定向到最后调用的 URL。问题是有时用户会被重定向到 API 的登录页面以授权集成。据我所知,我应该只做一次。

简而言之,如何避免向我的用户显示 API 身份验证屏幕?

我还没有完成集成;我仍然必须处理一些安全问题。 负责这样做的 class 就在下面:

<?php

use Mautic\Auth\ApiAuth;
use Mautic\MauticApi;

class Mautic
{

   private static $instance;
   private $publicKey;
   private $secretKey;
   private $callback;
   private $baseURL;
   private $Api;
   private $ApiURL;
   private $auth;
   private $token;
   private $companyName;

   public function __construct()
   {
      $config = $this->getConfig();

      $this->publicKey   = $config['publicKey'];
      $this->secretKey   = $config['secretKey'];
      $this->baseURL     = $config['baseURL'];
      $this->companyName = $config['companyName'];

      $this->Api    = new MauticApi();
      $this->ApiURL = $this->baseURL . '/api/';

      if (!$this->isTokenValid()) {
         $this->getToken();
      }
   }

   /**
    * Read the config file "mautic.json" located in the root directory and returns an array with config values
    *
    * @return array
    */
   private function getConfig(): array
   {
      return $this->getJSON('mautic.json');
   }

   /**
    * Instantiates a new API class
    *
    * @param string $apiName
    * @return object
    */
   private function setApi(string $apiName): object
   {
      if(!$this->auth){
         $this->getToken();
      }
      return $this->Api->newApi($apiName, $this->auth, $this->ApiURL);
   }

   /**
    * Retorna la instancia de la clase actual
    *
    * @return object
    */
   public static function getInstance(): object
   {
      if (!self::$instance)
         self::$instance = new self();

      return self::$instance;
   }

   public function isTokenValid(): bool
   {
      $oldTokenExpiration = $this->checkForToken()['expires'];
      if (time() >= $oldTokenExpiration) {
         return false;
      }
      return true;
   }

   private function getToken($accessToken = null, $tokenExpiration = null, $refreshToken = null)
   {

      if ($previousToken = $this->checkForToken()) {
         $settings['accessToken']        = $previousToken['access_token'];
         $settings['accessTokenExpires'] = $previousToken['expires'];
         $settings['refreshToken']       = $previousToken['refresh_token'];
      }

      $settings  = [
         'baseUrl'      => $this->baseURL,     // Base URL of the Mautic instance
         'version'      => 'OAuth2',           // Version of the OAuth
         'clientKey'    => $this->publicKey,   // Client/Consumer key from Mautic
         'clientSecret' => $this->secretKey,   // Client/Consumer secret key from Mautic
         'callback'     => "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"
      ];

      if (isset($accessToken) && isset($tokenExpiration) && isset($refreshToken)) {
      }

      $initAuth = new ApiAuth();
      $auth     = $initAuth->newAuth($settings);

      // Initiate process for obtaining an access token; this will redirect the user to the authorize endpoint and/or set the tokens when the user is redirected back after granting authorization

      if ($auth->validateAccessToken()) {
         if ($auth->accessTokenUpdated()) {
            $accessTokenData = $auth->getAccessTokenData();
            $this->storeToken($accessTokenData);
            $this->auth = $auth;
            $this->token = $accessTokenData['access_token'];
            return $this->auth;
         }
      }
   }

   private function storeToken($accessTokenData)
   {
      $tokenInfo = json_encode($accessTokenData);
      file_put_contents("token.json", $tokenInfo);
   }

   /**
    * Read the file "token.json" located in the root directory and returns an array with any passed token values
    *
    * @return array
    */
   private function checkForToken(): array
   {
      return $this->getJSON('token.json');
   }

   /**
    * Reads a JSON file and returns its key and values as an array
    *
    * @param string $filePath
    * @return array
    */
   private function getJSON($filePath): array
   {
      if (!file_exists($filePath)) {
         return false;
      }
      $oldToken = file_get_contents($filePath);
      $oldToken = json_decode($oldToken);
      return (array) $oldToken;
   }

   /**
    * Creates a new contact
    *
    * @param string $name
    * @param string $phone
    * @param string $email
    * @param string $companyName
    * @return array
    */
   public function createContact(string $name, string $phone, string $email, int $companyName = null): array
   {

      if ($companyName == null) {
         $companyName = $this->getConfig()['companyName'];
      }

      $data = array(
         'firstname'          => $name,
         'phone'              => $phone,
         'email'              => $email,
         'company'            => $companyName,
         'ipAddress'          => $_SERVER['REMOTE_ADDR'],
         'overwriteWithBlank' => true,
      );
      $contactApi = $this->setApi('contacts');
      $newContact = $contactApi->create($data);
      return $newContact;
   }

   /**
    * Retorna los datos de un contacto
    *
    * @param int $contactId
    * @return object
    */
   public function getContact(int $contactId): object
   {
      return json_decode($this->curlGET("contacts", array($contactId)));
   }

   /**
    * Ejecuta una requisición GET al servidor de la API
    *
    * @param string $APIMethod
    * @param array $dataToSend
    * @return string
    */
   private function curlGET(string $APIMethod, array  $dataToSend = array()): string
   {

      $dataToSend["access_token"] = $this->token;
      $baseURL                    = $this->ApiURL . $APIMethod;
      $curl                       = curl_init();
      $curlOptions                = array(
         CURLOPT_URL              => $baseURL . '?' . http_build_query($dataToSend),
         CURLOPT_RETURNTRANSFER   => true,
         CURLOPT_SSL_VERIFYHOST   => false,
         CURLOPT_SSL_VERIFYPEER   => false
      );

      curl_setopt_array($curl, $curlOptions);

      $returnedData = curl_exec($curl);

      if (!$returnedData) {
         return curl_error($curl);
      } else {
         curl_close($curl);
         return $returnedData;
      }
   }
}

好像是重新认证的问题。成功验证后,您就不需要一次又一次地执行此操作。

流程完成后,您将获得令牌、令牌过期和刷新令牌。这是完整的示例(https://tutorialsjoint.com/mautic-rest-api/).

获得令牌并检查令牌是否过期后,您应该使用刷新令牌来获取新的访问令牌。出于某种原因,如果您的刷新令牌无效,那么您只需要重新进行身份验证,这通常发生在您更改客户端凭据时。

在你的代码中我看到你正在进行身份验证但是看不到刷新令牌调用,这应该是你的问题。