Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a default service to link local user accounts with external ones during the registration process #16110

Merged
merged 43 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
aa734f1
feat(Users): added default services to retrieve user to link to login…
PiemP May 20, 2024
c387004
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP May 20, 2024
2ee51cd
fix: avoid null excpetion in AccountController
PiemP May 22, 2024
a12d557
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP May 22, 2024
0ce3a96
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP Jun 10, 2024
bd01473
style: name changes, docs, indent, new line
PiemP Jun 10, 2024
ed96f40
cleanup before comments
MikeAlhayek Jun 10, 2024
dfd2dd6
Merge branch 'main' into srvcs_acct_to_login_data
MikeAlhayek Jun 10, 2024
6d74eaf
style: from LinkParameterValue to ExternalUserIdentifier
PiemP Jun 10, 2024
30188bf
style: from LinkParameterValue to ExternalUserIdentifier
PiemP Jun 10, 2024
ed52a4c
style: from LinkParameterValue to ExternalUserIdentifier
PiemP Jun 10, 2024
4726652
style: rename method, comment interface
PiemP Jun 10, 2024
c8898a4
style: improved comments
PiemP Jun 10, 2024
e04b9aa
style: removed grammar errors in comments
PiemP Jun 10, 2024
1ce6665
Update src/OrchardCore.Modules/OrchardCore.Users/Views/Account/LinkEx…
MikeAlhayek Jun 10, 2024
5115dd3
Update src/OrchardCore/OrchardCore.Users.Abstractions/Services/IUserT…
MikeAlhayek Jun 10, 2024
604fd35
Update src/OrchardCore/OrchardCore.Users.Abstractions/Services/IUserT…
MikeAlhayek Jun 10, 2024
8179182
Update src/OrchardCore/OrchardCore.Users.Abstractions/Services/IUserT…
MikeAlhayek Jun 10, 2024
f210886
Update src/OrchardCore/OrchardCore.Users.Abstractions/Services/IUserT…
MikeAlhayek Jun 10, 2024
31967ed
cleanup
MikeAlhayek Jun 10, 2024
06e963f
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP Jun 11, 2024
010de02
fix: var name in account controller
PiemP Jun 11, 2024
c9914fe
fix: comments in IUserToExternaLoginProvider
PiemP Jun 11, 2024
12e0597
updated comment in IUserToExternalLoginProvider
PiemP Jun 12, 2024
3255f3d
simplified code in DefaultUserToExternalLoginProvider
PiemP Jun 12, 2024
a330c50
updated class comment IUserToExternalLoginProvider
PiemP Jun 12, 2024
7e50a95
style: code to new line in ExternalLoginInfoExtensions
PiemP Jun 12, 2024
139ca99
docs: updated comment in the AccountController about order
PiemP Jun 12, 2024
c28fbca
style: brackets on a new line in AccountController
PiemP Jun 12, 2024
c3f4bbe
style(Users.Abstractions): change name to interface
PiemP Jun 12, 2024
5fd181a
style: from GetUserAsync to FindByLoginAsync
PiemP Jun 12, 2024
ec6a034
Merge branch 'main' into srvcs_acct_to_login_data
PiemP Jun 13, 2024
63e26ca
Merge branch 'main' into srvcs_acct_to_login_data
PiemP Jun 13, 2024
5c378b8
fix: removed IExternalLoginMapper
PiemP Jun 15, 2024
f2faf17
fix: improve if declaration
PiemP Jun 15, 2024
a0ce348
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP Jun 15, 2024
807ca2d
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP Jun 17, 2024
da86ae6
Update AccountController.cs
MikeAlhayek Jun 17, 2024
6459e5d
Merge branch 'main' into srvcs_acct_to_login_data
PiemP Jun 18, 2024
d3e1010
Update src/OrchardCore.Modules/OrchardCore.Users/Controllers/AccountC…
PiemP Jun 18, 2024
3bfcd28
Merge remote-tracking branch 'upstream/main' into srvcs_acct_to_login…
PiemP Jun 18, 2024
a6ec2b9
Merge branch 'main' into srvcs_acct_to_login_data
hishamco Jun 19, 2024
7be7530
Merge branch 'main' into srvcs_acct_to_login_data
hishamco Jun 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using OrchardCore.Modules;
using OrchardCore.Mvc.Core.Utilities;
using OrchardCore.Settings;
using OrchardCore.Users.Abstractions;
using OrchardCore.Users.Events;
using OrchardCore.Users.Handlers;
using OrchardCore.Users.Models;
Expand Down Expand Up @@ -47,6 +48,7 @@ public class AccountController : AccountBaseController
private readonly IClock _clock;
private readonly IDistributedCache _distributedCache;
private readonly IEnumerable<IExternalLoginEventHandler> _externalLoginHandlers;
private readonly IEnumerable<IExternalLoginUserToRelateFinder> _externalLoginUsrFinder;

