Token based authentication for the REST API (#610).

This commit is contained in:
Alex Tselegidis 2020-03-27 11:02:06 +01:00
parent 3c4ecb2873
commit 2321c3b7fc
33 changed files with 161 additions and 27 deletions

View file

@ -37,7 +37,7 @@ $config['migration_table'] = 'ea_migrations';
| be upgraded / downgraded to.
|
*/
$config['migration_version'] = 15; // current
$config['migration_version'] = 17; // current
/*

View file

@ -11,7 +11,7 @@
* @since v1.2.0
* ---------------------------------------------------------------------------- */
use \EA\Engine\Types\NonEmptyText;
use EA\Engine\Types\NonEmptyText;
/**
* API V1 Controller
@ -35,27 +35,88 @@ class API_V1_Controller extends CI_Controller {
*/
public function __construct()
{
if ( ! isset($_SERVER['PHP_AUTH_USER']))
{
$this->_requestAuthentication();
return;
}
parent::__construct();
try
{
parent::__construct();
$this->load->model('settings_model');
$api_token = $this->settings_model->get_setting('api_token');
$authorization = new \EA\Engine\Api\V1\Authorization($this);
if ( ! empty($api_token) && $api_token === $this->_getBearerToken())
{
return;
}
if ( ! isset($_SERVER['PHP_AUTH_USER']))
{
$this->_requestAuthentication();
return;
}
$username = new NonEmptyText($_SERVER['PHP_AUTH_USER']);
$password = new NonEmptyText($_SERVER['PHP_AUTH_PW']);
$authorization = new \EA\Engine\Api\V1\Authorization($this);
$authorization->basic($username, $password);
}
catch (\Exception $exception)
} catch (\Exception $exception)
{
exit($this->_handleException($exception));
}
}
/**
* Returns the bearer token value.
*
* @return string
*/
protected function _getBearerToken()
{
$headers = $this->_getAuthorizationHeader();
// HEADER: Get the access token from the header
if ( ! empty($headers))
{
if (preg_match('/Bearer\s(\S+)/', $headers, $matches))
{
return $matches[1];
}
}
return NULL;
}
/**
* Returns the authorization header.
*
* @return string
*/
protected function _getAuthorizationHeader()
{
$headers = NULL;
if (isset($_SERVER['Authorization']))
{
$headers = trim($_SERVER['Authorization']);
} else
{
if (isset($_SERVER['HTTP_AUTHORIZATION']))
{
//Nginx or fast CGI
$headers = trim($_SERVER['HTTP_AUTHORIZATION']);
} elseif (function_exists('apache_request_headers'))
{
$requestHeaders = apache_request_headers();
// Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
//print_r($requestHeaders);
if (isset($requestHeaders['Authorization']))
{
$headers = trim($requestHeaders['Authorization']);
}
}
}
return $headers;
}
/**
* Sets request authentication headers.
*/

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Aggiungi giornata lavorativa';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,5 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -308,3 +308,4 @@ $lang['add_extra_period'] = 'Add a working day';
$lang['require_phone_number'] = 'Require phone number';
$lang['require_phone_number_hint'] = 'When enabled, customers and users will need to enter the customer\'s phone number when booking an appointment';
$lang['check_spam_folder'] = 'Please check your spam folder if the email does not arrive within a few minutes.';
$lang['api_token_hint'] = 'Set a secret token in order to enable the token based authentication of the Easy!Appointments API.';

View file

@ -11,7 +11,7 @@
* @since v1.4.0
* ---------------------------------------------------------------------------- */
class Migration_location extends CI_Migration {
class Migration_add_appointment_location_column extends CI_Migration {
public function up()
{
$this->db->query('

View file

@ -0,0 +1,35 @@
<?php defined('BASEPATH') OR exit('No direct script access allowed');
/* ----------------------------------------------------------------------------
* Easy!Appointments - Open Source Web Scheduler
*
* @package EasyAppointments
* @author A.Tselegidis <alextselegidis@gmail.com>
* @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
* @license http://opensource.org/licenses/GPL-3.0 - GPLv3
* @link http://easyappointments.org
* @since v1.4.0
* ---------------------------------------------------------------------------- */
class Migration_Add_api_token_setting extends CI_Migration {
public function up()
{
$this->load->model('settings_model');
try
{
$this->settings_model->get_setting('api_token');
}
catch (Exception $exception)
{
$this->settings_model->set_setting('api_token', '');
}
}
public function down()
{
$this->load->model('settings_model');
$this->settings_model->remove_setting('api_token');
}
}

View file

@ -100,17 +100,7 @@
<?= lang('company_link_hint') ?>
</span>
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="form-group">
<label for="google-analytics-code">
Google Analytics ID</label>
<input id="google-analytics-code" placeholder="UA-XXXXXXXX-X"
data-field="google_analytics_code" class="form-control">
<span class="help-block">
<?= lang('google_analytics_code_hint') ?>
</span>
</div>
<div class="form-group">
<label for="date-format">
<?= lang('date_format') ?>
@ -153,6 +143,27 @@
<?= lang('first_weekday_hint') ?>
</span>
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="form-group">
<label for="google-analytics-code">
Google Analytics ID</label>
<input id="google-analytics-code" placeholder="UA-XXXXXXXX-X"
data-field="google_analytics_code" class="form-control">
<span class="help-block">
<?= lang('google_analytics_code_hint') ?>
</span>
</div>
<div class="form-group">
<label for="api-token">
API Token</label>
<input id="api-token"
data-field="api_token" class="form-control">
<span class="help-block">
<?= lang('api_token_hint') ?>
</span>
</div>
<div class="form-group">
<label><?= lang('customer_notifications') ?></label>
<br>

View file

@ -24,6 +24,7 @@ VALUES
('display_privacy_policy', '0'),
('privacy_policy_content', 'Privacy policy content.'),
('first_weekday', 'sunday'),
('require_phone_number', '1');
('require_phone_number', '1'),
('api_token', '');
INSERT INTO `ea_migrations` VALUES ('15');
INSERT INTO `ea_migrations` VALUES ('16');