Partilhar via


Uso de provedores OAuth com o MVC 4

por Tom FitzMacken

Este tutorial mostra como criar um aplicativo Web ASP.NET MVC 4 que permite que os usuários façam logon com credenciais de um provedor externo, como Facebook, Twitter, Microsoft ou Google, e, em seguida, integrem algumas das funcionalidades desses provedores em seu aplicativo Web. Para simplificar, este tutorial se concentra em trabalhar com credenciais do Facebook.

Para usar credenciais externas em um aplicativo Web ASP.NET MVC 5, confira Criar um aplicativo MVC 5 ASP.NET com Facebook e Google OAuth2 e Logon openID.

Habilitar essas credenciais em seus sites oferece uma vantagem significativa porque milhões de usuários já têm contas com esses provedores externos. Esses usuários podem estar mais inclinados a se inscrever em seu site se não precisarem criar e lembrar de um novo conjunto de credenciais. Além disso, depois que um usuário fizer logon por meio de um desses provedores, você poderá incorporar operações sociais do provedor.

O que você criará

Há duas metas main neste tutorial:

  1. Habilite um usuário para fazer logon com credenciais de um provedor OAuth.
  2. Recupere as informações da conta do provedor e integre essas informações ao registro da conta do seu site.

Embora os exemplos neste tutorial se concentrem em usar o Facebook como provedor de autenticação, você pode modificar o código para usar qualquer um dos provedores. As etapas para implementar qualquer provedor são muito semelhantes às etapas que você verá neste tutorial. Você só observará diferenças significativas ao fazer chamadas diretas para o conjunto de API do provedor.

Pré-requisitos

Ou

Além disso, este tópico pressupõe que você tenha conhecimento básico sobre ASP.NET MVC e Visual Studio. Se você precisar de uma introdução ao ASP.NET MVC 4, consulte Introdução ao ASP.NET MVC 4.

Criar o projeto

No Visual Studio, crie um novo aplicativo Web ASP.NET MVC 4 e nomeie-o como "OAuthMVC". Você pode direcionar .NET Framework 4.5 ou 4.

criar projeto

Na janela Novo projeto ASP.NET MVC 4, selecione Aplicativo da Internet e deixe Razor como o mecanismo de exibição.

selecione Aplicativo da Internet

Habilitar um provedor

Quando você cria um aplicativo Web MVC 4 com o modelo aplicativo da Internet, o projeto é criado com um arquivo chamado AuthConfig.cs na pasta App_Start.

Arquivo AuthConfig

O arquivo AuthConfig contém código para registrar clientes para provedores de autenticação externa. Por padrão, esse código é comentado, portanto, nenhum dos provedores externos está habilitado.

public static class AuthConfig
{
    public static void RegisterAuth()
    {
        // To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, and Twitter,
        // you must update this site. For more information visit https://go.microsoft.com/fwlink/?LinkID=252166

        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");

        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");

        //OAuthWebSecurity.RegisterFacebookClient(
        //    appId: "",
        //    appSecret: "");

        //OAuthWebSecurity.RegisterGoogleClient();
    }
}

Você deve cancelar o comentário desse código para usar o cliente de autenticação externa. Você cancela o comentário apenas dos provedores que deseja incluir em seu site. Para este tutorial, você habilitará apenas as credenciais do Facebook.

public static class AuthConfig
{
    public static void RegisterAuth()
    {
        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");

        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");

        OAuthWebSecurity.RegisterFacebookClient(
            appId: "",
            appSecret: "");

        //OAuthWebSecurity.RegisterGoogleClient();        
    }
}

Observe no exemplo acima que o método inclui cadeias de caracteres vazias para os parâmetros de registro. Se você tentar executar o aplicativo agora, o aplicativo gerará uma exceção de argumento porque cadeias de caracteres vazias não são permitidas para os parâmetros. Para fornecer valores válidos, você deve registrar seu site com os provedores externos, conforme mostrado na próxima seção.

Registrando-se com um provedor externo

Para autenticar usuários com credenciais de um provedor externo, você deve registrar seu site com o provedor. Ao registrar seu site, você receberá os parâmetros (como chave ou ID e segredo) a serem incluídos ao registrar o cliente. Você deve ter uma conta com os provedores que deseja usar.

