Browse Source

Merge pull request #188 from aspnetzero/Alper/facebook-authentication

Alper/facebook authentication
pull/190/head
Halil İbrahim Kalkan 8 years ago
committed by GitHub
parent
commit
9ba53e2d0f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/AbpDesk/AbpDesk.Web.Mvc/AbpDeskWebMvcModule.cs
  2. 2
      src/AbpDesk/AbpDesk.Web.Mvc/Startup.cs
  3. 7
      src/AbpDesk/AbpDesk.Web.Mvc/appsettings.json
  4. BIN
      src/AbpDesk/Web_PlugIns/AbpDesk.MongoBlog.dll
  5. 29
      src/Volo.Abp.Account.Web/Pages/Account/ExternalLogin.cshtml
  6. 138
      src/Volo.Abp.Account.Web/Pages/Account/ExternalLogin.cshtml.cs
  7. 74
      src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml
  8. 8
      src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
  9. 5
      src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EfCoreIdentityUserRepository.cs

14
src/AbpDesk/AbpDesk.Web.Mvc/AbpDeskWebMvcModule.cs

@ -66,6 +66,20 @@ namespace AbpDesk.Web.Mvc
//services.Configure<RemoteServiceOptions>(configuration); //Needed when we use Volo.Abp.Identity.HttpApi.Client //services.Configure<RemoteServiceOptions>(configuration); //Needed when we use Volo.Abp.Identity.HttpApi.Client
//Adding Facebook authentication
if (bool.Parse(configuration["Authentication:Facebook:IsEnabled"]))
{
services.AddAuthentication().AddFacebook(options =>
{
options.AppId = configuration["Authentication:Facebook:AppId"];
options.AppSecret = configuration["Authentication:Facebook:AppSecret"];
options.Scope.Add("email");
options.Scope.Add("public_profile");
});
}
services.AddAssemblyOf<AbpDeskWebMvcModule>(); services.AddAssemblyOf<AbpDeskWebMvcModule>();
services.Configure<BundlingOptions>(options => services.Configure<BundlingOptions>(options =>

2
src/AbpDesk/AbpDesk.Web.Mvc/Startup.cs

@ -1,12 +1,10 @@
using System; using System;
using System.IO;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Serilog; using Serilog;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Modularity.PlugIns;
namespace AbpDesk.Web.Mvc namespace AbpDesk.Web.Mvc
{ {

7
src/AbpDesk/AbpDesk.Web.Mvc/appsettings.json

@ -7,5 +7,12 @@
"AbpIdentity": { "AbpIdentity": {
"BaseUrl": "http://localhost:63290/" "BaseUrl": "http://localhost:63290/"
} }
},
"Authentication": {
"Facebook": {
"IsEnabled": "true",
"AppId": "911417875702990",
"AppSecret": "adea0bff222ae340d8fb0ce3e6275d6b"
}
} }
} }

BIN
src/AbpDesk/Web_PlugIns/AbpDesk.MongoBlog.dll

Binary file not shown.

29
src/Volo.Abp.Account.Web/Pages/Account/ExternalLogin.cshtml

@ -0,0 +1,29 @@
@page
@model Volo.Abp.Account.Web.Pages.Account.ExternalLoginModel
@{
ViewData["Title"] = "Register";
}
<h2>@ViewData["Title"]</h2>
<h4>Associate your @Model.LoginProvider account.</h4>
<hr />
<p class="text-info">
You've successfully authenticated with <strong>@Model.LoginProvider</strong>.
Please enter an email address for this site below and click the Register button to finish
logging in.
</p>
<div class="row">
<div class="col-md-4">
<form asp-page-handler="Confirmation" asp-route-returnUrl="@Model.ReturnUrl" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Register</button>
</form>
</div>
</div>

138
src/Volo.Abp.Account.Web/Pages/Account/ExternalLogin.cshtml.cs

