mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-23 17:12:41 +00:00
Tests for logging in a bearer
This commit is contained in:
parent
2d78a59603
commit
f13366121f
3 changed files with 75 additions and 32 deletions
|
@ -201,7 +201,7 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
// ensure the logged-in user matches the IndieAuth identifier URL
|
// ensure the logged-in user matches the IndieAuth identifier URL
|
||||||
$user = $req->getAttribute("authenticatedUser");
|
$user = $req->getAttribute("authenticatedUser");
|
||||||
if (!$this->matchIdentifier($this->buildIdentifier($req, $user), $query['me'])) {
|
if (!$this->matchIdentifier($this->buildIdentifier($req, $user), $query['me'])) {
|
||||||
throw new ExceptionAuth("access_denied");
|
throw new ExceptionAuth("access_denied");
|
||||||
}
|
}
|
||||||
$type = !strlen($query['response_type'] ?? "") ? "id" : $query['response_type'];
|
$type = !strlen($query['response_type'] ?? "") ? "id" : $query['response_type'];
|
||||||
if (!in_array($type, ["code", "id"])) {
|
if (!in_array($type, ["code", "id"])) {
|
||||||
|
@ -337,7 +337,7 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return new JsonResponse([
|
return new JsonResponse([
|
||||||
'me' => $data['me'] ?? "",
|
'me' => $data['me'] ?? "",
|
||||||
'client_id' => $data['client_id'] ?? "",
|
'client_id' => $data['client_id'] ?? "",
|
||||||
'scope' => $data['scope'] ?? self::SCOPES,
|
'scope' => implode(" ", ($data['scope'] ?? self::SCOPES)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
* @throws \JKingWeb\Arsse\REST\Microsub\ExceptionAuth
|
* @throws \JKingWeb\Arsse\REST\Microsub\ExceptionAuth
|
||||||
*/
|
*/
|
||||||
public static function validateBearer(string $authorization, array $scopes = []): array {
|
public static function validateBearer(string $authorization, array $scopes = []): array {
|
||||||
if (!preg_match("/^Bearer (.+)/", $authorization, $match)) {
|
if (!preg_match("<^Bearer ([a-z0-9\._~/+-]+=*)$>i", $authorization, $match)) {
|
||||||
throw new ExceptionAuth("invalid_request");
|
throw new ExceptionAuth("invalid_request");
|
||||||
}
|
}
|
||||||
$token = $match[1];
|
$token = $match[1];
|
||||||
|
@ -374,7 +374,7 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} catch (\JKingWeb\Arsse\Db\ExceptionInput $e) {
|
} catch (\JKingWeb\Arsse\Db\ExceptionInput $e) {
|
||||||
throw new ExceptionAuth("invalid_token");
|
throw new ExceptionAuth("invalid_token");
|
||||||
}
|
}
|
||||||
$data = @json_decode($token['data'], true) ?? [];
|
$data = @json_decode((string) $token['data'], true) ?? [];
|
||||||
$data['scope'] = $data['scope'] ?? self::SCOPES;
|
$data['scope'] = $data['scope'] ?? self::SCOPES;
|
||||||
// scope is hard-coded for now
|
// scope is hard-coded for now
|
||||||
if (array_diff($scopes, $data['scope'])) {
|
if (array_diff($scopes, $data['scope'])) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
use JKingWeb\Arsse\Db\ExceptionInput;
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
||||||
use JKingWeb\Arsse\REST\Microsub\Auth;
|
use JKingWeb\Arsse\REST\Microsub\Auth;
|
||||||
|
use JKingWeb\Arsse\REST\Microsub\ExceptionAuth;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Zend\Diactoros\Response\JsonResponse as Response;
|
use Zend\Diactoros\Response\JsonResponse as Response;
|
||||||
use Zend\Diactoros\Response\EmptyResponse;
|
use Zend\Diactoros\Response\EmptyResponse;
|
||||||
|
@ -210,4 +211,42 @@ class TestAuth extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
'Success 2' => [['code' => "good-code", 'redirect_uri' => "https://example.org/", 'client_id' => "https://example.net/", 'grant_type' => "authorization_code", 'me' => "https://example.com/u/somehow"], "somehow", '{"me":"https://example.com/u/somehow","redirect_uri":"https://example.org/","client_id":"https://example.net/","response_type":"code"}', new Response(['me' => "http://example.com/u/somehow", 'token_type' => "Bearer", 'access_token' => "TOKEN", 'scope' => $scopes], 200)],
|
'Success 2' => [['code' => "good-code", 'redirect_uri' => "https://example.org/", 'client_id' => "https://example.net/", 'grant_type' => "authorization_code", 'me' => "https://example.com/u/somehow"], "somehow", '{"me":"https://example.com/u/somehow","redirect_uri":"https://example.org/","client_id":"https://example.net/","response_type":"code"}', new Response(['me' => "http://example.com/u/somehow", 'token_type' => "Bearer", 'access_token' => "TOKEN", 'scope' => $scopes], 200)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @dataProvider provideBearers */
|
||||||
|
public function testLogInABearer(string $authorization, array $scopes, string $token, string $user, $data, $exp) {
|
||||||
|
if ($data instanceof \Exception) {
|
||||||
|
\Phake::when(Arsse::$db)->tokenLookup("microsub.access", $this->anything())->thenThrow($data);
|
||||||
|
} else {
|
||||||
|
\Phake::when(Arsse::$db)->tokenLookup("microsub.access", $this->anything())->thenReturn(['user' => $user, 'data' => $data]);
|
||||||
|
}
|
||||||
|
if ($exp instanceof \Exception) {
|
||||||
|
$this->assertException($exp);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$act = Auth::validateBearer($authorization, $scopes);
|
||||||
|
$this->assertSame($exp, $act);
|
||||||
|
} finally {
|
||||||
|
if (strlen($token)) {
|
||||||
|
\Phake::verify(Arsse::$db)->tokenLookup("microsub.access", $token);
|
||||||
|
} else {
|
||||||
|
\Phake::verify(Arsse::$db, \Phake::times(0))->tokenLookup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideBearers() {
|
||||||
|
return [
|
||||||
|
'Not a bearer' => ["Beaver TOKEN", [], "", "", "", new ExceptionAuth("invalid_request")],
|
||||||
|
'Token missing 1' => ["Bearer", [], "", "", "", new ExceptionAuth("invalid_request")],
|
||||||
|
'Token missing 2' => ["Bearer ", [], "", "", "", new ExceptionAuth("invalid_request")],
|
||||||
|
'Not a token' => ["Bearer !", [], "", "", "", new ExceptionAuth("invalid_request")],
|
||||||
|
'Invalid token' => ["Bearer TOKEN", [], "TOKEN", "", new ExceptionInput("subjectMissing"), new ExceptionAuth("invalid_token")],
|
||||||
|
'Insufficient scope 1' => ["Bearer TOKEN", ["missing"], "TOKEN", "someone", null, new ExceptionAuth("insufficient_scope")],
|
||||||
|
'Insufficient scope 2' => ["Bearer TOKEN", ["channels"], "TOKEN", "someone", '{"scope":["read","follow"]}', new ExceptionAuth("insufficient_scope")],
|
||||||
|
'Success 1' => ["Bearer TOKEN", [], "TOKEN", "someone", null, ["someone", ['scope' => Auth::SCOPES]]],
|
||||||
|
'Success 2' => ["bearer TOKEN", [], "TOKEN", "someone", null, ["someone", ['scope' => Auth::SCOPES]]],
|
||||||
|
'Success 3' => ["BEARER TOKEN", [], "TOKEN", "someone", null, ["someone", ['scope' => Auth::SCOPES]]],
|
||||||
|
'Broken data' => ["Bearer TOKEN", [], "TOKEN", "someone", '{', ["someone", ['scope' => Auth::SCOPES]]],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\Test;
|
namespace JKingWeb\Arsse\Test;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\AbstractException;
|
||||||
use JKingWeb\Arsse\Exception;
|
use JKingWeb\Arsse\Exception;
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Conf;
|
use JKingWeb\Arsse\Conf;
|
||||||
|
@ -152,9 +153,12 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
|
||||||
|
|
||||||
public function assertException($msg = "", string $prefix = "", string $type = "Exception") {
|
public function assertException($msg = "", string $prefix = "", string $type = "Exception") {
|
||||||
if (func_num_args()) {
|
if (func_num_args()) {
|
||||||
if ($msg instanceof \JKingWeb\Arsse\AbstractException) {
|
if ($msg instanceof \Exception) {
|
||||||
$this->expectException(get_class($msg));
|
$this->expectException(get_class($msg));
|
||||||
$this->expectExceptionCode($msg->getCode());
|
$this->expectExceptionCode($msg->getCode());
|
||||||
|
if (!$msg instanceof AbstractException && strlen($msg->getMessage())) {
|
||||||
|
$this->expectExceptionMessage($msg->getMessage());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
$class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type;
|
||||||
$msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg";
|
$msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg";
|
||||||
|
|
Loading…
Reference in a new issue