Autenticação do .NET Core Identity Server 4 Autenticação de identidade do VS


96

Estou tentando entender a maneira adequada de fazer autenticação no ASP.NET Core. Eu olhei vários recursos (muitos dos quais estão desatualizados).

Algumas pessoas fornecem soluções alternativas declarando usar uma solução baseada em nuvem, como o Azure AD, ou usar IdentityServer4 e hospedar meu próprio servidor de token.

Na versão mais antiga do .Net, uma das formas mais simples de autenticação seria criar um princípio personalizado e armazenar dados de usuário de autenticação adicionais dentro dele.

public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
    string FirstName { get; set; }

    string LastName { get; set; }
}

public class CustomPrincipal : ICustomPrincipal
{
    public IIdentity Identity { get; private set; }

    public CustomPrincipal(string username)
    {
        this.Identity = new GenericIdentity(username);
    }

    public bool IsInRole(string role)
    {
        return Identity != null && Identity.IsAuthenticated && 
           !string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName { get { return FirstName + " " + LastName; } }
}

public class CustomPrincipalSerializedModel
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

Em seguida, você seria serializar seus dados em um cookie e devolvê-lo ao cliente.

public void CreateAuthenticationTicket(string username) {     

    var authUser = Repository.Find(u => u.Username == username);  
    CustomPrincipalSerializedModel serializeModel = new CustomPrincipalSerializedModel();

    serializeModel.FirstName = authUser.FirstName;
    serializeModel.LastName = authUser.LastName;
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    string userData = serializer.Serialize(serializeModel);

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
    1,username,DateTime.Now,DateTime.Now.AddHours(8),false,userData);
    string encTicket = FormsAuthentication.Encrypt(authTicket);
    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
    Response.Cookies.Add(faCookie);
}

Minhas perguntas são:

  1. Como posso autenticar da mesma forma que fazia nas versões anteriores do .Net? O modo antigo ainda funciona ou existe uma versão mais recente.

  2. Quais são os prós e os contras de usar seus próprios versos de servidor de token criando seu próprio princípio personalizado?

  3. Ao usar uma solução baseada em nuvem ou um servidor Token separado, como você integraria isso ao seu aplicativo atual, se eu ainda precisaria de uma tabela de usuários em meu aplicativo, como você associaria os dois?

  4. Sendo que existem tantas soluções diferentes, como posso criar um aplicativo empresarial, para permitir Login através do Gmail / Facebook enquanto ainda posso expandir para outros SSO's

  5. Quais são algumas implementações simples dessas tecnologias?

Esta questão é muito ampla e também altamente baseada em opiniões. Existem muitas respostas possíveis ou boas respostas seriam muito longas para este formato. Adicione detalhes para restringir o conjunto de respostas ou para isolar um problema que pode ser respondido em alguns parágrafos. Muitas boas perguntas geram certo grau de opinião com base na experiência de especialistas, mas as respostas a essa pergunta tendem a ser quase inteiramente baseadas em opiniões, ao invés de fatos, referências ou conhecimentos específicos.
Nkosi

@Nkosi desculpe a frase foi assim. Esclareci isso para ser mais específico
johnny 5 de

Respostas:


149

TL; DR

IdentityServer = criptografia de token e serviços de validação via OAuth 2.0 / OpenId-Connect

Identidade ASP.NET = estratégia de gerenciamento de identidade atual em ASP.NET

Como posso autenticar da mesma forma que fazia nas versões anteriores do .Net? O modo antigo ainda funciona ou existe uma versão mais recente.

Não vejo razão para você não conseguir fazer o método antigo no ASP.NET Core, mas, em geral, essa estratégia foi substituída pela Identidade ASP.NET, e a Identidade ASP.NET está viva e bem no ASP.NET Core.

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity

