public function checkAccessToken(EventInterface $event)
{
$request = $event->getRequest();
$response = $event->getResponse();
$query = $request->query;
$eventName = $event->getName();
$config = $event->getConfig();
if (($eventName === 'image.get' || $eventName === 'image.head') && $this->isWhitelisted($request)) {
// All transformations in the request are whitelisted. Skip the access token check
return;
}
// If the response has a short URL header, we can skip the access token check
if ($response->headers->has('X-Imbo-ShortUrl')) {
return;
}
if (!$query->has('accessToken')) {
throw new RuntimeException('Missing access token', 400);
}
$token = $query->get('accessToken');
// First the the raw un-encoded URI, then the URI as is
$uris = [$request->getRawUri(), $request->getUriAsIs()];
$privateKey = $event->getAccessControl()->getPrivateKey($request->getPublicKey());
// append uris with [] expanded or [0] reduced
$uris[] = $this->getUnescapedAlternativeURL($request->getRawUri());
$uris[] = $this->getEscapedAlternativeURL($request->getRawUri());
// See if we should modify the protocol for the incoming request
$protocol = $config['authentication']['protocol'];
if ($protocol === 'both') {
$uris = array_reduce($uris, function ($dest, $uri) {
$baseUrl = preg_replace('#^https?#', '', $uri);
$dest[] = 'http' . $baseUrl;
$dest[] = 'https' . $baseUrl;
return $dest;
}, []);
} else {
if (in_array($protocol, ['http', 'https'])) {
$uris = array_map(function ($uri) use($protocol) {
return preg_replace('#^https?#', $protocol, $uri);
}, $uris);
}
}
foreach ($uris as $uri) {
// Remove the access token from the query string as it's not used to generate the HMAC
$uri = rtrim(preg_replace('/(?<=(\\?|&))accessToken=[^&]+&?/', '', $uri), '&?');
$correctToken = hash_hmac('sha256', $uri, $privateKey);
if ($correctToken === $token) {
return;
}
}
throw new RuntimeException('Incorrect access token', 400);
}