Este tutorial não mostra todas as etapas que você deve executar para se registrar com esses provedores. Normalmente, as etapas não são difíceis. Para registrar seu site com êxito, siga as instruções fornecidas nesses sites. Para começar a registrar seu site, consulte o site do desenvolvedor para:

Ao registrar seu site no Facebook, você pode fornecer "localhost" para o domínio do site e "http://localhost/" para a URL, conforme mostrado na imagem abaixo. O uso do localhost funciona com a maioria dos provedores, mas atualmente não funciona com o provedor da Microsoft. Para o provedor da Microsoft, você deve incluir uma URL válida do site.

registrar site

Na imagem anterior, os valores da ID do aplicativo, do segredo do aplicativo e do email de contato foram removidos. Quando você realmente registrar seu site, esses valores estarão presentes. Você desejará observar os valores da ID do aplicativo e do segredo do aplicativo, pois os adicionará ao seu aplicativo.

Criando usuários de teste

Se você não se importar em usar uma conta existente do Facebook para testar seu site, poderá ignorar esta seção.

Você pode criar facilmente usuários de teste para seu aplicativo na página de gerenciamento de aplicativos do Facebook. Você pode usar essas contas de teste para fazer logon em seu site. Você cria usuários de teste clicando no link Funções no painel de navegação esquerdo e clicando no link Criar .

criar usuários de teste

O site do Facebook cria automaticamente o número de contas de teste solicitadas.

Adicionando a ID do aplicativo e o segredo do provedor

Agora que você recebeu a ID e o segredo do Facebook, volte para o arquivo AuthConfig e adicione-os como os valores de parâmetro. Os valores mostrados abaixo não são valores reais.

public static class AuthConfig
{
    public static void RegisterAuth()
    {
        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");

        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");

        //OAuthWebSecurity.RegisterFacebookClient(
        //    appId: "",
        //    appSecret: "");

        //OAuthWebSecurity.RegisterGoogleClient();
    }
}

Fazer logon com credenciais externas

Isso é tudo o que você precisa fazer para habilitar credenciais externas em seu site. Execute seu aplicativo e clique no link de logon no canto superior direito. O modelo reconhece automaticamente que você registrou o Facebook como um provedor e inclui um botão para o provedor. Se você registrar vários provedores, um botão para cada um será incluído automaticamente.

logon externo

Este tutorial não aborda como personalizar os botões de logon para os provedores externos. Para obter essas informações, consulte Personalizando a interface do usuário de logon ao usar OAuth/OpenID.

Clique no botão facebook para fazer logon com as credenciais do Facebook. Ao selecionar um dos provedores externos, você será redirecionado para esse site e solicitado por esse serviço a fazer logon.

A imagem a seguir mostra a tela de logon do Facebook. Ele observa que você está usando sua conta do Facebook para fazer logon em um site chamado oauthmvcexample.

autenticação do Facebook

Depois de fazer logon com as credenciais do Facebook, uma página informa ao usuário que o site terá acesso a informações básicas.

permissão de solicitação

Depois de selecionar Ir para o Aplicativo, o usuário deve se registrar no site. A imagem a seguir mostra a página de registro depois que um usuário fez logon com as credenciais do Facebook. Normalmente, o nome de usuário é preenchido previamente com um nome do provedor.

A captura de tela mostra uma página Registrar na qual você pode associar sua conta do Facebook a este aplicativo.

Clique em Registrar para concluir o registro. Feche o navegador.

Você pode ver que a nova conta foi adicionada ao banco de dados. No servidor Explorer, abra o banco de dados DefaultConnection e abra a pasta Tabelas.

tabelas de banco de dados

Clique com o botão direito do mouse na tabela UserProfile e selecioneMostrar Dados da Tabela.

mostrar dados

Você verá a nova conta que adicionou. Examine os dados em webpage_OAuthMembership tabela. Você verá mais dados relacionados ao provedor externo para a conta que acabou de adicionar.