A identidade ASP.NET usa um armazenamento de apoio como o SQL Server para armazenar informações do usuário, como nome de usuário, senha (hash), e-mail, telefone e pode ser facilmente estendido para armazenar o nome, o sobrenome ou qualquer outra coisa. Portanto, não há realmente nenhuma razão para criptografar as informações do usuário em um cookie e passá-las de um cliente para o outro. Ele oferece suporte a noções como declarações de usuário, tokens de usuário, funções de usuário e logins externos. Aqui estão as entidades na identidade ASP.NET:

  • AspNetUsers
  • AspNetUserRoles
  • AspNetUserClaims
  • AspNetUserLogins (para vincular provedores de identidade externos, como Google, AAD)
  • AspNetUserTokens (para armazenar coisas como access_tokens e refresh_tokens acumulados pelo usuário)

Quais são os prós e os contras de usar seus próprios versos de servidor de token criando seu próprio princípio personalizado?

Um servidor de token seria um sistema que gera uma estrutura de dados simples contendo informações de autorização e / ou autenticação. A autorização geralmente leva o for de um token denominado access_token . Essas seriam as "chaves da casa", por assim dizer, permitindo que você passasse pela porta e entre na residência de um recurso protegido, geralmente uma API da web. Para autenticação, o id_tokencontém um identificador exclusivo para um usuário / pessoa. Embora seja comum colocar esse identificador no access_token, agora existe um protocolo dedicado para fazer isso: OpenID-Connect .

A razão para ter seu próprio Security Token Service (STS), seria proteger seus ativos de informação, via criptografia, e controlar quais clientes (aplicativos) podem acessar esses recursos. Além disso, os padrões para controles de identidade agora existem nas especificações OpenID-Connect. IdentityServer é um exemplo de servidor de autorização OAuth 2.0 combinado com um servidor de autenticação OpenID-Connect.

Mas nada disso é necessário se você quiser apenas uma tabela de usuário em seu aplicativo. Você não precisa de um servidor de token - apenas use a identidade ASP.NET. A identidade ASP.NET mapeia seu usuário para um objeto ClaimsIdentity no servidor - sem necessidade de uma classe IPrincipal personalizada.

Ao usar uma solução baseada em nuvem ou um servidor Token separado, como você integraria isso ao seu aplicativo atual, se eu ainda precisaria de uma tabela de usuários em meu aplicativo, como você associaria os dois?

Veja estes tutoriais para integrar soluções de identidade separadas com um aplicativo: https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html https://auth0.com/docs/quickstart/webapp/aspnet-core

No mínimo, você precisaria de uma tabela de duas colunas mapeando o nome de usuário para o identificador de usuário do provedor externo. Isso é o que a tabela AspNetUserLogins faz na identidade do ASP.NET. As linhas dessa tabela, entretanto, dependem de ser um registro do usuário em AspNetUsers.

ASP.NET Identity oferece suporte a provedores externos como Google, Microsoft, Facebook, qualquer provedor OpenID-Connect, Azure AD já estão lá. (Google e Microsoft já implementaram o protocolo OpenID-Connect para que você também não precise de seus pacotes de integração personalizados, como este , por exemplo). Além disso, o ADFS ainda não está disponível no ASP.NET Core Identity.

Consulte este documento para começar a trabalhar com provedores externos na identidade ASP.NET:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/

Sendo que existem tantas soluções diferentes, como posso criar um aplicativo empresarial, para permitir Login através do Gmail / Facebook enquanto ainda posso expandir para outros SSO's

Conforme explicado acima, a identidade do ASP.NET já faz isso. É bastante fácil criar uma tabela de "Provedores externos" e os dados direcionam seu processo de login externo. Portanto, quando um novo "SSO" surgir, basta adicionar uma nova linha com as propriedades como o url do provedor, o ID do cliente e o segredo que eles fornecem. A identidade do ASP.NET já tem a IU incorporada aos modelos do Visual Studio, mas consulte Login social para botões mais frios.

Resumo

Se você só precisa de uma tabela de usuários com recursos de entrada de senha e um perfil de usuário, a identidade ASP.NET é perfeita. Não há necessidade de envolver autoridades externas. Mas, se houver muitos aplicativos que precisam acessar muitas apis, uma autoridade independente para proteger e validar a identidade e os tokens de acesso faz sentido. IdentityServer é um bom ajuste, ou veja openiddict-core ou Auth0 para uma solução em nuvem.

