Restructured src to use PSR-4 autoloading, moved many functions to functions.php
This commit is contained in:
parent
1b2bd1f513
commit
b111c619d4
@ -9,6 +9,17 @@
|
|||||||
"email": "barnaby@waterpigs.co.uk"
|
"email": "barnaby@waterpigs.co.uk"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"autoload": {
|
||||||
|
"files": ["src/functions.php"],
|
||||||
|
"psr-4": {
|
||||||
|
"Taproot\\IndieAuth": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Taproot\\IndieAuth\\Test": "tests"
|
||||||
|
}
|
||||||
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"psr/http-message": "^1.0",
|
"psr/http-message": "^1.0",
|
||||||
"psr/log": "^1.1",
|
"psr/log": "^1.1",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Taproot\IndieAuth;
|
namespace Taproot\IndieAuth\Middleware;
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Taproot\IndieAuth;
|
namespace Taproot\IndieAuth\Middleware;
|
||||||
|
|
||||||
use Nyholm\Psr7\Response;
|
use Nyholm\Psr7\Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
@ -11,21 +11,7 @@ use Dflydev\FigCookies;
|
|||||||
use Psr\Log\LoggerAwareInterface;
|
use Psr\Log\LoggerAwareInterface;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Psr\Log\NullLogger;
|
use Psr\Log\NullLogger;
|
||||||
|
use function Taproot\IndieAuth\generateRandomString;
|
||||||
// From https://github.com/indieweb/indieauth-client-php/blob/main/src/IndieAuth/Client.php, thanks aaronpk.
|
|
||||||
function generateRandomString($numBytes) {
|
|
||||||
if (function_exists('random_bytes')) {
|
|
||||||
$bytes = random_bytes($numBytes);
|
|
||||||
} elseif (function_exists('openssl_random_pseudo_bytes')){
|
|
||||||
$bytes = openssl_random_pseudo_bytes($numBytes);
|
|
||||||
} else {
|
|
||||||
$bytes = '';
|
|
||||||
for($i=0, $bytes=''; $i < $numBytes; $i++) {
|
|
||||||
$bytes .= chr(mt_rand(0, 255));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bin2hex($bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
class DoubleSubmitCookieCsrfMiddleware implements MiddlewareInterface, LoggerAwareInterface {
|
class DoubleSubmitCookieCsrfMiddleware implements MiddlewareInterface, LoggerAwareInterface {
|
||||||
const READ_METHODS = ['HEAD', 'GET', 'OPTIONS'];
|
const READ_METHODS = ['HEAD', 'GET', 'OPTIONS'];
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Taproot\IndieAuth;
|
namespace Taproot\IndieAuth\Middleware;
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
@ -35,54 +35,6 @@ use function PHPSTORM_META\type;
|
|||||||
* Example CSRF protection cookie middleware: https://github.com/zakirullin/csrf-middleware/blob/master/src/CSRF.php
|
* Example CSRF protection cookie middleware: https://github.com/zakirullin/csrf-middleware/blob/master/src/CSRF.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: maybe move these to a functions file so they’re usable by consumers even when the class isn’t loaded.
|
|
||||||
// Alternatively, make them static methods so they can be autoloaded.
|
|
||||||
function isIndieAuthAuthorizationCodeRedeemingRequest(ServerRequestInterface $request) {
|
|
||||||
return strtolower($request->getMethod()) == 'post'
|
|
||||||
&& array_key_exists('grant_type', $request->getParsedBody())
|
|
||||||
&& $request->getParsedBody()['grant_type'] == 'authorization_code';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIndieAuthAuthorizationRequest(ServerRequestInterface $request, $permittedMethods=['get']) {
|
|
||||||
return in_array(strtolower($request->getMethod()), array_map('strtolower', $permittedMethods))
|
|
||||||
&& array_key_exists('response_type', $request->getQueryParams())
|
|
||||||
&& $request->getQueryParams()['response_type'] == 'code';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isAuthorizationApprovalRequest(ServerRequestInterface $request) {
|
|
||||||
return strtolower($request->getMethod()) == 'post'
|
|
||||||
&& array_key_exists('taproot_indieauth_action', $request->getParsedBody())
|
|
||||||
&& $request->getParsedBody()['taproot_indieauth_action'] == 'approve';
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildQueryString(array $parameters) {
|
|
||||||
$qs = [];
|
|
||||||
foreach ($parameters as $k => $v) {
|
|
||||||
$qs[] = urlencode($k) . '=' . urlencode($v);
|
|
||||||
}
|
|
||||||
return join('&', $qs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append Query Parameters
|
|
||||||
*
|
|
||||||
* Converts `$queryParams` into a query string, then checks `$uri` for an
|
|
||||||
* existing query string. Then appends the newly generated query string
|
|
||||||
* with either ? or & as appropriate.
|
|
||||||
*/
|
|
||||||
function appendQueryParams(string $uri, array $queryParams) {
|
|
||||||
$queryString = buildQueryString($queryParams);
|
|
||||||
$separator = parse_url($uri, \PHP_URL_QUERY) ? '&' : '?';
|
|
||||||
return "{$uri}{$separator}{$queryString}";
|
|
||||||
}
|
|
||||||
|
|
||||||
function trySetLogger($target, LoggerInterface $logger) {
|
|
||||||
if ($target instanceof LoggerAwareInterface) {
|
|
||||||
$target->setLogger($logger);
|
|
||||||
}
|
|
||||||
return $target;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
const CUSTOMIZE_AUTHORIZATION_CODE = 'customise_authorization_code';
|
const CUSTOMIZE_AUTHORIZATION_CODE = 'customise_authorization_code';
|
||||||
const SHOW_AUTHORIZATION_PAGE = 'show_authorization_page';
|
const SHOW_AUTHORIZATION_PAGE = 'show_authorization_page';
|
||||||
@ -92,9 +44,9 @@ class Server {
|
|||||||
|
|
||||||
public $callbacks;
|
public $callbacks;
|
||||||
|
|
||||||
public TokenStorageInterface $authorizationCodeStorage;
|
public Storage\TokenStorageInterface $authorizationCodeStorage;
|
||||||
|
|
||||||
public TokenStorageInterface $accessTokenStorage;
|
public Storage\TokenStorageInterface $accessTokenStorage;
|
||||||
|
|
||||||
public MiddlewareInterface $csrfMiddleware;
|
public MiddlewareInterface $csrfMiddleware;
|
||||||
|
|
||||||
@ -133,9 +85,9 @@ class Server {
|
|||||||
$this->callbacks = $callbacks;
|
$this->callbacks = $callbacks;
|
||||||
|
|
||||||
$authorizationCodeStorage = $config['authorizationCodeStorage'];
|
$authorizationCodeStorage = $config['authorizationCodeStorage'];
|
||||||
if (!$authorizationCodeStorage instanceof TokenStorageInterface) {
|
if (!$authorizationCodeStorage instanceof Storage\TokenStorageInterface) {
|
||||||
if (is_string($authorizationCodeStorage)) {
|
if (is_string($authorizationCodeStorage)) {
|
||||||
$authorizationCodeStorage = new FilesystemJsonStorage($authorizationCodeStorage, 600, true);
|
$authorizationCodeStorage = new Storage\FilesystemJsonStorage($authorizationCodeStorage, 600, true);
|
||||||
} else {
|
} else {
|
||||||
throw new Exception('$authorizationCodeStorage parameter must be either a string (path) or an instance of Taproot\IndieAuth\TokenStorageInterface.');
|
throw new Exception('$authorizationCodeStorage parameter must be either a string (path) or an instance of Taproot\IndieAuth\TokenStorageInterface.');
|
||||||
}
|
}
|
||||||
@ -144,10 +96,10 @@ class Server {
|
|||||||
$this->authorizationCodeStorage = $authorizationCodeStorage;
|
$this->authorizationCodeStorage = $authorizationCodeStorage;
|
||||||
|
|
||||||
$accessTokenStorage = $config['accessTokenStorage'];
|
$accessTokenStorage = $config['accessTokenStorage'];
|
||||||
if (!$accessTokenStorage instanceof TokenStorageInterface) {
|
if (!$accessTokenStorage instanceof Storage\TokenStorageInterface) {
|
||||||
if (is_string($accessTokenStorage)) {
|
if (is_string($accessTokenStorage)) {
|
||||||
// Create a default access token storage with a TTL of 7 days.
|
// Create a default access token storage with a TTL of 7 days.
|
||||||
$accessTokenStorage = new FilesystemJsonStorage($accessTokenStorage, 60 * 60 * 24 * 7, true);
|
$accessTokenStorage = new Storage\FilesystemJsonStorage($accessTokenStorage, 60 * 60 * 24 * 7, true);
|
||||||
} else {
|
} else {
|
||||||
throw new Exception('$accessTokenStorage parameter must be either a string (path) or an instance of Taproot\IndieAuth\TokenStorageInterface.');
|
throw new Exception('$accessTokenStorage parameter must be either a string (path) or an instance of Taproot\IndieAuth\TokenStorageInterface.');
|
||||||
}
|
}
|
||||||
@ -160,7 +112,7 @@ class Server {
|
|||||||
$csrfMiddleware = $config['csrfMiddleware'];
|
$csrfMiddleware = $config['csrfMiddleware'];
|
||||||
if (!$csrfMiddleware instanceof MiddlewareInterface) {
|
if (!$csrfMiddleware instanceof MiddlewareInterface) {
|
||||||
// Default to the statless Double-Submit Cookie CSRF Middleware, with default settings.
|
// Default to the statless Double-Submit Cookie CSRF Middleware, with default settings.
|
||||||
$csrfMiddleware = new DoubleSubmitCookieCsrfMiddleware($this->csrfKey);
|
$csrfMiddleware = new Middleware\DoubleSubmitCookieCsrfMiddleware($this->csrfKey);
|
||||||
}
|
}
|
||||||
trySetLogger($csrfMiddleware, $this->logger);
|
trySetLogger($csrfMiddleware, $this->logger);
|
||||||
$this->csrfMiddleware = $csrfMiddleware;
|
$this->csrfMiddleware = $csrfMiddleware;
|
||||||
@ -214,7 +166,7 @@ class Server {
|
|||||||
|
|
||||||
// Because the special case above isn’t allowed to be CSRF-protected, we have to do some rather silly
|
// Because the special case above isn’t allowed to be CSRF-protected, we have to do some rather silly
|
||||||
// gymnastics here to selectively-CSRF-protect requests which do need it.
|
// gymnastics here to selectively-CSRF-protect requests which do need it.
|
||||||
return $this->csrfMiddleware->process($request, new ClosureRequestHandler(function (ServerRequestInterface $request) {
|
return $this->csrfMiddleware->process($request, new Middleware\ClosureRequestHandler(function (ServerRequestInterface $request) {
|
||||||
// If this is an authorization or approval request (allowing POST requests as well to accommodate
|
// If this is an authorization or approval request (allowing POST requests as well to accommodate
|
||||||
// approval requests and custom auth form submission.
|
// approval requests and custom auth form submission.
|
||||||
if (isIndieAuthAuthorizationRequest($request, ['get', 'post'])) {
|
if (isIndieAuthAuthorizationRequest($request, ['get', 'post'])) {
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Taproot\IndieAuth;
|
namespace Taproot\IndieAuth\Storage;
|
||||||
|
|
||||||
use DirectoryIterator;
|
use DirectoryIterator;
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Taproot\IndieAuth;
|
namespace Taproot\IndieAuth\Storage;
|
||||||
|
|
||||||
// TODO: document.
|
// TODO: document.
|
||||||
|
|
74
src/functions.php
Normal file
74
src/functions.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Taproot\IndieAuth;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Log\LoggerAwareInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
// From https://github.com/indieweb/indieauth-client-php/blob/main/src/IndieAuth/Client.php, thanks aaronpk.
|
||||||
|
function generateRandomString($numBytes) {
|
||||||
|
if (function_exists('random_bytes')) {
|
||||||
|
$bytes = random_bytes($numBytes);
|
||||||
|
} elseif (function_exists('openssl_random_pseudo_bytes')){
|
||||||
|
$bytes = openssl_random_pseudo_bytes($numBytes);
|
||||||
|
} else {
|
||||||
|
$bytes = '';
|
||||||
|
for($i=0, $bytes=''; $i < $numBytes; $i++) {
|
||||||
|
$bytes .= chr(mt_rand(0, 255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bin2hex($bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isIndieAuthAuthorizationCodeRedeemingRequest(ServerRequestInterface $request) {
|
||||||
|
return strtolower($request->getMethod()) == 'post'
|
||||||
|
&& array_key_exists('grant_type', $request->getParsedBody())
|
||||||
|
&& $request->getParsedBody()['grant_type'] == 'authorization_code';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isIndieAuthAuthorizationRequest(ServerRequestInterface $request, $permittedMethods=['get']) {
|
||||||
|
return in_array(strtolower($request->getMethod()), array_map('strtolower', $permittedMethods))
|
||||||
|
&& array_key_exists('response_type', $request->getQueryParams())
|
||||||
|
&& $request->getQueryParams()['response_type'] == 'code';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAuthorizationApprovalRequest(ServerRequestInterface $request) {
|
||||||
|
return strtolower($request->getMethod()) == 'post'
|
||||||
|
&& array_key_exists('taproot_indieauth_action', $request->getParsedBody())
|
||||||
|
&& $request->getParsedBody()['taproot_indieauth_action'] == 'approve';
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQueryString(array $parameters) {
|
||||||
|
$qs = [];
|
||||||
|
foreach ($parameters as $k => $v) {
|
||||||
|
$qs[] = urlencode($k) . '=' . urlencode($v);
|
||||||
|
}
|
||||||
|
return join('&', $qs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append Query Parameters
|
||||||
|
*
|
||||||
|
* Converts `$queryParams` into a query string, then checks `$uri` for an
|
||||||
|
* existing query string. Then appends the newly generated query string
|
||||||
|
* with either ? or & as appropriate.
|
||||||
|
*/
|
||||||
|
function appendQueryParams(string $uri, array $queryParams) {
|
||||||
|
$queryString = buildQueryString($queryParams);
|
||||||
|
$separator = parse_url($uri, \PHP_URL_QUERY) ? '&' : '?';
|
||||||
|
return "{$uri}{$separator}{$queryString}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try setLogger
|
||||||
|
*
|
||||||
|
* If `$target` implements `LoggerAwareInterface`, set it’s logger
|
||||||
|
* to `$logger`. Returns `$target`.
|
||||||
|
*/
|
||||||
|
function trySetLogger($target, LoggerInterface $logger) {
|
||||||
|
if ($target instanceof LoggerAwareInterface) {
|
||||||
|
$target->setLogger($logger);
|
||||||
|
}
|
||||||
|
return $target;
|
||||||
|
}
|
Reference in New Issue
Block a user