Se você quiser habilitar apenas a autenticação externa, você está pronto. No entanto, você pode integrar ainda mais as informações do provedor ao novo processo de registro de usuário, conforme mostrado nas seções a seguir.

Criar modelos para informações adicionais do usuário

Como você observou nas seções anteriores, não é necessário recuperar nenhuma informação adicional para que o registro de conta interno funcione. No entanto, a maioria dos provedores externos transmite informações adicionais sobre o usuário. As seções a seguir mostram como reter essas informações e salvá-la em um banco de dados. Especificamente, você manterá valores para o nome completo do usuário, o URI da página da Web pessoal do usuário e um valor que indica se o Facebook verificou a conta.

Você usará Migrações do Code First para adicionar uma tabela para armazenar informações adicionais do usuário. Você está adicionando a tabela a um banco de dados existente, portanto, primeiro você precisará criar um instantâneo do banco de dados atual. Ao criar um instantâneo do banco de dados atual, você pode criar posteriormente uma migração que contenha apenas a nova tabela. Para criar um instantâneo do banco de dados atual:

  1. Abrir o Console do Gerenciador de Pacotes
  2. Executar o comando enable-migrations
  3. Execute o comando add-migration initial –IgnoreChanges
  4. Executar o comando update-database

Agora, você adicionará as novas propriedades. Na pasta Modelos, abra o arquivo AccountModels.cs e localize a classe RegisterExternalLoginModel. A classe RegisterExternalLoginModel contém valores que voltam do provedor de autenticação. Adicione propriedades chamadas FullName e Link, conforme realçado abaixo.

public class RegisterExternalLoginModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    public string ExternalLoginData { get; set; }

    [Display(Name = "Full name")]
    public string FullName { get; set; }

    [Display(Name = "Personal page link")]
    public string Link { get; set; }
}

Também em AccountModels.cs, adicione uma nova classe chamada ExtraUserInformation. Essa classe representa a nova tabela que será criada no banco de dados.

[Table("ExtraUserInformation")]
public class ExternalUserInformation
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public string FullName { get; set; }
    public string Link { get; set; }
    public bool? Verified { get; set; }
}

Na classe UsersContext, adicione o código realçado abaixo para criar uma propriedade DbSet para a nova classe.

public class UsersContext : DbContext
{
    public UsersContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<ExternalUserInformation> ExternalUsers { get; set; }
}

Agora você está pronto para criar a nova tabela. Abra o Console do Gerenciador de Pacotes novamente e desta vez:

  1. Executar o comando add-migration AddExtraUserInformation
  2. Executar o comando update-database

A nova tabela agora existe no banco de dados.

Recuperar os dados adicionais

Há duas maneiras de recuperar dados adicionais do usuário. A primeira maneira é manter os dados do usuário que são passados de volta, por padrão, durante a solicitação de autenticação. A segunda maneira é chamar especificamente a API do provedor e solicitar mais informações. Os valores de FullName e Link são passados automaticamente pelo Facebook. Um valor que indica se o Facebook verificou se a conta foi recuperada por meio de uma chamada à API do Facebook. Primeiro, você preencherá os valores de FullName e Link e, depois, obterá o valor verificado.

Para recuperar os dados adicionais do usuário, abra o arquivo AccountController.cs na pasta Controladores .

Esse arquivo contém a lógica para registrar, registrar e gerenciar contas. Em particular, observe os métodos chamados ExternalLoginCallback e ExternalLoginConfirmation. Nesses métodos, você pode adicionar código para personalizar operações de logon externo para seu aplicativo. A primeira linha do método ExternalLoginCallback contém:

AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
    Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));

Dados adicionais do usuário são passados novamente na propriedade ExtraData do objeto AuthenticationResult que é retornado do método VerifyAuthentication . O cliente do Facebook contém os seguintes valores na propriedade ExtraData :

  • id
  • name
  • link
  • gender
  • accesstoken

Outros provedores terão dados semelhantes, mas ligeiramente diferentes, na propriedade ExtraData.

Se o usuário for novo em seu site, você recuperará alguns dados adicionais e passará esses dados para a exibição de confirmação. O último bloco de código no método será executado somente se o usuário for novo em seu site. Substitua a seguinte linha:

