OAuth2.php 5.44 KB
Newer Older
1 2 3 4 5 6 7
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

8
namespace yii\authclient;
9 10 11 12 13

use Yii;
use yii\base\Exception;

/**
14
 * OAuth2 serves as a client for the OAuth 2 flow.
15 16 17 18
 *
 * In oder to acquire access token perform following sequence:
 *
 * ~~~
19
 * use yii\authclient\OAuth2;
20
 *
21
 * $oauthClient = new OAuth2();
22 23 24 25 26 27 28 29 30 31 32 33
 * $url = $oauthClient->buildAuthUrl(); // Build authorization URL
 * Yii::$app->getResponse()->redirect($url); // Redirect to authorization URL.
 * // After user returns at our site:
 * $code = $_GET['code'];
 * $accessToken = $oauthClient->fetchAccessToken($code); // Get access token
 * ~~~
 *
 * @see http://oauth.net/2/
 *
 * @author Paul Klimov <klimov.paul@gmail.com>
 * @since 2.0
 */
34
class OAuth2 extends BaseOAuth
35
{
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    /**
     * @var string protocol version.
     */
    public $version = '2.0';
    /**
     * @var string OAuth client ID.
     */
    public $clientId;
    /**
     * @var string OAuth client secret.
     */
    public $clientSecret;
    /**
     * @var string token request URL endpoint.
     */
    public $tokenUrl;

53

54 55
    /**
     * Composes user authorization URL.
56
     * @param array $params additional auth GET params.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
     * @return string authorization URL.
     */
    public function buildAuthUrl(array $params = [])
    {
        $defaultParams = [
            'client_id' => $this->clientId,
            'response_type' => 'code',
            'redirect_uri' => $this->getReturnUrl(),
            'xoauth_displayname' => Yii::$app->name,
        ];
        if (!empty($this->scope)) {
            $defaultParams['scope'] = $this->scope;
        }

        return $this->composeUrl($this->authUrl, array_merge($defaultParams, $params));
    }

    /**
     * Fetches access token from authorization code.
76 77
     * @param string $authCode authorization code, usually comes at $_GET['code'].
     * @param array $params additional request params.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
     * @return OAuthToken access token.
     */
    public function fetchAccessToken($authCode, array $params = [])
    {
        $defaultParams = [
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret,
            'code' => $authCode,
            'grant_type' => 'authorization_code',
            'redirect_uri' => $this->getReturnUrl(),
        ];
        $response = $this->sendRequest('POST', $this->tokenUrl, array_merge($defaultParams, $params));
        $token = $this->createToken(['params' => $response]);
        $this->setAccessToken($token);

        return $token;
    }

    /**
     * Composes HTTP request CUrl options, which will be merged with the default ones.
98 99 100 101
     * @param string $method request type.
     * @param string $url request URL.
     * @param array $params request params.
     * @return array CUrl options.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
     * @throws Exception on failure.
     */
    protected function composeRequestCurlOptions($method, $url, array $params)
    {
        $curlOptions = [];
        switch ($method) {
            case 'GET': {
                $curlOptions[CURLOPT_URL] = $this->composeUrl($url, $params);
                break;
            }
            case 'POST': {
                $curlOptions[CURLOPT_POST] = true;
                $curlOptions[CURLOPT_HTTPHEADER] = ['Content-type: application/x-www-form-urlencoded'];
                $curlOptions[CURLOPT_POSTFIELDS] = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
                break;
            }
118
            case 'HEAD': {
119 120 121 122 123 124 125
                $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
                if (!empty($params)) {
                    $curlOptions[CURLOPT_URL] = $this->composeUrl($url, $params);
                }
                break;
            }
            default: {
126 127 128 129
                $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
                if (!empty($params)) {
                    $curlOptions[CURLOPT_POSTFIELDS] = $params;
                }
130 131 132 133 134 135 136
            }
        }

        return $curlOptions;
    }

    /**
137
     * @inheritdoc
138
     */
139
    protected function apiInternal($accessToken, $url, $method, array $params, array $headers)
140 141 142
    {
        $params['access_token'] = $accessToken->getToken();

143
        return $this->sendRequest($method, $url, $params, $headers);
144 145 146 147
    }

    /**
     * Gets new auth token to replace expired one.
148
     * @param OAuthToken $token expired auth token.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
     * @return OAuthToken new auth token.
     */
    public function refreshAccessToken(OAuthToken $token)
    {
        $params = [
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret,
            'grant_type' => 'refresh_token'
        ];
        $params = array_merge($token->getParams(), $params);
        $response = $this->sendRequest('POST', $this->tokenUrl, $params);

        return $response;
    }

    /**
165
     * Composes default [[returnUrl]] value.
166 167 168 169 170 171 172 173 174 175 176 177 178
     * @return string return URL.
     */
    protected function defaultReturnUrl()
    {
        $params = $_GET;
        unset($params['code']);
        $params[0] = Yii::$app->controller->getRoute();

        return Yii::$app->getUrlManager()->createAbsoluteUrl($params);
    }

    /**
     * Creates token from its configuration.
179
     * @param array $tokenConfig token configuration.
180 181 182 183 184 185 186 187
     * @return OAuthToken token instance.
     */
    protected function createToken(array $tokenConfig = [])
    {
        $tokenConfig['tokenParamKey'] = 'access_token';

        return parent::createToken($tokenConfig);
    }
AlexGx committed
188
}