public static function generate(string $token = null, int $length = null): Token
    {
        if ($token == null) {
            if ($length == null) {
                $length = 64;
            }

            // generate token here
            if (function_exists('openssl_random_pseudo_bytes')) {
                $token = bin2hex(openssl_random_pseudo_bytes($length));

                if (strlen($token) > $length) {
                    // we have a string, now, take some random part there
                    $token = substr($token, rand(0, strlen($token) - $length), $length);
                }
            } else {
                // a fallback if openssl_random_pseudo_bytes is not accessible for some reason
                $someString = time() . '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' . Application::getKey();
                $token = substr(str_shuffle($someString), 0, $length);
            }
        }

        $config = Application::getConfig('session');

        $cookieName = static::getCookieName();
        if (is_string($cookieName) && strlen($cookieName) > 0) {
            $cookie = Cookie::rawSet($cookieName, $token, 0, '/', $config->get('domain', ''), $config->get('cookie_secure', false), false);
        } else {
            $cookie = null;
        }

        $token = new Token($token, $cookie);
        static::$token = $token;

        $sessionKeyName = static::getSessionKeyName();
        if (is_string($sessionKeyName) && strlen($sessionKeyName) > 0) {
            Session::set($sessionKeyName, $token);
        }

        return $token;
    }