@ -0,0 +1,138 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Identity;
using Volo.Abp.Ui;
using Volo.Abp.Uow;
namespace Volo.Abp.Account.Web.Pages.Account
{
public class ExternalLoginModel : AccountModelBase
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
public ExternalLoginModel(
SignInManager<IdentityUser> signInManager,
UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
[BindProperty]
public InputModel Input { get; set; }
public string LoginProvider { get; set; }
public string ReturnUrl { get; set; }
[TempData]
public string ErrorMessage { get; set; }
public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
}
public IActionResult OnGetAsync()
{
return RedirectToPage("./Login");
}
[UnitOfWork]
public virtual IActionResult OnPost(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
}
[UnitOfWork]
public virtual async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null, string returnUrlHash = "")
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login");
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToPage("./Login");
}
// 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 RedirectSafely(returnUrl, returnUrlHash);
}
if (result.IsLockedOut)
{
throw new UserFriendlyException("Cannot proceed because user is locked out!");
}
ReturnUrl = returnUrl;
LoginProvider = info.LoginProvider;
//User does not have an account, create an account.
var success = await CreateUserAsync(returnUrl, returnUrlHash);
if (success)
{
return RedirectSafely(returnUrl, returnUrlHash);
}
return Page();
}
[UnitOfWork]
public virtual async Task<bool> CreateUserAsync(string returnUrl = null, string returnUrlHash = null)
{
if (!ModelState.IsValid)
{
return false;
}
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
throw new ApplicationException("Error loading external login information during confirmation.");
}
var user = new IdentityUser(GuidGenerator.Create(), info.Principal.FindFirstValue(ClaimTypes.Email));
var result = await _userManager.CreateAsync(user);
//todo: needs to check identity errors?
//CheckIdentityErrors( await _userManager.CreateAsync(user));
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, false);
return true;
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
return false;
}
}
}

74
src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml

@ -1,27 +1,61 @@
@page @page
@model Volo.Abp.Account.Web.Pages.Account.LoginModel @model Volo.Abp.Account.Web.Pages.Account.LoginModel
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-6">
<form method="post"> <div class="col-md-4">
<div class="form-group"> <form method="post">
<label for="UsernameOrEmailAddress">Username or email address</label> <div class="form-group">
<input type="text" class="form-control" id="UsernameOrEmailAddress" name="UsernameOrEmailAddress"> <label for="UsernameOrEmailAddress">Username or email address</label>
<input type="text" class="form-control" id="UsernameOrEmailAddress" name="UsernameOrEmailAddress">
</div>
<div class="form-group">
<label for="Password">Password</label>
<input type="password" class="form-control" id="Password" name="Password">
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" name="RememberMe" value="true" checked="checked">
Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<div style="padding-top: 20px">
<a href="@Url.Page("./Register", new { returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash })">Register</a>
</div> </div>
<div class="form-group">
<label for="Password">Password</label>
<input type="password" class="form-control" id="Password" name="Password">
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" name="RememberMe" value="true" checked="checked">
Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<div>
<a href="@Url.Page("./Register", new { returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash })">Register</a>
</div> </div>
</div> </div>
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to log in.</h4>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-default" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div> </div>

8
src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Identity; using Volo.Abp.Identity;
@ -15,6 +18,8 @@ namespace Volo.Abp.Account.Web.Pages.Account
public string ReturnUrlHash { get; set; } //TODO: Try to automatically bind from querystring! public string ReturnUrlHash { get; set; } //TODO: Try to automatically bind from querystring!
public IList<AuthenticationScheme> ExternalLogins { get; set; }
private readonly SignInManager<IdentityUser> _signInManager; private readonly SignInManager<IdentityUser> _signInManager;
public LoginModel(SignInManager<IdentityUser> signInManager) public LoginModel(SignInManager<IdentityUser> signInManager)
@ -22,10 +27,11 @@ namespace Volo.Abp.Account.Web.Pages.Account
_signInManager = signInManager; _signInManager = signInManager;
} }
public void OnGet(string returnUrl = "", string returnUrlHash = "") public async Task OnGetAsync(string returnUrl = "", string returnUrlHash = "")
{ {
ReturnUrl = returnUrl; ReturnUrl = returnUrl;
ReturnUrlHash = returnUrl; ReturnUrlHash = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
} }
//TODO: Bind input to a property instead of getting as parameter..? //TODO: Bind input to a property instead of getting as parameter..?

5
src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EfCoreIdentityUserRepository.cs

@ -37,7 +37,10 @@ namespace Volo.Abp.Identity
public async Task<IdentityUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken) public async Task<IdentityUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
{ {
//TODO: This should be changed since loginProvider, providerKey are not PKs. //TODO: This should be changed since loginProvider, providerKey are not PKs.
var userLogin = await DbContext.UserLogins.FindAsync(new object[] { loginProvider, providerKey }, cancellationToken); var userLogin = await DbContext.UserLogins
.Where(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)
.FirstOrDefaultAsync(cancellationToken);
if (userLogin == null) if (userLogin == null)
{ {
return null; return null;

Loading…
Cancel
Save