Minhas desculpas é que isso não atingiu o alvo ou é muito introdutório. Sinta-se à vontade para interagir para obter o centro do alvo que você está procurando.

Adendo: autenticação de cookie

Para fazer autenticação básica com cookies, siga estas etapas. Mas, que eu saiba, um principal de declarações customizado não é compatível. Para obter o mesmo efeito, utilize a lista de reivindicações do ClaimPrincipalobjeto.

Crie um novo aplicativo da Web ASP.NET Core 1.1 no Visual Studio 2015/2017 escolhendo "Sem autenticação" na caixa de diálogo. Em seguida, adicione o pacote:

Microsoft.AspNetCore.Authentication.Cookies

De acordo com o Configuremétodo em Startup.csvigor isto (antes app.UseMvc):

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "MyCookieMiddlewareInstance",
    LoginPath = new PathString("/Controller/Login/"),
    AutomaticAuthenticate = true,
    AutomaticChallenge = true
});

Em seguida, crie uma interface de usuário de login e poste o formulário html em um método de ação como este:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(String username, String password, String returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // check user's password hash in database
        // retrieve user info

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username),
            new Claim("FirstName", "Alice"),
            new Claim("LastName", "Smith")
        };

        var identity = new ClaimsIdentity(claims, "Password");

        var principal = new ClaimsPrincipal(identity);

        await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal);

        return RedirectToLocal(returnUrl);
    }

    ModelState.AddModelError(String.Empty, "Invalid login attempt.");

    return View();
}

O objeto HttpContext.User deve ter suas declarações personalizadas e podem ser facilmente recuperadas pela coleção List de ClaimPrincipal.

Espero que isso seja suficiente, pois uma solução / projeto completo parece um pouco demais para um post StackOverflow.


1
Por favor, mostre um exemplo de implementação de autenticação no núcleo
johnny 5 de

2
Os documentos do ASP.NET Core mostram o exemplo canônico: docs.microsoft.com/en-us/aspnet/core/security/authentication/… .
travis.js

Se você puder, poste um exemplo simples de autenticação. Sem um link para que as pessoas tenham um recurso para acessar, postarei uma resposta detalhada sobre como configurar o IdentityServer4
johnny 5

Para IdentityServer, ele tem o exemplo que você está procurando: identityserver4.readthedocs.io/en/dev/quickstarts/… ?
travis.js

Para ASP.NET Identity, este não tem o exemplo ou o que você está dizendo está desatualizado? docs.microsoft.com/en-us/aspnet/core/security/authentication/…
travis.js

12

TL; DR

Eu realmente gostaria de mostrar uma postagem completa sobre como implementar corretamente o IdentityServer4, mas tentei ajustar todo o texto, mas estava além do limite do que o StackOverflow aceita, então, em vez disso, corrigirei algumas dicas e coisas que aprendi.

Quais são os benefícios de usar um Token Server vs. Identidade ASP?

Um servidor de tokens tem muitos benefícios, mas não é adequado para todos. Se você estiver implementando uma solução do tipo empresarial, onde deseja que vários clientes possam fazer login, o servidor de token é sua melhor aposta, mas se você está apenas fazendo um site simples que deseja oferecer suporte a logins externos, pode sair com identidade ASP e algum Middleware.

Identity Server 4 dicas

O servidor de identidade 4 está muito bem documentado em comparação com muitos outros frameworks que vi, mas é difícil começar do zero e ver o quadro completo.

Meu primeiro erro foi tentar usar OAuth como autenticação, sim, existem maneiras de fazer isso, mas OAuth é para autorização, não autenticação, se você quiser autenticar use OpenIdConnect (OIDC)

No meu caso, eu queria criar um cliente javascript, que se conecta a uma API da web. Eu olhei várias soluções, mas inicialmente tentei usar o webapi para chamar o Authenticate contra o Identity Server e só faria com que esse token persistisse porque foi verificado no servidor. Esse fluxo pode funcionar potencialmente, mas tem muitas falhas.

