protected function parseToken()
    {
        $request = $this->requestHandler->getRequest();
        if (! $request->hasHeader('Authorization')) {
            return null;
        }

        try {
            // Attempt to parse and validate the JWT
            $jwt = $request->bearerToken();
            $token = (new Parser())->parse($jwt);
            if (! $token->verify(new Sha256(), file_get_contents($this->publicKey))) {
                throw new AccessDeniedException(
                    'Access token could not be verified.',
                    'Check authorization and resource environment match & that token has not been tampered with.'
                );
            }

            // Ensure access token hasn't expired
            $data = new ValidationData();
            $data->setCurrentTime(Carbon::now()->timestamp);
            if ($token->validate($data) === false) {
                throw new AccessDeniedException('Access token is invalid or expired.');
            }

            // We've made it! Save the details on the validator.
            return $token;
        } catch (\InvalidArgumentException $exception) {
            throw new AccessDeniedException('Could not parse JWT.', $exception->getMessage());
        } catch (\RuntimeException $exception) {
            throw new AccessDeniedException('Error while decoding JWT contents.');
        }
    }