return View("ExternalLoginConfirmation", new RegisterExternalLoginModel 
{ 
    UserName = result.UserName, 
    ExternalLoginData = loginData 
});

Por esta linha:

return View("ExternalLoginConfirmation", new RegisterExternalLoginModel
{
    UserName = result.UserName,
    ExternalLoginData = loginData,
    FullName = result.ExtraData["name"],
    Link = result.ExtraData["link"]
});

Essa alteração inclui apenas valores para as propriedades FullName e Link.

No método ExternalLoginConfirmation , modifique o código conforme realçado abaixo para salvar as informações adicionais do usuário.

if (user == null)
{
    // Insert name into the profile table
    UserProfile newUser = db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
    db.SaveChanges();

    db.ExternalUsers.Add(new ExternalUserInformation 
    { 
        UserId = newUser.UserId, 
        FullName = model.FullName, 
        Link = model.Link 
    });
    db.SaveChanges();

    OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
    OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);

    return RedirectToLocal(returnUrl);
}
else
{
    ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
}

Ajustando a exibição

Os dados de usuário adicionais recuperados do provedor serão exibidos na página de registro.

Na pastaConta de Exibições/, abra ExternalLoginConfirmation.cshtml. Abaixo do campo existente para nome de usuário, adicione campos para FullName, Link e PictureLink.

<li>
    @Html.LabelFor(m => m.FullName)
    @Html.TextBoxFor(m => m.FullName)
</li>
<li>
    @Html.LabelFor(m => m.Link)
    @Html.TextBoxFor(m => m.Link)
</li>

Agora você está quase pronto para executar o aplicativo e registrar um novo usuário com as informações adicionais salvas. Você deve ter uma conta que ainda não esteja registrada no site. Você pode usar uma conta de teste diferente ou excluir as linhas nas tabelas UserProfile e webpages_OAuthMembership para a conta que deseja reutilizar. Ao excluir essas linhas, você garantirá que a conta seja registrada novamente.

Execute o aplicativo e registre o novo usuário. Observe que desta vez a página de confirmação contém mais valores.

A captura de tela mostra onde você pode inserir um nome de usuário e outras informações depois de associar uma conta do Facebook ao aplicativo.

Depois de concluir o registro, feche o navegador. Procure no banco de dados para observar os novos valores na tabela ExtraUserInformation .

Instalar o pacote NuGet para a API do Facebook

O Facebook fornece uma API que você pode chamar para executar operações. Você pode chamar a API do Facebook direcionando o envio de solicitações HTTP ou instalando um pacote NuGet que facilita o envio dessas solicitações. O uso de um pacote NuGet é mostrado neste tutorial, mas a instalação do pacote NuGet não é essencial. Este tutorial mostra como usar o pacote do SDK do C# do Facebook. Há outros pacotes NuGet que ajudam a chamar a API do Facebook.

Nas janelas Gerenciar Pacotes NuGet , selecione o pacote do SDK do C# do Facebook.

instalar pacote

Você usará o SDK do C# do Facebook para chamar uma operação que exige o token de acesso para o usuário. A próxima seção mostra como obter o token de acesso.

Recuperar token de acesso

A maioria dos provedores externos passa um token de acesso depois que as credenciais do usuário são verificadas. Esse token de acesso é muito importante porque permite que você chame operações que só estão disponíveis para usuários autenticados. Portanto, recuperar e armazenar o token de acesso é essencial quando você deseja fornecer mais funcionalidade.

Dependendo do provedor externo, o token de acesso pode ser válido por apenas um período limitado de tempo. Para garantir que você tenha um token de acesso válido, recupere-o sempre que o usuário fizer logon e armazene-o como um valor de sessão em vez de salvá-lo em um banco de dados.

No método ExternalLoginCallback , o token de acesso também é passado de volta na propriedade ExtraData do objeto AuthenticationResult . Adicione o código realçado a ExternalLoginCallback para salvar o token de acesso no objeto Session . Esse código é executado sempre que o usuário faz logon com uma conta do Facebook.

