Tutorial: Autenticando um usuário no meio de uma sessão

Se você tiver segurança de chat web ativada, você deve configurar um ID de usuário para o cliente no início da sessão como parte do JSON Web Token (JWT) você usa para assinar mensagens. Para os usuários que não são autenticados, este é tipicamente um ID gerado, e não pode ser alterado após a criação do JWT. No entanto, você pode usar uma variável privada para autenticar um usuário posteriormente na sessão.

Com a segurança do chat web ativada, o ID do usuário associado a cada mensagem é baseado na reivindicação sub na carga útil do JWT. Esse valor deve ser configurado no início da sessão, quando o JWT é criado, e não pode ser alterado durante a vida útil da sessão. Para usuários não autenticados (anônimos), você geralmente usaria um ID gerado, salvo em um cookie, para garantir que cada cliente exclusivo seja contado apenas uma vez para finalidades de faturamento.

No entanto, você pode desejar que seus clientes possam se autenticar no meio de uma sessão (por exemplo, para concluir uma ação que atualiza as informações da conta do usuário). Como o ID do usuário gerado no sinistro sub não pode ser alterado, você precisa de outra forma de autenticar o usuário de forma segura. Você pode fazer isso armazenando o ID de usuário autenticado real do cliente como uma variável privada na carga útil do usuário do JWT. (Você poderia armazenar o ID do usuário em uma variável de contexto ordinária, mas isso não seria seguro, pois tais variáveis podem ser modificadas.)

Para obter uma versão de trabalho completa do exemplo descrito neste tutorial, consulte Ativando a segurança para watsonx Assistant bate-papo da web(complexo).

Para uma versão de bate-papo da web com códigos mínimos para ativar a segurança, que não tem cargas úteis criptografadas e mudanças do usuário durante a sessão. Consulte Ativando a segurança para watsonx Assistant bate-papo da web(simples).

Este exemplo neste tutorial, que é baseado em um servidor Express para o Node.js, mostra como iniciar uma sessão com um ID de usuário anônimo e, em seguida, autenticar o usuário durante a sessão.

  1. Crie uma função chamada getOrSetAnonymousID() que gere um ID de usuário anônimo exclusivo para cada cliente e armazene-o em um cookie (ou, se o cookie já existir, utilize o ID do usuário armazenado).

    Use um cookie que dura pelo menos 45 dias. Se você não armazenar o ID do usuário por mais de 30 dias, o mesmo cliente poderá ser contado como vários usuários diferentes durante o mesmo período de faturamento. (Isso ainda pode acontecer se o mesmo usuário excluir o cookie ou usar um navegador diferente.)

function getOrSetAnonymousID(request, response) {
  let anonymousID = request.cookies['ANONYMOUS-USER-ID'];
  if (!anonymousID) {
    anonymousID = `anon-${uuid()}`;
  }

  response.cookie('ANONYMOUS-USER-ID', anonymousID, {
    expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 45), // 45 days.
    httpOnly: true,
  });

  return anonymousID;
}
  1. Na função que você usa para criar um JWT, use o ID anônimo retornado da função getOrSetAnonymousID() como o valor do sinistro sub. Isso configura o valor do ID do usuário que será usado para identificar com exclusividade o cliente para fins de faturamento.

    Além disso, recupere qualquer valor a partir do cookie SESSION_INFO, que utilizaremos para armazenar informações de login autenticadas. Se um valor existir, armazene-o na reivindicação privada user_payload do JWT. (Se o usuário ainda não tiver autenticado, este cookie ainda não existe.)

const jwtContent = {
  sub: anonymousUserID,
  user_payload: {
    name: 'Anonymous',
    custom_user_id: anonymousUserID,
  },
};

if (sessionInfo) {
  jwtContent.user_payload.name = sessionInfo.userName;
  jwtContent.user_payload.custom_user_id = sessionInfo.customUserID;
}
  1. Crie uma função para manipular a autenticação do usuário. No nosso exemplo, estamos usando uma função authenticate() simples que configura um ID de usuário codificado, mas em um aplicativo real o ID do usuário provavelmente seria recuperado de um banco de dados após uma verificação de autenticação segura. Armazene as informações do usuário no cookie SESSION_INFO.
function authenticate(request, response) {

  const userInfo = {
    userName: 'Cade',
    customUserID: 'cade-id',
  };

  response.cookie('SESSION_INFO', JSON.stringify(userInfo), { encode: String });

  response.send('Ok');
}
  1. Quando um usuário efetuar login, ligue para a função authenticate() para armazenar as informações do usuário no cookie SESSION_INFO. Em seguida, ligue para a função createJWT() para regenerar o JWT, usando a sessão atualizada info para preencher o sinistro user_payload.

    Em nosso exemplo, a autenticação é simulada com um simples clique de botão. O mesmo botão também simula o registro de saída excluindo o cookie:

    async function onClick() {
      if (getCookieValue('SESSION_INFO')) {
        document.cookie = 'SESSION_INFO=; Max-Age=0';
      } else {
        await fetch('http://localhost:3001/authenticate');
      }
    
      const result = await fetch('http://localhost:3001/createJWT');
      const newToken = await result.text();
    
      webChatInstance.updateIdentityToken(newToken);
    
      updateUI();
    }
    

    O ID anônimo na solicitação sub continuará sendo usado para rastrear o cliente para propósitos de faturamento, mas agora o ID do usuário real do cliente é armazenado separadamente na carga útil do usuário.

  2. Em suas ações, agora é possível acessar o ID do usuário real do cliente, referenciando a variável de contexto privado user_payload :

${system_integrations.chat.private.user_payload}.custom_user_id

Para o código de trabalho completo, consulte a Segurança Habilitação para watsonx Assistant chat web exemplo.

Se você for obrigado a cumprir os requisitos do GDPR, pode ser necessário que você armazene persistentemente qualquer IDs de usuário anônimos gerados, especialmente para usuários anônimos que posteriormente efetuam o login com credenciais do usuário. Armazenar esses IDs de usuário possibilita que você exclua posteriormente todos os dados associados a um cliente individual se solicitado a fazê-lo.