.NET 5 Core makes it easy allow users to log in to applications through Facebook. This article shows how to build .NET 5 Core app that enables users to log in using OAuth 2.0 with credentials from an external. This article demonstrates how to build .NET 5 Core app using OAuth 2.0 with external authentication providers. The tutorial Implement social authentication in .NET Core and you can configure your application to use a Facebook social login when you are using ASP.NET Core Identity. Also, learn how to enable the users of your ASP.NET Core website to log in using Facebook using just .NET 5.
To set up external login with Facebook in ASP.NET Core, you will need to do the following:
- Go to the Facebook Developer site (https://developers.facebook.com/) and create a new app.
- In the app dashboard, navigate to the "Settings" tab and click "Add Platform". Select "Web" and enter the URL of your app in the "Site URL" field.
- In your ASP.NET Core app, install Microsoft.AspNetCore.Authentication.Facebook NuGet package.
- In the Startup class, call the AddFacebook method on the AuthenticationBuilder object to configure the Facebook authentication handler. This method takes an Action<FacebookOptions> that you can use to set options such as the app ID and app secret.
- In the app's Razor pages or controllers, use the [Authorize] attribute on actions that require authentication.
- When a user tries to authenticate, they will be redirected to the Facebook login page. After they log in, they will be redirected back to your app and authenticated.
Here is an example of how to set up Facebook authentication in the ConfigureServices method of the Startup class:
services.AddAuthentication().AddFacebook(facebookOptions =>
{
facebookOptions.AppId = Configuration["Authentication:Facebook:AppId"];
facebookOptions.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
});
To log in from Facebook into an application first you need to have a Facebook app, then use the following procedure.
Step 1.
Registering your website with Facebook.
Click on the link: https://developers.facebook.com/apps.
- Login with your Facebook.
- If you are not registered as a Developer then click on "Register as Developer", then provide all the requested information.
- After registering you will find a button named Create App on your right-hand site, click on this button. After clicking on this button it will open a window like the following image.
Now you need to provide an App Name and an App Namespace for this app.Select an app type from list of apps like as given above image.
Step 2
After selected Select an app type then click on the continue button to proceed, a window will appear as in the following:
Step 3
Now that you have created your app, you are greeted with a list of products that you can add to your App. Click on Set Up on the Facebook Login card like as given image below.
After that a QuickStart wizard will be show greeted with a list launched asking you to select a platform for the app. Skip this wizard and click on Facebook Login > Settings from the navigation menu on the left like as given image below.
This will take you to the Client OAuth Settings page. In the Valid OAuth redirect URIs field enter the base URL of your application with /signin-facebook appended to it. For this article, the URL will be http://localhost:45474/signin-facebook. Click on Save Changes like as given below.
Now click on Settings > Basic on the navigation menu. You will see the App ID and App Secret values for the Facebook app we have just created. Click on the show button inside the App secret field to see the value. Take note of both values as we will need them to configure Facebook authentication in our web app.
Step 4.
Integrating Facebook Auth in .NET 5.0
Now I am going to integrate facebook authentication in our .NET 5.0 application so first create new project like as given step by.
- Open visual studio 2019
- Create a new project.
- Select ASP.NET Core Web Application and Next.
- Provide a Project name and confirm or change the Location. Select Create.
- Select the latest version of ASP.NET Core in the drop-down (.NET Core 5.0) and then select Web Application.
- Under Authentication, select Change and set the authentication to Individual User Accounts. Select OK.
- In the Create a new ASP.NET Core Web Application window, select Create.
The first install Authentication Facebook package from Nuget package in .NET 5 application. Open Package Manager Console in Visual Studio and run the following command:
Install-Package Microsoft.AspNetCore.Authentication.Facebook
Install package more details https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.Facebook
or
You can also install Authentication.Facebook package like as give below.
Modifying Login action and Handling Callback
The first is a FacebookLogin method which will request authentication and send the user of to Facebook. This will route to /signin-facebook, which is what we set up as the LoginPath in our AddCookie method inside Startup.cs class.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Security.Claims;
using System.Threading.Tasks;
namespace FecebookAuth
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(
options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
//services.AddIdentity<ApplicationUser,Role>().AddEntityFrameworkStores<DbContext>();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.AddAuthentication()
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = "xxxx";
facebookOptions.AppSecret = "xxxxxxx";
facebookOptions.AccessDeniedPath = "/AccessDeniedPathInfo";
});
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddSession(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts();
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Account}/{action=Login}/{id?}");
});
}
}
}
External Identity Provider Implementation
The form the _ExternalAuthentication partial view alreadt targets the ExternalLogin action. So we have to create it and add the required logic:
[HttpPost]
public IActionResult ExternalLogin(string returnUrl = null)
{
// Request a redirect to the external login provider.
string provider = "Facebook";
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
This is the action that we target by clicking the Facebook button. It has two parameters: provider and returnUrl.
Additional Implementation
So, let’s create a new action and add the required logic:
[TempData]
public string ErrorMessage { get; set; }
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToAction(nameof(ExternalLogin));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{ return RedirectToAction(nameof(ExternalLogin));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
//_logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
//return RedirectToAction(nameof(returnUrl));
}
else
{
string email = string.Empty;
string firstName = string.Empty;
string lastName = string.Empty;
string profileImage = string.Empty;
//get google login user infromation like that.
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
{
email = info.Principal.FindFirstValue(ClaimTypes.Email);
}
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.GivenName))
{ firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
}
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.GivenName))
{
lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);
}
//this function is get facebook profile images
var identifier = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
profileImage = $"https://graph.facebook.com/{identifier}/picture?type=large";
var user = new IdentityUser { UserName = email, Email = email, EmailConfirmed = true };
var result2 = await _userManager.CreateAsync(user);
if (result2.Succeeded)
{
result2 = await _userManager.AddLoginAsync(user, info);
if (result2.Succeeded)
{
//do somethng here
}
}
return View("Login");
}
}
AccountController.cs full code:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace GoogleAuthor.Controllers
{
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
public AccountController(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager
)
{
_userManager = userManager;
_signInManager = signInManager;
}
private ActionResult RedirectToLocal(string returnUrl)
{
return Redirect(returnUrl);
}
public IActionResult Login(string returnUrl)
{
return View();
}
[HttpPost]
public IActionResult ExternalLogin(string returnUrl = null)
{
// Request a redirect to the external login provider.
string provider = "Facebook";
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider); }
[TempData]
public string ErrorMessage { get; set; }
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToAction(nameof(ExternalLogin));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(ExternalLogin));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
//_logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
//return RedirectToAction(nameof(returnUrl));
}
else {
string email = string.Empty;
string firstName = string.Empty;
string lastName = string.Empty;
string profileImage = string.Empty;
//get google login user infromation like that.
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
{ email = info.Principal.FindFirstValue(ClaimTypes.Email);
}
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.GivenName))
{
firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
}
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.GivenName))
{
lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);
}
//this function is get facebook profile images
var identifier = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
profileImage = $"https://graph.facebook.com/{identifier}/picture?type=large";
var user = new IdentityUser { UserName = email, Email = email, EmailConfirmed = true };
var result2 = await _userManager.CreateAsync(user);
if (result2.Succeeded)
{
result2 = await _userManager.AddLoginAsync(user, info);
if (result2.Succeeded)
{
//do somethng here
}
}
return View("Login");
}
}
public IActionResult GoogleLogInSuccess()
{
return View();
}
}
}
HTML
@using Microsoft.AspNetCore.Identity;
@inject SignInManager<IdentityUser> SignInManager;
@{
ViewData["Title"] = "Login";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
<div class="col-sm-12">
<div class="justify-content-center">
<form asp-action="ExternalLogin" asp-controller="Account">
<h4 class="text-center margin-top">Login With Facebook Account</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<input type="text" hidden="hidden" name="returnUrl" value="/Home/Index" class="currenctURL1" id="currentURL1" />
<input type="submit" value="Login With Facebook" class="btn btn-primary" />
</form>
</div>
</div>
</div>
Comments