[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
    AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
        Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
    if (!result.IsSuccessful)
    {
        return RedirectToAction("ExternalLoginFailure");
    }

    if (result.ExtraData.Keys.Contains("accesstoken"))
    {
        Session["facebooktoken"] = result.ExtraData["accesstoken"];
    }

    if (OAuthWebSecurity.Login(
        result.Provider, 
        result.ProviderUserId, 
        createPersistentCookie: false))
    {
        return RedirectToLocal(returnUrl);
    }

    if (User.Identity.IsAuthenticated)
    {
        // If the current user is logged in add the new account
        OAuthWebSecurity.CreateOrUpdateAccount(
            result.Provider,
            result.ProviderUserId, 
            User.Identity.Name);
        return RedirectToLocal(returnUrl);
    }
    else
    {
        // User is new, ask for their desired membership name
        string loginData = OAuthWebSecurity.SerializeProviderUserId(
            result.Provider, 
            result.ProviderUserId);
        ViewBag.ProviderDisplayName =
            OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
        ViewBag.ReturnUrl = returnUrl;
        return View("ExternalLoginConfirmation", new RegisterExternalLoginModel
        {
            UserName = result.UserName,
            ExternalLoginData = loginData,
            FullName = result.ExtraData["name"],
            Link = result.ExtraData["link"]
        });    
    }
}

Embora este exemplo recupere um token de acesso do Facebook, você pode recuperar o token de acesso de qualquer provedor externo por meio da mesma chave chamada "accesstoken".

Logoff

O método LogOff padrão faz logoff do usuário do aplicativo, mas não faz logoff do usuário do provedor externo. Para fazer logoff do usuário do Facebook e impedir que o token persista depois que o usuário tiver feito logoff, você pode adicionar o seguinte código realçado ao método LogOff no AccountController.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    WebSecurity.Logout();
    if (Session["facebooktoken"] != null)
    {
        var fb = new Facebook.FacebookClient();
        string accessToken = Session["facebooktoken"] as string;
        var logoutUrl = fb.GetLogoutUrl(new { access_token = accessToken, next = "http://localhost:39852/" });

        Session.RemoveAll();
        return Redirect(logoutUrl.AbsoluteUri);
    }

    return RedirectToAction("Index", "Home");
}

O valor fornecido no next parâmetro é a URL a ser usada depois que o usuário sair do Facebook. Ao testar em seu computador local, você forneceria o número da porta correto para seu site local. Em produção, você forneceria uma página padrão, como contoso.com.

Recuperar informações do usuário que exigem o token de acesso

Agora que você armazenou o token de acesso e instalou o pacote do SDK do C# do Facebook, você pode usá-los juntos para solicitar informações adicionais do usuário do Facebook. No método ExternalLoginConfirmation , crie uma instância da classe FacebookClient passando o valor do token de acesso. Solicite o valor da propriedade verificada para o usuário autenticado atual. A propriedade verificada indica se o Facebook validou a conta por meio de outros meios, como enviar uma mensagem para um celular. Salve esse valor no banco de dados.

if (user == null)
{
    // Insert name into the profile table
    UserProfile newUser = db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
    db.SaveChanges();

    bool facebookVerified;

    var client = new Facebook.FacebookClient(Session["facebooktoken"].ToString());
    dynamic response = client.Get("me", new { fields = "verified" });
    if (response.ContainsKey("verified"))
    {
        facebookVerified = response["verified"];
    }
    else
    {
        facebookVerified = false;
    }

    db.ExternalUsers.Add(new ExternalUserInformation 
    { 
        UserId = newUser.UserId, 
        FullName = model.FullName, 
        Link = model.Link, 
        Verified = facebookVerified 
    });
    db.SaveChanges();

    OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
    OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);

    return RedirectToLocal(returnUrl);
}

Novamente, você precisará excluir os registros no banco de dados do usuário ou usar uma conta diferente do Facebook.

Execute o aplicativo e registre o novo usuário. Examine a tabela ExtraUserInformation para ver o valor da propriedade Verified.

Conclusão

Neste tutorial, você criou um site integrado ao Facebook para dados de autenticação e registro de usuário. Você aprendeu sobre o comportamento padrão configurado para o aplicativo Web MVC 4 e como personalizar esse comportamento padrão.