protected readonly IHtmlLocalizer H;
protected readonly IStringLocalizer S;
Expand All @@ -67,7 +69,8 @@ public AccountController(
IShellFeaturesManager shellFeaturesManager,
IDisplayManager<LoginForm> loginFormDisplayManager,
IUpdateModelAccessor updateModelAccessor,
IEnumerable<IExternalLoginEventHandler> externalLoginHandlers)
IEnumerable<IExternalLoginEventHandler> externalLoginHandlers,
IEnumerable<IExternalLoginUserToRelateFinder> externalLoginUsrFinder)
{
_signInManager = signInManager;
_userManager = userManager;
Expand All @@ -83,6 +86,7 @@ public AccountController(
_loginFormDisplayManager = loginFormDisplayManager;
_updateModelAccessor = updateModelAccessor;
_externalLoginHandlers = externalLoginHandlers;
_externalLoginUsrFinder = externalLoginUsrFinder.Reverse();
PiemP marked this conversation as resolved.
Show resolved Hide resolved

H = htmlLocalizer;
S = stringLocalizer;
Expand Down Expand Up @@ -384,12 +388,9 @@ public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null,
}
else
{
var email = info.Principal.FindFirstValue(ClaimTypes.Email) ?? info.Principal.FindFirstValue("email");

if (!string.IsNullOrWhiteSpace(email))
{
iUser = await _userManager.FindByEmailAsync(email);
}
//really important the order of the services registration in the dependency injection context
var usrFinder = _externalLoginUsrFinder.Where(x => x.CanManageThis(info.LoginProvider)).FirstOrDefault();
PiemP marked this conversation as resolved.
Show resolved Hide resolved
iUser = usrFinder == null ? null : await usrFinder.FindUserToRelateAsync(info);

ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
Expand All @@ -409,7 +410,7 @@ public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null,

// Link external login to an existing user
ViewData["UserName"] = iUser.UserName;
ViewData["Email"] = email;
ViewData["LinkParameterValue"] = usrFinder?.GetValueThatLinkAccount(info);

return View(nameof(LinkExternalLogin));
}
Expand All @@ -423,6 +424,8 @@ public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null,
}
else
{
var email = info.Principal.FindFirstValue(ClaimTypes.Email) ?? info.Principal.FindFirstValue("email");

var externalLoginViewModel = new RegisterExternalLoginViewModel
{
NoPassword = registrationSettings.NoPasswordForExternalUsers,
Expand Down Expand Up @@ -630,9 +633,9 @@ public async Task<IActionResult> LinkExternalLogin(LinkExternalLoginViewModel mo

return NotFound();
}
var email = info.Principal.FindFirstValue(ClaimTypes.Email) ?? info.Principal.FindFirstValue("email");

var user = await _userManager.FindByEmailAsync(email);
//really important the order of the services registration in the dependency injection context
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
var usrFinder = _externalLoginUsrFinder.Where(x => x.CanManageThis(info.LoginProvider)).FirstOrDefault();
var user = await usrFinder?.FindUserToRelateAsync(info) ?? null;

if (user == null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using OrchardCore.Users.Abstractions;

namespace OrchardCore.Users.Services;

public class DefaultExternalLoginUserToRelateFinder : IExternalLoginUserToRelateFinder
{
private readonly UserManager<IUser> _userManager;
PiemP marked this conversation as resolved.
Show resolved Hide resolved

public DefaultExternalLoginUserToRelateFinder(UserManager<IUser> userManager)
{
_userManager = userManager;
}

public bool CanManageThis(string extLoginKind)
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
{
return true;
}

public async Task<IUser> FindUserToRelateAsync(ExternalLoginInfo info)
PiemP marked this conversation as resolved.
Show resolved Hide resolved
{
//the default behavior previously used in OrchardCore
var email = info.Principal.FindFirstValue(ClaimTypes.Email) ?? info.Principal.FindFirstValue("email");

IUser iUser = null;
if (!string.IsNullOrWhiteSpace(email))
{
iUser = await _userManager.FindByEmailAsync(email);
}

return iUser;
}

public string GetValueThatLinkAccount(ExternalLoginInfo info)
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
{
return info.Principal.FindFirstValue(ClaimTypes.Email) ?? info.Principal.FindFirstValue("email");
}
}
3 changes: 3 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Users/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
using OrchardCore.Settings.Deployment;
using OrchardCore.Setup.Events;
using OrchardCore.Sms;
using OrchardCore.Users.Abstractions;
using OrchardCore.Users.Commands;
using OrchardCore.Users.Controllers;
using OrchardCore.Users.Deployment;
Expand Down Expand Up @@ -198,6 +199,8 @@ public override void ConfigureServices(IServiceCollection services)
services.AddScoped<CustomUserSettingsService>();
services.AddRecipeExecutionStep<CustomUserSettingsStep>();
services.AddScoped<IDisplayDriver<LoginForm>, LoginFormDisplayDriver>();

services.AddScoped<IExternalLoginUserToRelateFinder, DefaultExternalLoginUserToRelateFinder>();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<form asp-controller="Account" asp-action="LinkExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal no-multisubmit">
<h4>@T["Link your account."]</h4>
<p class="text-info">
@T["You've successfully authenticated with <strong>{0}</strong>. You already have an account with this email address. Enter your local account password and click the Register button to link the accounts and finish logging in.", ViewData["LoginProvider"]]
@T["You've successfully authenticated with <strong>{0}</strong>. Seems already exist an account identificable by this information: <strong>{1}</strong>. Enter your local account password and click the Register button to link the accounts and finish logging in.", ViewData["LoginProvider"], ViewData["LinkParameterValue"]]
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
</p>
<hr />
<div asp-validation-summary="ModelOnly"></div>
Expand All @@ -20,9 +20,9 @@
</div>

<div class="mb-3">
<label for="Email" class="col-md-3 form-label">@T["Email"]</label>
<label for="LinkParameterValue" class="col-md-3 form-label">@T["Parameter that identify an existing account"]</label>
PiemP marked this conversation as resolved.
Show resolved Hide resolved
<div class="col-md-9">
<input id="Email" value="@ViewData["Email"]" class="form-control" disabled />
<input id="LinkParameterValue" value="@ViewData["LinkParameterValue"]" class="form-control" disabled />
PiemP marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;

namespace OrchardCore.Users.Abstractions;

public interface IExternalLoginUserToRelateFinder
PiemP marked this conversation as resolved.
Show resolved Hide resolved
{
bool CanManageThis(string extLoginKind);
PiemP marked this conversation as resolved.
Show resolved Hide resolved

Task<IUser> FindUserToRelateAsync(ExternalLoginInfo info);

string GetValueThatLinkAccount(ExternalLoginInfo info);
}