mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-23 09:02:41 +00:00
Second set of authentication tests
This commit is contained in:
parent
ba17d16358
commit
c0f42ac031
4 changed files with 29 additions and 14 deletions
|
@ -39,7 +39,12 @@ class URL {
|
||||||
* @param string $p Password to add to the URL, if a username is specified
|
* @param string $p Password to add to the URL, if a username is specified
|
||||||
*/
|
*/
|
||||||
public static function normalize(string $url, string $u = null, string $p = null): string {
|
public static function normalize(string $url, string $u = null, string $p = null): string {
|
||||||
extract(parse_url($url));
|
$parts = parse_url($url);
|
||||||
|
if (!$parts) {
|
||||||
|
// bail if there is no authority
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
extract($parts);
|
||||||
$out = "";
|
$out = "";
|
||||||
if (isset($scheme)) {
|
if (isset($scheme)) {
|
||||||
$out .= strtolower($scheme).":";
|
$out .= strtolower($scheme).":";
|
||||||
|
|
|
@ -120,6 +120,9 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
*/
|
*/
|
||||||
protected function matchIdentifier(string $canonical, string $me): bool {
|
protected function matchIdentifier(string $canonical, string $me): bool {
|
||||||
$me = parse_url(URL::normalize($me));
|
$me = parse_url(URL::normalize($me));
|
||||||
|
if (!$me) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$me['scheme'] = $me['scheme'] ?? "";
|
$me['scheme'] = $me['scheme'] ?? "";
|
||||||
$me['path'] = explode("/", $me['path'] ?? "");
|
$me['path'] = explode("/", $me['path'] ?? "");
|
||||||
$me['id'] = rawurldecode(array_pop($me['path']) ?? "");
|
$me['id'] = rawurldecode(array_pop($me['path']) ?? "");
|
||||||
|
@ -191,7 +194,7 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return new EmptyResponse(400);
|
return new EmptyResponse(400);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$state = $query['state'] ?? "";
|
$state = rawurlencode($query['state'] ?? "");
|
||||||
// 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'])) {
|
||||||
|
@ -210,7 +213,7 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
], \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
|
], \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
|
||||||
// issue an authorization code and build the redirect URL
|
// issue an authorization code and build the redirect URL
|
||||||
$code = Arsse::$db->tokenCreate($user, "microsub.auth", null, Date::add("PT2M"), $data);
|
$code = Arsse::$db->tokenCreate($user, "microsub.auth", null, Date::add("PT2M"), $data);
|
||||||
$next = URL::queryAppend($redir, "code=$code&state=$state");
|
$next = URL::queryAppend($redir, "state=$state&code=$code");
|
||||||
return new EmptyResponse(302, ['Location' => $next]);
|
return new EmptyResponse(302, ['Location' => $next]);
|
||||||
} catch (ExceptionAuth $e) {
|
} catch (ExceptionAuth $e) {
|
||||||
$next = URL::queryAppend($redir, "state=$state&error=".$e->getMessage());
|
$next = URL::queryAppend($redir, "state=$state&error=".$e->getMessage());
|
||||||
|
|
|
@ -73,6 +73,7 @@ class TestURL extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
["EXAMPLE.COM/", "EXAMPLE.COM/"],
|
["EXAMPLE.COM/", "EXAMPLE.COM/"],
|
||||||
["EXAMPLE.COM", "EXAMPLE.COM"],
|
["EXAMPLE.COM", "EXAMPLE.COM"],
|
||||||
[" ", "%20"],
|
[" ", "%20"],
|
||||||
|
["http:///%G", "http:///%G"]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace JKingWeb\Arsse\TestCase\REST\Microsub;
|
||||||
|
|
||||||
use JKingWeb\Arsse\Arsse;
|
use JKingWeb\Arsse\Arsse;
|
||||||
use JKingWeb\Arsse\Database;
|
use JKingWeb\Arsse\Database;
|
||||||
|
use JKingWeb\Arsse\Misc\Date;
|
||||||
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;
|
||||||
|
@ -97,7 +98,7 @@ class TestAuth extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
$act = $this->req("http://example.com/u/?f=auth", "GET", $params, [], [], "", null, $authenticatedUser);
|
$act = $this->req("http://example.com/u/?f=auth", "GET", $params, [], [], "", null, $authenticatedUser);
|
||||||
$this->assertMessage($exp, $act);
|
$this->assertMessage($exp, $act);
|
||||||
if ($act->getStatusCode() == 302 && !preg_match("/\berror=\w/", $act->getHeaderLine("Location") ?? "")) {
|
if ($act->getStatusCode() == 302 && !preg_match("/\berror=\w/", $act->getHeaderLine("Location") ?? "")) {
|
||||||
\Phake::verify(Arsse::$db)->tokenCreate($authenticatedUser, "microsub.auth", null, null, json_encode([
|
\Phake::verify(Arsse::$db)->tokenCreate($authenticatedUser, "microsub.auth", null, $this->isInstanceOf(\DateTimeInterface::class), json_encode([
|
||||||
'me' => $params['me'],
|
'me' => $params['me'],
|
||||||
'client_id' => $params['client_id'],
|
'client_id' => $params['client_id'],
|
||||||
'redirect_uri' => $params['redirect_uri'],
|
'redirect_uri' => $params['redirect_uri'],
|
||||||
|
@ -110,16 +111,21 @@ class TestAuth extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
|
||||||
public function provideLoginData() {
|
public function provideLoginData() {
|
||||||
return [
|
return [
|
||||||
'Challenge' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], null, new EmptyResponse(401)],
|
'Challenge' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], null, new EmptyResponse(401)],
|
||||||
'Failed challenge' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "", new EmptyResponse(401)],
|
'Failed challenge' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "", new EmptyResponse(401)],
|
||||||
'Wrong user 1' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "jane.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
'Wrong user 1' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "jane.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Wrong user 2' => [['me' => "https://example.com/u/jane.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
'Wrong user 2' => [['me' => "https://example.com/u/jane.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Wrong domain' => [['me' => "https://example.net/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
'Wrong domain 1' => [['me' => "https://example.net/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Wrong port' => [['me' => "https://example.com:80/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
'Wrong domain 2' => [['me' => "https:///u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Wrong scheme' => [['me' => "ftp://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
'Wrong port' => [['me' => "https://example.com:80/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Wrong path' => [['me' => "http://example.com/user/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
'Wrong scheme' => [['me' => "ftp://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Bad redirect' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "//example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(400)],
|
'Wrong path' => [['me' => "http://example.com/user/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=access_denied"])],
|
||||||
'Bad response type' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "bad"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=unsupported_response_type"])],
|
'Bad redirect 1' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "//example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(400)],
|
||||||
|
'Bad redirect 2' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "https:///redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(400)],
|
||||||
|
'Bad response type' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "bad"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&error=unsupported_response_type"])],
|
||||||
|
'Success 1' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=ABCDEF&code=authCode"])],
|
||||||
|
'Success 2' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/redirect", 'state' => "R&R", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/redirect?state=R%26R&code=authCode"])],
|
||||||
|
'Success 3' => [['me' => "https://example.com/u/john.doe", 'client_id' => "http://example.org/", 'redirect_uri' => "http://example.org/?p=redirect", 'state' => "ABCDEF", 'response_type' => "code"], "john.doe", new EmptyResponse(302, ['Location' => "http://example.org/?p=redirect&state=ABCDEF&code=authCode"])],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue