We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.

Guilherme • 5 years ago

Boa noite Wellington, os posts estão muito bons. Me surgiu uma divida, é comum incluir roles e permissions em tokens jwt? Achei estranho pq se as permissões do usuário forem alteradas, a aplicação ainda permitirá os mesmos acessos. A alternativa,para esta situação seria fazer a verificação de roles e permissions a cada requisição? existe solução mais elegante?

wellingtonjhn • 5 years ago

Olá Guilherme, desculpe a demora em responder. Fico feliz que tenha gostado dos posts.

Sobre sua dúvida, sim, é muito comum incluir roles no token JWT, as permissions foi algo que eu inventei pra exemplificar o artigo apenas, mas na pratica são roles e claims.

Não é necessário consultar na base de dados as permissões a cada request, isso seria contra o propósito do próprio token JWT, afinal uma das possibilidades dele é que temos as credenciais de acesso contidas diretamente no token.

Caso as permissões sejam alteradas na base de dados realmente o token JWT (se ainda estiver válido) vai continuar com as permissões anteriores. Para resolver esse problema é comum que se use em conjunto o que chamamos de Refresh Token, nesse caso o token JWT fica com um tempo de expiração curto, coisa de alguns minutos apenas, e quando a API receber um token expirado pode tentar automaticamente fazer o Refresh Token e pegar as permissões mais atualizadas. Isso também é usado em outros cenários, por exemplo para evitar que um token JWT com tempo de validade longo caia em mãos erradas (hacker) e seja utilizado indevidamente mesmo que o usuário já tenha feito logout no sistema.

De qualquer forma, não recomendo que você faça isso manualmente. Use um sistema de identidade mais confiável como o Identity Server, pois ele já contém todas essas features integradas e é usado amplamente no mercado mundial, e é open-source.

Espero ter respondido suas dúvidas.

Abraços.

Felipe Oliveira • 5 years ago

Boa tarde.

Post excelente. Somente algumas dúvidas, como eu posso utilizar as roles para alterar a view de acordo com o tipo de usuário logado? Só pode ser feito usando SPA? Como eu posso ler uma claim que carrega a role no token para validar essa ação no front?

Obrigado.

wellingtonjhn • 5 years ago

Olá Felipe, a aplicação SPA não terá acesso as claims diretamente, ela terá apenas o token JWT. O que se pode fazer nesse caso é ler seu conteúdo no front pois é baseado em base64. Outra alternativa é criar um endpoint na API que extraia essa informação e devolva para o front deserializado, sendo sincero não sei qual é a melhor abordagem pois não trabalho muito com frontend.

Talvez esse post te ajude: https://jasonwatmore.com/po...

Já nas views do Razor é possível ler o conteúdo do token pois elas são renderizadas no lado do servidor, seria algo assim:

@((ClaimsIdentity) User.Identity)

... ou você pode criar um método que extraia uma role específica:

public static string GetSpecificClaim(this ClaimsIdentity claimsIdentity, string claimType)
{
var claim = claimsIdentity.Claims.FirstOrDefault(x => x.Type == claimType);

return (claim != null) ? claim.Value : string.Empty;
}

.. e usar na view:

@((ClaimsIdentity) User.Identity).GetSpecificClaim("someclaimtype")

https://docs.microsoft.com/...

Espero ter ajudado.

Abraços.

Felipe Oliveira • 5 years ago

Pesquisando eu vi uma abordagem por rotas, que acho que seria o caminho dos endpoints mencionados, no caso, eu utilizaria o Authorize encaminhando cada role para sua respectiva rota, no caso eu também posso usar por ações específicas.

Eu também poderia usar as claims dessa forma?

wellingtonjhn • 5 years ago

Olá Felipe, a utilização de Authorize em rotas é o mais comum mesmo, no exemplo eu coloquei o Authorize na controller apenas como exemplo, mas funciona nas actions também.

As ações específicas podem ser implementadas com Policies como no artigo.

No final das contas, todas as informações do token JWT são claims e você pode usar qualquer uma delas para autorização, entretanto o mais comum é olhar para as Roles em conjunto com o Authorize ou Policies.

Espero ter respondido.
Abraços.

Felipe Oliveira • 5 years ago

Sim, obrigado.

Somente outra questão, se não for incomodar.

Eu consigo aplicar o mesmo conceito usando o ASP.NET? (Aqui na empresa os sistemas legados usam o ASP.NET como framework, porém, todo conteúdo recente sobre web API e autenticação que encontro usa o Core)

Obrigado.

wellingtonjhn • 5 years ago

Não incomoda, tenho prazer em responder e ajudar no que puder.

No ASP.Net 4.x (.Net "full" Framework) também é possível implementar autenticação JWT e autorização da mesma forma, a única diferença é que não terá as mesmas implementações e "facilidades" que existem no .Net Core como Policies por exemplo, apenas o AuthorizeAttribute que é baseado em Roles. De qualquer forma, você sempre tem a opção de implemetar algo por conta própria baseada nas Claims.

Além disso, existem algumas implementações "não oficiais", mas que funcionam muito bem.

Veja se isso pode te ajudar: https://vladimirgeorgiev.co...

De qualquer forma, para novas implementações recomendo muito que seja utilizado .Net Core pois já é bem estável, maduro e amplamente utilizado pelo mercado em nível mundial. A própria Microsoft já divulgou que continuará suportando o .Net Framework com atualizações "menores" como correção de bugs e segurança, mas novas features serão feitas apenas no .Net Core e no novo .Net 5.

https://devblogs.microsoft....

https://devblogs.microsoft....

Abraços!

Daniel Borges Leal • 6 years ago

Wellington, esse foi o melhor post de autenticação/autorização JWT de .NetCore que eu já encontrei. Parabéns!!!

Ficou uma dúvida. Estou tentando replicar seu exemplo. Criei as tabelas Roles, Permissions, UsersRoles e UsersPermissions (Many to Many). Defini no banco que um determinado usuário tem a role Admin e as permissions ListUser e DeleteUser. Entretanto, quando eu me autentico, ele não reconhece as roles e permissions e o Authorize barra o acesso daquele Usuário ao método.

Como vincular esses valores procedentes do banco de dados às Claims do User Logado???

Muito obrigado pela postagem novamente. Me ajudou bastante.

wellingtonjhn • 6 years ago

Oi Daniel, eu é quem agradeço seu feedback e fico muito feliz que você gostou do artigo e mais ainda em saber que ele te ajudou. =)
Sobre sua dúvida, em um artigo anterior eu mostro como criar o token JWT e incluir as Claims a partir do retorno do banco (no caso não existia banco pois simulei com listas em memória, mas o princípio é o mesmo). Uma vez que você consiga retornar os dados do banco, basta encaminhar o objeto User para a classe JwtService, nela existe o método GetClaimsIdentity onde são criadas as Claims a partir dos dados do User.

https://www.wellingtonjhn.c...

Abraços!

Daniel Borges Leal • 6 years ago

Consegui, muito obrigado!!!

wellingtonjhn • 6 years ago

Show! Qualquer dúvida me avise. Abraços!