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

问题描述

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

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

我还没完成整合;我仍然必须解决一些安全问题。 负责这样做的类就在下面:

<?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/)。

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

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