Browse Source

Handle errors better

microsub
J. King 5 years ago
parent
commit
c814ce1791
  1. 84
      lib/REST/Microsub/Auth.php

84
lib/REST/Microsub/Auth.php

@ -50,7 +50,13 @@ class Auth extends \JKingWeb\Arsse\REST\AbstractHandler {
return new EmptyResponse(405, ['Allow' => implode(",", array_keys(self::FUNCTIONS[$process]))]);
} else {
$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);
} else {
// user has logged in
// ensure the logged-in user matches the IndieAuth identifier URL
$id = $req->getAttribute("authenticatedUser");
$query = $req->getQueryParams();
$url = buildIdentifier($req);
if ($user !== $id || URL::normalize($query['me']) !== $url) {
return new EmptyResponse(403);
} else {
$redir = URL::normalize(rawurldecode($query['redirect_uri']));
$state = $query['state'] ?? "";
// check that the redirect URL is an absolute one
if (!URL::absolute($redir)) {
return new EmptyResponse(400);
$redir = URL::normalize(rawurldecode($query['redirect_uri']));
// check that the redirect URL is an absolute one
if (!URL::absolute($redir)) {
return new EmptyResponse(400);
}
try {
// ensure the logged-in user matches the IndieAuth identifier URL
$id = $req->getAttribute("authenticatedUser");
$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
$data = json_encode([
'id' => $query['client_id'],
'url' => $query['redirect_uri'],
'type' => $type,
],\JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
// issue an authorization code and build the redirect URL
$code = Arsse::$db->tokenCreate($id, "microsub.auth", null, Date::add("PT2M"), $data);
$next = URL::queryAppend($redir, "code=$code&state=$state");
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
*
* @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 {
$post = $req->getParsedBody();
try {
// validate the request parameters
$code = $post['code'] ?? "";
$id = $post['client_id'] ?? "";
$url = $post['redirect_uri'] ?? "";
if (!strlen($code) || !strlen($id) || !strlen($url)) {
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 {
return new JsonResponse(['me' => $this->buildIdentifier($req)]);
// validate the request parameters
$code = $post['code'] ?? "";
$id = $post['client_id'] ?? "";
$url = $post['redirect_uri'] ?? "";
if (!strlen($code) || !strlen($id) || !strlen($url)) {
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;
}
} 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);
return new JsonResponse($out);
}
}

Loading…
Cancel
Save