Fluxo de logon único usando JWT para autenticação de domínio cruzado

112

Há muitas informações na web sobre o uso de JWT ( Json Web Token) para autenticação. Mas ainda não encontrei uma explicação clara de como deve ser o fluxo ao usar tokens JWT para uma solução de logon único em um ambiente de vários domínios .

Trabalho para uma empresa que tem muitos sites em hosts diferentes. Vamos usar example1.com e example2.com . Precisamos de uma solução de logon único, o que significa que se um usuário se autentica em example1.com , queremos que ele também seja autenticado em example2.com automaticamente.

Usando o fluxo OpenId Connect , entendo que o usuário que deseja autenticar em example1.com primeiro será redirecionado para o servidor de autenticação (ou OP: "Provedor OpenId"). O usuário é autenticado nesse servidor, que o redireciona de volta ao site example1.com original com um token JWT assinado. (Eu entendo que há outro fluxo que retorna um token intermediário que pode ser trocado pelo token JWT real mais tarde, mas não acho que isso seja necessário para nós) ...

Agora o usuário está de volta a example1.com e autenticado! Ele pode fazer solicitações, passando o token JWT em um Authenticationcabeçalho e o servidor é capaz de verificar o JWT assinado e, portanto, é capaz de identificar o usuário. Agradável!

Primeira pergunta :

Como o token JWT deve ser armazenado no cliente? Novamente, há muitas informações sobre isso, e as pessoas parecem concordar que usar Web Storageé o caminho a seguir, e não o bom e velho cookies. Queremos que o JWT seja persistente entre as reinicializações do navegador, então vamos usar Local Storage, não Session Storage...

Agora o usuário pode reiniciar seu navegador e ainda será autenticado em example1.com , contanto que o token JWT não tenha expirado!

Além disso, se example1.com precisa fazer uma solicitação Ajax para outro de nossos domínios, entendo que a configuração do CORS permitiria isso. Mas nosso principal caso de uso não são as solicitações entre domínios, mas sim uma solução de logon único !

Portanto, a questão principal:

Agora, qual deve ser o fluxo, se o usuário for para example2.com e quisermos que ele seja autenticado, usando o token JWT que ele já possui? Local Storagenão parece permitir o acesso entre domínios, portanto, neste ponto, o navegador não consegue ler o token JWT para fazer solicitações a example2.com !

Devemos :

  • O usuário será redirecionado para o servidor de autenticação novamente? Quando o usuário autenticou para example1.com , o servidor de autenticação pode ter definido um cookie no usuário para que esta nova solicitação de autenticação para example2.com pudesse usar esse cookie para ver se o usuário já está autenticado e imediatamente redirecioná-lo de volta para example2.com com o mesmo token JWT?
  • Ou pode o navegador, em example2.com , acessar o token JWT sem ter que ir para o servidor de autenticação novamente? Vejo que existem soluções de armazenamento cruzado , mas essas são amplamente utilizadas? Eles são a solução sugerida para um ambiente SSO de domínio cruzado?

Não queremos nada extravagante, ficaríamos felizes com a solução mais usada!

eletrotipo
fonte

Respostas:

28

O usuário deve ser redirecionado para o servidor de autenticação novamente e obter um novo token (JWT), especificamente direcionado para example2.com. É assim que o OpenID Connect e qualquer outro protocolo SSO federado entre domínios funcionam.

Hans Z.
fonte
15
Mas sem que o usuário tenha que reenviar as credenciais de autenticação (nome de usuário / senha por exemplo), pois é SSO, certo? Então, como isso é feito? O servidor de autenticação deve definir um cookie padrão para o usuário na primeira vez, para que possa autenticá-lo automaticamente quando esse usuário voltar de um novo domínio?
eletrótipo
7
Mas e se o usuário configurou o navegador para bloquear todos os cookies?
Christiaan Westerbeek,
1
Eu acho que um aviso deve ser colocado sobre os cookies de que "o site pode não funcionar corretamente se o seu navegador bloquear os cookies"
AnBisw
o signon único não significa necessariamente que o usuário tem uma sessão em andamento rastreada por um cookie: sua característica definidora é que se reutiliza as mesmas credenciais no mesmo provedor de identidade para obter acesso a diferentes aplicativos de terceiros, ou seja, nenhum cookie é necessário, basta reutilizar as mesmas creds
Hans Z.
35

Redirecionar o usuário para o serviço de autenticação central quando o usuário não está conectado para solicitar credenciais e emitir um novo token de autenticação é o cenário comum em sistemas de logon único usando protocolos conhecidos como oauth2 ou OpenId Connect

No entanto, quando esse esquema é usado entre domínios, a principal desvantagem é que o usuário será redirecionado e autenticado cada vez que navegar para outro domínio devido à política de mesma origem : o token de acesso não pode ser compartilhado entre os domínios ( example2.comnão pode acessar os dados de example1.com), então o domínio de destino tratará o usuário como não autenticado, redirecionando-o para o serviço SSO central.

Para evitar que o serviço de autenticação solicite novamente credenciais, é comum ter um cookie de sessão (não um token de acesso), mas existe uma técnica para compartilhar dados entre domínios usando o armazenamento local / cookies do navegador e um iframe apontando para um domínio intermediário sso.example.com

  1. Para autenticar o usuário no example1.com, redirecione-o para o servidor de autenticação no sso.example.com, emita um JWT após a autenticação e armazene-o no localStorage deste domínio. Depois disso, redirecione o usuário para o domínio de origem example1.com

  2. Crie um iframe example2.comapontando para sso.example.com. O iframe em sso.example.com lê o token JWT e envia uma mensagem para a página pai

  3. A página pai recebe a mensagem e obtém o token anexado continuando com o fluxo SSO

Não há problema com a política de mesma origem porque sso.example.comtem acesso ao seu localStorage e a comunicação entre o iframe e a página pai é permitida se os domínios de origem e de destino se reconhecerem (consulte http://blog.teamtreehouse.com/cross-domain- messaging-with-postmessage )

Para simplificar o desenvolvimento, lançamos recentemente um SSO de domínio cruzado com JWT em https://github.com/Aralink/ssojwt

Este método é perfeitamente compatível com fluxos SSO. É apenas uma forma de compartilhar o token de autenticação sem redirecionamentos e evitar log-ins desnecessários quando os domínios são federados

pedrofb
fonte
3
Além de essa solução não aderir a um padrão, geralmente no SSO entre domínios, um cruza os limites administrativos e, nesse caso, usar o mesmo JWT para ambos os domínios abriria a possibilidade de um proprietário de aplicativo em um domínio representar o usuário no outro domínio
Hans Z.
6
Obrigado @HansZ. Na verdade, implementamos essa solução para ter uma única administração de vários domínios com dezenas de aplicativos e os mesmos usuários. A operação é semelhante ao sistema do Google (relativamente falando)
pedrofb
2

Não tenho certeza se isso responde à sua pergunta, mas se seu objetivo principal é o logon único, acho que um proxy reverso simples resolveria seu problema (pelo menos o de armazenamento entre domínios).

Então, example1.com example2.com

se tornaria algo como

example.com/example1

example.com/example2

(E do lado do usuário, isso geralmente é mais limpo)

Se isso não for uma opção, você pode ter que configurar para que quando um usuário autenticar em 1 domínio, ele use AJAX / iframes ocultos para criar uma autenticação com os outros domínios também (enviando um token 1 vez via url se você precisar )

e se ISSO não for uma opção, talvez você precise recorrer ao nome de usuário + pin, pois os navegadores estão ficando mais rígidos sobre a interação entre domínios.

Tezra
fonte