1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-23 09:02:41 +00:00

Handle errors better

This commit is contained in:
J. King 2019-09-14 20:51:05 -04:00
parent daab0068d6
commit c814ce1791

View file

@ -50,7 +50,13 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
return new EmptyResponse(405, ['Allow' => implode(",", array_keys(self::FUNCTIONS[$process]))]); return new EmptyResponse(405, ['Allow' => implode(",", array_keys(self::FUNCTIONS[$process]))]);
} else { } else {
$func = self::FUNCTIONS[$process][$method]; $func = self::FUNCTIONS[$process][$method];
return $this->$func($id, $req); try {
return $this->$func($id, $req);
} catch (ExceptionAuth $e) {
// human-readable error messages could be added, but these must be ASCII per OAuth, so there's probably not much point
// see https://tools.ietf.org/html/rfc6749#section-5.2
return new JsonResponse(['error' => $e->getMessage()], 400);
}
} }
} }
@ -112,28 +118,37 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
return new EmptyResponse(401); return new EmptyResponse(401);
} else { } else {
// user has logged in // user has logged in
// ensure the logged-in user matches the IndieAuth identifier URL
$id = $req->getAttribute("authenticatedUser");
$query = $req->getQueryParams(); $query = $req->getQueryParams();
$url = buildIdentifier($req); $redir = URL::normalize(rawurldecode($query['redirect_uri']));
if ($user !== $id || URL::normalize($query['me']) !== $url) { // check that the redirect URL is an absolute one
return new EmptyResponse(403); if (!URL::absolute($redir)) {
} else { return new EmptyResponse(400);
$redir = URL::normalize(rawurldecode($query['redirect_uri'])); }
$state = $query['state'] ?? ""; try {
// check that the redirect URL is an absolute one // ensure the logged-in user matches the IndieAuth identifier URL
if (!URL::absolute($redir)) { $id = $req->getAttribute("authenticatedUser");
return new EmptyResponse(400); $url = buildIdentifier($req);
if ($user !== $id || URL::normalize($query['me']) !== $url) {
throw new ExceptionAuth("access_denied");
} }
$type = !strlen($query['response_type'] ?? "") ? "id" : $query['response_type'];
if (!in_array($type, ["code", "id"])) {
throw new ExceptionAuth("unsupported_response_type");
}
$state = $query['state'] ?? "";
// store the client ID and redirect URL // store the client ID and redirect URL
$data = json_encode([ $data = json_encode([
'id' => $query['client_id'], 'id' => $query['client_id'],
'url' => $query['redirect_uri'], 'url' => $query['redirect_uri'],
'type' => $type,
],\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($id, "microsub.auth", null, Date::add("PT2M"), $data); $code = Arsse::$db->tokenCreate($id, "microsub.auth", null, Date::add("PT2M"), $data);
$next = URL::queryAppend($redir, "code=$code&state=$state"); $next = URL::queryAppend($redir, "code=$code&state=$state");
return new EmptyResponse(302, ["Location: $next"]); return new EmptyResponse(302, ["Location: $next"]);
} catch (ExceptionAuth $e) {
$next = URL::queryAppend($redir, "state=$state&error=".$e->getMessage());
return new EmptyResponse(302, ["Location: $next"]);
} }
} }
} }
@ -147,33 +162,32 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
* doesn't actually matter for our purposes * doesn't actually matter for our purposes
* *
* @see https://indieauth.spec.indieweb.org/#authorization-code-verification * @see https://indieauth.spec.indieweb.org/#authorization-code-verification
* @see https://indieauth.spec.indieweb.org/#authorization-code-verification-0
*/ */
protected function opCodeVerification(string $user, ServerRequestInterface $req): ResponseInterface { protected function opCodeVerification(string $user, ServerRequestInterface $req): ResponseInterface {
$post = $req->getParsedBody(); $post = $req->getParsedBody();
try { // validate the request parameters
// validate the request parameters $code = $post['code'] ?? "";
$code = $post['code'] ?? ""; $id = $post['client_id'] ?? "";
$id = $post['client_id'] ?? ""; $url = $post['redirect_uri'] ?? "";
$url = $post['redirect_uri'] ?? ""; if (!strlen($code) || !strlen($id) || !strlen($url)) {
if (!strlen($code) || !strlen($id) || !strlen($url)) { throw new ExceptionAuth("invalid_request");
throw new ExceptionAuth("invalid_request"); }
// check that the token exists
$token = Arsse::$db->tokenLookup("microsub.auth", $code);
if (!$token) {
throw new ExceptionAuth("unsupported_grant_type");
}
$data = @json_decode($token['data'], true);
// validate the token
if ($token['user'] !== $user || !is_array($data) || $data['id'] !== $id || $data['url'] !== $url) {
throw new ExceptionAuth("unsupported_grant_type");
} else {
$out = ['me' => $this->buildIdentifier($req)];
if ($data['type'] === "code") {
$out['scope'] = self::SCOPES;
} }
// check that the token exists return new JsonResponse($out);
$token = Arsse::$db->tokenLookup("microsub.auth", $code);
if (!$token) {
throw new ExceptionAuth("unsupported_grant_type");
}
$data = @json_decode($token['data'], true);
// validate the token
if ($token['user'] !== $user || !is_array($data) || $data['id'] !== $id || $data['url'] !== $url) {
throw new ExceptionAuth("unsupported_grant_type");
} else {
return new JsonResponse(['me' => $this->buildIdentifier($req)]);
}
} catch (ExceptionAuth $e) {
// human-readable error messages could be added, but these must be ASCII per OAuth, so there's probably not much point
// see https://tools.ietf.org/html/rfc6749#section-5.2
return new JsonResponse(['error' => $e->getMessage()], 400);
} }
} }