    def is_authorized(self, handler, user, action, resource):
        """
        Return whether the authenticated user has permission to perform `action` on `resource`.

        Currently: action and resource are ignored,
        and only the `access:servers` scope is checked.

        This method can be overridden (in combination with custom scopes) to implement granular permissions,
        such as read-only access or access to subsets of the server.
        """

        # This check for access scopes is redundant
        # with the IdentityProvider above,
        # but better to be redundant than allow unauthorized actions.
        # If we remove a redundant check,
        # it should be the one in the identity provider,
        # not this one.
        have_scopes = self.hub_auth.check_scopes(
            self.hub_auth.oauth_scopes, user.hub_user
        )
        self.log.debug(
            f"{user.username} has permissions {have_scopes} required to {action} on {resource}"
        )
        return bool(have_scopes)
Return whether the authenticated user has permission to perform `action` on `resource`.

Currently: action and resource are ignored,
and only the `access:servers` scope is checked.

This method can be overridden (in combination with custom scopes) to implement granular permissions,
such as read-only access or access to subsets of the server.
jupyterhub/singleuser/extension.py