public function getToken()
    {
        $logger = $this->getLogger();
        $this->logTokenData();

        $cacheKey = sha1(sprintf('%s.%s', __METHOD__, json_encode(func_get_args())));
        $cacheItem = $this->cacheItemPool->getItem($cacheKey);
        if (!$this->accessToken && $cacheItem->isHit()) {
            $this->accessToken = $cacheItem->get();
        }

        // Access token has expired, but expiration token has not expired.
        // Issue ourselves a new access token for the same video manager.
        if (!is_null($this->accessToken)
            && $this->accessToken->expired()
            && !is_null($this->refreshToken)
            && !$this->refreshToken->expired()) {
            $logger->info('Access token has expired - getting new one for same video manager with refresh token');
            $this->accessToken = $this->createAccessTokenFromRefreshToken($this->refreshToken);
        } elseif (is_null($this->accessToken)
            || (!is_null($this->refreshToken) && $this->refreshToken->expired())) {
            // Either we have no token, or the refresh token has expired
            // so we will need to generate completely new tokens
            $logger->info('No access token, or refresh token has expired - generate completely new ones');
            $tokenData = $this->createNewTokens();

            $this->accessToken = $tokenData['accessToken'];
            $this->refreshToken = $tokenData['refreshToken'];
        }

        $cacheItem->set($this->accessToken);
        $cacheItem->expiresAt((new \DateTime())
            ->setTimestamp($this->accessToken->getTokenData()['exp'])
            ->sub(new \DateInterval('PT30S'))
        );
        $this->cacheItemPool->save($cacheItem);

        return $this->accessToken->getTokenString();
    }