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 Authentication
cabeç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 Storage
nã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!
fonte
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.com
não pode acessar os dados deexample1.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
Para autenticar o usuário no
example1.com
, redirecione-o para o servidor de autenticação nosso.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.comCrie um iframe
example2.com
apontando parasso.example.com
. O iframe em sso.example.com lê o token JWT e envia uma mensagem para a página paiA 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.com
tem 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
fonte
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.
fonte