Mapeamento de claims do JWT para um Usuário Discourse via plugin de login

Estive tentando encontrar um plugin SSO que me permita aproveitar as declarações vindas do meu IdP para meus Usuários do Discourse.

No plugin OIDC, você está praticamente preso ao endpoint userinfo. Isso não é ruim, mas eu estava tentando usar outras informações do nosso identity store e o resultado do userinfo não pode ser ajustado. Eu tentei forçar o plugin OIDC a usar o id_token_info para fabricar o usuário, mas sem sucesso.

Voltei para o plugin oauth, mas superficialmente ele parece ter a mesma restrição básica, que é depender de informações do usuário de um endpoint específico. Estou trabalhando para ver se consigo encontrar um que retorne o conteúdo das declarações JWT, mas esse não é realmente um caso de uso normal, então não estou esperando muito.

Originalmente, pensei que os “callback userinfo paths” no oauth basic pudessem ser usados para mapear as declarações para o Usuário, mas sempre pareço obter nulos na resposta e falha na inserção. Posso decodificar o token do IdP e ver as declarações corretas e, neste caso, na raiz do JSON, como iss, exp, etc., mas não consigo conectá-los ao lado ActiveRecord.

Estou olhando para jwt, mas ele não parece ter o mapeamento de declarações para o usuário. Basicamente, se você obtiver um 200, está tudo bem, o que também não era o que eu estava procurando.

Também encontrei omniauth-jwt](GitHub - discourse/discourse-omniauth-jwt: An OmniAuth strategy that uses JSON Web Token for Single Sign-On), que parece mais próximo do meu objetivo, embora não pareça ser um plugin nem ativamente mantido. Algo que talvez eu pudesse consertar, mas é um bocado maior do que eu esperava morder.

Alguém pode me indicar uma direção para um plugin atualmente mantido para mapear declarações JWT para um Usuário ou onde eu possa estar errando com um dos plugins existentes?

Não tenho ideia, mas o que eu faria seria pegar GitHub - discourse/all-the-plugins e usar grep para OmniAuth. Isso lhe dará um monte de plugins que usam Isso lhe dá GitHub - discourse/discourse-jwt: Discourse Auth support for JSON Web Tokens (JWT), que pode ser o que você está procurando.

Sim, já passei por esse.

A menos que eu esteja extra lento hoje, ele cobre apenas autenticação com atributos fixos. Nenhuma maneira de fazer um mapeamento de declaração que eu pudesse encontrar. Se eu fosse fazer um fork de algo, provavelmente seria por aí que eu começaria, mas queria ter certeza de que não estava perdendo algo óbvio por aí.

1 curtida

E para adicionar um pouco mais de contexto para quem encontrar este tópico.

O OAuth básico parece suportar apenas a obtenção de atributos de um endpoint de dados de usuário definido e não suporta o mapeamento de declarações JWT. Portanto, é semelhante ao plugin OIDC, mas em vez da localização do userinfo fornecida pelo documento de descoberta, você pode direcionar qualquer endpoint JSON e, em seguida, mapear por caminho. Adicionando as configurações para incluir autenticação no cabeçalho, você pode acessar locais como https://graph.microsoft.com/v1.0/me, que usamos para OAuth baseado em Entra.

Agora, o Entra ID oferece alguma extensibilidade para objetos principais, mas não é tão fácil quanto adicionar uma declaração opcional e seria uma mudança global, pelo que vejo. Portanto, não tenho certeza se é uma opção real para nós. Dando um passo ainda maior no caminho de maturidade e apenas usando o plugin JWT parece ser o único caminho, mas exigiria algum trabalho de PR para adicionar suporte ao mapeamento de declarações. Basicamente, da mesma forma que o oauth2-basic existente permite personalizar o mapeamento do campo Discourse para um atributo JSON, ele precisaria permitir mais personalização do campo para declarações JWT.

Agora, esse é um caminho para nós, mas encontrei um problema diferente que acho que o impede completamente.

Depois de fazer o oauth2-basic funcionar, ele solicita um novo usuário e vê que já existe um usuário usando o e-mail do uso existente do plugin OIDC. Mesmo que compartilhem o mesmo atributo de e-mail, acho que ele não pode mudar de provedor para o mesmo usuário Discourse. Fazer com que todos comecem do zero não é uma opção real e, embora eu provavelmente pudesse hackear uma migração de um registro de provedor oauth em user_associated_accounts de um provedor oidc, sinto que estou apenas pedindo problemas. Portanto, mesmo que o JWT tivesse o suporte de mapeamento de declarações, todos os Usuários existentes estão fixados no provedor OIDC sem alguma manipulação do banco de dados ou a criação de um manipulador de “usuário existente” para permitir a alteração da conta associada, parece que você está preso.

Isso é estranho. Deveria corresponder ao endereço de e-mail e conectar-se à mesma conta, ao que parece. Os logins OAuth funcionam dessa maneira.

Eu esperava que eles se conectassem, permitindo mais de um registro user_associated por usuário do Discourse (por provider_id) ou um prompt de “vinculação” para permitir a troca de um provedor para um novo provedor. No entanto, em meus testes, não foi o caso e apenas observa que o e-mail está em uso e solicita a criação de um novo Usuário.

Se eu estivesse usando o mesmo plugin, tenho certeza de que seria tranquilo, mas neste caso, são IDs de provedor exclusivos, cada um com seus próprios metadados.

1 curtida