View source
<?php
namespace Auth0\SDK\API;
use Auth0\SDK\API\Helpers\ApiClient;
use Auth0\SDK\Exception\CoreException;
use Auth0\SDK\Exception\ApiException;
use Auth0\SDK\Store\EmptyStore;
use Auth0\SDK\Store\SessionStore;
use OAuth2\Client;
class Oauth2Client {
public $persistantMap = [
'refresh_token',
'access_token',
'user',
'id_token',
];
public static $URL_MAP = [
'api' => 'https://{domain}/api/',
'authorize' => 'https://{domain}/authorize/',
'token' => 'https://{domain}/oauth/token/',
'user_info' => 'https://{domain}/userinfo/',
];
protected $domain;
protected $client_id;
protected $client_secret;
protected $refresh_token;
protected $redirect_uri;
protected $debug_mode;
protected $debugger;
protected $access_token;
protected $id_token;
protected $user;
protected $store;
protected $oauth_client;
public function __construct(array $config) {
$this
->checkRequirements();
if (isset($config['domain'])) {
$this->domain = $config['domain'];
}
else {
throw new CoreException('Invalid domain');
}
if (isset($config['client_id'])) {
$this->client_id = $config['client_id'];
}
else {
throw new CoreException('Invalid client_id');
}
if (isset($config['client_secret'])) {
$this->client_secret = $config['client_secret'];
}
else {
throw new CoreException('Invalid client_secret');
}
if (isset($config['redirect_uri'])) {
$this->redirect_uri = $config['redirect_uri'];
}
else {
throw new CoreException('Invalid redirect_uri');
}
if (isset($config['debug'])) {
$this->debug_mode = $config['debug'];
}
else {
$this->debug_mode = false;
}
if (isset($config['persist_user']) && $config['persist_user'] === false) {
$this
->dontPersist('user');
}
if (!isset($config['persist_access_token']) || isset($config['persist_access_token']) && $config['persist_access_token'] === false) {
$this
->dontPersist('access_token');
}
if (!isset($config['persist_refresh_token']) || isset($config['persist_refresh_token']) && $config['persist_refresh_token'] === false) {
$this
->dontPersist('refresh_token');
}
if (!isset($config['persist_id_token']) || isset($config['persist_id_token']) && $config['persist_id_token'] === false) {
$this
->dontPersist('id_token');
}
if (isset($config['store'])) {
if ($config['store'] === false) {
$this->store = new EmptyStore();
}
else {
$this->store = $config['store'];
}
}
else {
$this->store = new SessionStore();
}
$this->oauth_client = new Client($this->client_id, $this->client_secret);
$this->user = $this->store
->get('user');
$this->access_token = $this->store
->get('access_token');
$this->id_token = $this->store
->get('id_token');
$this->refresh_token = $this->store
->get('refresh_token');
if (!$this->access_token) {
$this->oauth_client
->setAccessToken($this->access_token);
}
}
private function dontPersist($name) {
$key = array_search($name, $this->persistantMap);
if ($key !== false) {
unset($this->persistantMap[$key]);
}
}
public function exchangeCode() {
$code = isset($_GET['code']) ? $_GET['code'] : (isset($_POST['code']) ? $_POST['code'] : null);
if (!isset($code)) {
$this
->debugInfo('No code found in _GET or _POST params.');
return false;
}
$this
->debugInfo('Code: ' . $code);
$auth_url = $this
->generateUrl('token');
$response = $this->oauth_client
->getAccessToken($auth_url, 'authorization_code', [
'code' => $code,
'redirect_uri' => $this->redirect_uri,
], [
'Auth0-Client' => ApiClient::getInfoHeadersData()
->build(),
]);
$auth0_response = $response['result'];
if ($response['code'] !== 200) {
if (isset($auth0_response['error'])) {
throw new ApiException($auth0_response['error'] . ': ' . $auth0_response['error_description']);
}
else {
throw new ApiException($auth0_response);
}
}
$this
->debugInfo(json_encode($auth0_response));
$access_token = isset($auth0_response['access_token']) ? $auth0_response['access_token'] : false;
$refresh_token = isset($auth0_response['refresh_token']) ? $auth0_response['refresh_token'] : false;
$id_token = isset($auth0_response['id_token']) ? $auth0_response['id_token'] : false;
if (!$access_token) {
throw new ApiException('Invalid access_token - Retry login.');
}
if (!$id_token) {
$this
->debugInfo('Missing id_token after code exchange. Remember to ask for openid scope.');
}
$this->oauth_client
->setAccessToken($access_token);
$this->oauth_client
->setAccessTokenType(Client::ACCESS_TOKEN_BEARER);
$this
->setAccessToken($access_token);
$this
->setIdToken($id_token);
$this
->setRefreshToken($refresh_token);
$userinfo_url = $this
->generateUrl('user_info');
$user = $this->oauth_client
->fetch($userinfo_url);
$this
->setUser($user['result']);
return true;
}
public function getUser() {
if ($this->user === null) {
$this
->exchangeCode();
}
if (!is_array($this->user)) {
return null;
}
return $this->user;
}
public function updateUserMetadata($metadata) {
$auth0Api = new Auth0Api($this
->getIdToken(), $this->domain);
$user = $auth0Api->users
->update($this->user['user_id'], [
'user_metadata' => $metadata,
]);
$this
->setUser($user);
}
public function getUserMetadata() {
return isset($this->user['user_metadata']) ? $this->user['user_metadata'] : [];
}
public function getAppMetadata() {
return isset($this->user['app_metadata']) ? $this->user['app_metadata'] : [];
}
public function setUser($user) {
$key = array_search('user', $this->persistantMap);
if ($key !== false) {
$this->store
->set('user', $user);
}
$this->user = $user;
return $this;
}
public function setAccessToken($access_token) {
$key = array_search('access_token', $this->persistantMap);
if ($key !== false) {
$this->store
->set('access_token', $access_token);
}
$this->access_token = $access_token;
return $this;
}
public function setRefreshToken($refresh_token) {
$key = array_search('refresh_token', $this->persistantMap);
if ($key !== false) {
$this->store
->set('refresh_token', $refresh_token);
}
$this->refresh_token = $refresh_token;
return $this;
}
public final function getAccessToken() {
if ($this->access_token === null) {
$this
->exchangeCode();
}
return $this->access_token;
}
public final function getRefreshToken() {
return $this->refresh_token;
}
public function setIdToken($id_token) {
$key = array_search('id_token', $this->persistantMap);
if ($key !== false) {
$this->store
->set('id_token', $id_token);
}
$this->id_token = $id_token;
return $this;
}
public final function getIdToken() {
if ($this->id_token === null) {
$this
->exchangeCode();
}
return $this->id_token;
}
public final function logout() {
$this
->deleteAllPersistentData();
$this->access_token = null;
$this->user = null;
$this->id_token = null;
$this->refresh_token = null;
}
protected final function generateUrl($domain_key, $path = '/') {
$base_domain = self::$URL_MAP[$domain_key];
$base_domain = str_replace('{domain}', $this->domain, $base_domain);
if ($path[0] === '/') {
$path = substr($path, 1);
}
return $base_domain . $path;
}
public final function checkRequirements() {
if (!function_exists('curl_version')) {
throw new CoreException('CURL extension is needed to use Auth0 SDK. Not found.');
}
if (!function_exists('json_decode')) {
throw new CoreException('JSON extension is needed to use Auth0 SDK. Not found.');
}
}
public function debugInfo($info) {
if ($this->debug_mode && (is_object($this->debugger) && $this->debugger instanceof \Closure)) {
list(, $caller) = debug_backtrace(false);
$caller_function = $caller['function'];
$caller_class = $caller['class'];
$this->debugger
->__invoke($caller_class . '::' . $caller_function . ' > ' . $info);
}
}
public function deleteAllPersistentData() {
foreach ($this->persistantMap as $key) {
$this->store
->delete($key);
}
}
public final function setDomain($domain) {
$this->domain = $domain;
return $this;
}
public final function getDomain() {
return $this->domain;
}
public final function setClientId($client_id) {
$this->client_id = $client_id;
return $this;
}
public final function getClientId() {
return $this->client_id;
}
public final function setClientSecret($client_secret) {
$this->client_secret = $client_secret;
return $this;
}
public final function getClientSecret() {
return $this->client_secret;
}
public final function setRedirectUri($redirect_uri) {
$this->redirect_uri = $redirect_uri;
return $this;
}
public final function getRedirectUri() {
return $this->redirect_uri;
}
public final function setDebugMode($debug_mode) {
$this->debug_mode = $debug_mode;
return $this;
}
public final function getDebugMode() {
return $this->debug_mode;
}
public final function setDebugger(\Closure $debugger) {
$this->debugger = $debugger;
return $this;
}
public final function getDebugger() {
return $this->debugger;
}
}