    def add_client(
        self,
        client_id,
        client_secret,
        redirect_uri,
        allowed_scopes=None,
        description='',
    ):
        """Add a client

        hash its client_secret before putting it in the database.
        """
        # Update client if it already exists, else create it
        # Sqlalchemy doesn't have a good db agnostic UPSERT,
        # so we do this manually. It's protected inside a
        # transaction, so should fail if there are multiple
        # rows with the same identifier.
        orm_client = (
            self.db.query(orm.OAuthClient).filter_by(identifier=client_id).one_or_none()
        )
        if orm_client is None:
            orm_client = orm.OAuthClient(
                identifier=client_id,
            )
            self.db.add(orm_client)
            app_log.info(f'Creating oauth client {client_id}')
        else:
            app_log.info(f'Updating oauth client {client_id}')
        if allowed_scopes == None:
            allowed_scopes = []
        orm_client.secret = hash_token(client_secret) if client_secret else ""
        orm_client.redirect_uri = redirect_uri
        orm_client.description = description or client_id
        orm_client.allowed_scopes = list(allowed_scopes)
        self.db.commit()
        return orm_client
Add a client

hash its client_secret before putting it in the database.
jupyterhub/oauth/provider.py