Finalmente, o fluxo adequado quando encontrei a amostra do cliente Javascript, obtive o fluxo certo. Seu cliente efetua login e define um token. Em seguida, você faz com que sua API da web consuma o Cliente OIdc, que verificará seu token de acesso no IdentityServer.

Conectando-se a lojas e migrações No início, tive vários conceitos errados sobre migrações. Fiquei com a impressão de que executando uma migração gerou o SQL a partir da dll internamente, em vez de usar o contexto configurado para descobrir como criar o SQL.

Existem duas sintaxes para migrações, sabendo qual delas o seu computador usa é importante:

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

Acho que o parâmetro após a Migração é o nome, por que você precisa de um nome, não tenho certeza, ApplicationDbContexté um DbContext Code-First no qual deseja criar.

As migrações usam um pouco de mágica automática para localizar sua string de conexão de como sua inicialização está configurada, eu apenas assumi que usou uma conexão do Server Explorer.

Se você tiver vários projetos, certifique-se de ter o projeto com o ApplicationDbContext definido como sua inicialização.

Há muitas partes móveis ao implementar autorização e autenticação. Esperançosamente, esta postagem ajuda alguém. A maneira mais fácil de entender completamente as autenticações é separar seus exemplos para juntar tudo e certificar-se de ler a documentação


o nome após a migração de adicionar é a referência relacionada à sua versão / alterações feitas. o mesmo nome será usado para adicionar o script de migração para cima e para baixo.
Jay

@Jay Obrigado por esse esclarecimento
johnny 5 de

O contexto de banco de dados de configuração do servidor de identidade ainda não é tão bom quanto o IdentityDbContext. criar uma implementação customizada é uma dor. Identityserver 4 agora parece não estar muito ativo para lançar novas atualizações após as atualizações .core.
Jay

4

Identidade ASP.NET - esta é a construção de uma forma de autenticar sua aplicação, seja ela Bearer ou Autenticação Básica, ela nos dá o código pronto para realizar o cadastro do usuário, login, mudança de senha e tudo.

Agora, considere que temos 10 aplicativos diferentes e não é viável fazer a mesma coisa em todos os 10 aplicativos. aquela prática muito frágil e muito ruim.

para resolver esse problema, o que podemos fazer é centralizar nossa autenticação e autorização, para que sempre que qualquer alteração não afete todos os nossos 10 aplicativos.

O servidor de identidade oferece a capacidade de fazer o mesmo. podemos criar um aplicativo da web de amostra que é usado apenas como serviço de identidade e validará seu usuário e fornecerá algum token de acesso JWT.


2

Sempre usei a autorização / autenticação integrada de identidade do ASP.NET (e anteriormente de associação), implementei o Auth0 recentemente ( https://auth0.com ) e recomendo isso como outra coisa para tentar.


O exemplo principal do Auth0 .net é muito rápido e simples de implementar, mas usar todos os recursos requer um pouco de trabalho, eu implementei o Auth0 integrando muitos recursos e ele funciona bem, mas como todas essas coisas, suas necessidades existem um pouco de trabalho e alguma frustração.
Mark Redman

Quando eu tiver uma autenticação funcionando bem, postarei uma resposta detalhada sobre ela. Acabei de trabalhar na autenticação na semana passada. E nada é tão direto quanto deveria ser
johnny 5

0

Logins sociais não são difíceis de implementar com o Identity, mas há alguma configuração inicial envolvida e, às vezes, as etapas que você encontra on-line nos documentos não são idênticas, geralmente você pode encontrar ajuda para isso na seção de desenvolvedores da plataforma que está tentando configurar os logins sociais para. Identidade é a substituição da antiga funcionalidade de associação encontrada em versões legadas da estrutura .net. O que eu achei surpreendente é que casos de uso de ponta, como passar um token jwt que você já tem para uma API da Web, não são abordados em nenhum lugar nos exemplos online mesmo na visão plural, tenho certeza de que você não precisa de sua própria autoridade de token para fazer isso, mas não encontrei um único exemplo sobre como transmitir dados em um get ou post que não esteja lidando com um servidor auto-hospedado.


talvez você esteja atrás disso docs.identityserver.io/en/release/quickstarts/…
Jay
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.