@ -133,7 +133,7 @@ namespace Oqtane.Extensions
|
|||||||
output = "[" + output + "]"; // convert to json array
|
output = "[" + output + "]"; // convert to json array
|
||||||
}
|
}
|
||||||
JsonNode items = JsonNode.Parse(output)!;
|
JsonNode items = JsonNode.Parse(output)!;
|
||||||
foreach(var item in items.AsArray())
|
foreach (var item in items.AsArray())
|
||||||
{
|
{
|
||||||
if (item[emailClaimType] != null)
|
if (item[emailClaimType] != null)
|
||||||
{
|
{
|
||||||
@ -235,97 +235,112 @@ namespace Oqtane.Extensions
|
|||||||
ClaimsIdentity identity = new ClaimsIdentity(Constants.AuthenticationScheme);
|
ClaimsIdentity identity = new ClaimsIdentity(Constants.AuthenticationScheme);
|
||||||
// use identity.Label as a temporary location to store validation status information
|
// use identity.Label as a temporary location to store validation status information
|
||||||
|
|
||||||
if (EmailValid(email, httpContext.GetSiteSettings().GetValue("ExternalLogin:DomainFilter", "")))
|
var providerType = httpContext.GetSiteSettings().GetValue("ExternalLogin:ProviderType", "");
|
||||||
|
var providerName = httpContext.GetSiteSettings().GetValue("ExternalLogin:ProviderName", "");
|
||||||
|
var alias = httpContext.GetAlias();
|
||||||
|
var _users = httpContext.RequestServices.GetRequiredService<IUserRepository>();
|
||||||
|
User user = null;
|
||||||
|
|
||||||
|
// verify if external user is already registerd for this site
|
||||||
|
var _identityUserManager = httpContext.RequestServices.GetRequiredService<UserManager<IdentityUser>>();
|
||||||
|
var identityuser = await _identityUserManager.FindByLoginAsync(providerType + ":" + alias.SiteId.ToString(), id);
|
||||||
|
if (identityuser != null)
|
||||||
{
|
{
|
||||||
var _identityUserManager = httpContext.RequestServices.GetRequiredService<UserManager<IdentityUser>>();
|
user = _users.GetUser(identityuser.UserName);
|
||||||
var _users = httpContext.RequestServices.GetRequiredService<IUserRepository>();
|
}
|
||||||
var _userRoles = httpContext.RequestServices.GetRequiredService<IUserRoleRepository>();
|
else
|
||||||
var alias = httpContext.GetAlias();
|
{
|
||||||
var providerType = httpContext.GetSiteSettings().GetValue("ExternalLogin:ProviderType", "");
|
if (EmailValid(email, httpContext.GetSiteSettings().GetValue("ExternalLogin:DomainFilter", "")))
|
||||||
var providerName = httpContext.GetSiteSettings().GetValue("ExternalLogin:ProviderName", "");
|
|
||||||
User user = null;
|
|
||||||
|
|
||||||
bool duplicates = false;
|
|
||||||
IdentityUser identityuser = null;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
identityuser = await _identityUserManager.FindByEmailAsync(email);
|
bool duplicates = false;
|
||||||
}
|
try
|
||||||
catch
|
|
||||||
{
|
|
||||||
// FindByEmailAsync will throw an error if the email matches multiple user accounts
|
|
||||||
duplicates = true;
|
|
||||||
}
|
|
||||||
if (identityuser == null)
|
|
||||||
{
|
|
||||||
if (duplicates)
|
|
||||||
{
|
{
|
||||||
identity.Label = ExternalLoginStatus.DuplicateEmail;
|
identityuser = await _identityUserManager.FindByEmailAsync(email);
|
||||||
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Multiple Users Exist With Email Address {Email}. Login Denied.", email);
|
|
||||||
}
|
}
|
||||||
else
|
catch
|
||||||
{
|
{
|
||||||
if (bool.Parse(httpContext.GetSiteSettings().GetValue("ExternalLogin:CreateUsers", "true")))
|
// FindByEmailAsync will throw an error if the email matches multiple user accounts
|
||||||
|
duplicates = true;
|
||||||
|
}
|
||||||
|
if (identityuser == null)
|
||||||
|
{
|
||||||
|
if (duplicates)
|
||||||
{
|
{
|
||||||
identityuser = new IdentityUser();
|
identity.Label = ExternalLoginStatus.DuplicateEmail;
|
||||||
identityuser.UserName = email;
|
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Multiple Users Exist With Email Address {Email}. Login Denied.", email);
|
||||||
identityuser.Email = email;
|
}
|
||||||
identityuser.EmailConfirmed = true;
|
else
|
||||||
var result = await _identityUserManager.CreateAsync(identityuser, DateTime.UtcNow.ToString("yyyy-MMM-dd-HH-mm-ss"));
|
{
|
||||||
if (result.Succeeded)
|
if (bool.Parse(httpContext.GetSiteSettings().GetValue("ExternalLogin:CreateUsers", "true")))
|
||||||
{
|
{
|
||||||
user = new User
|
identityuser = new IdentityUser();
|
||||||
|
identityuser.UserName = email;
|
||||||
|
identityuser.Email = email;
|
||||||
|
identityuser.EmailConfirmed = true;
|
||||||
|
var result = await _identityUserManager.CreateAsync(identityuser, DateTime.UtcNow.ToString("yyyy-MMM-dd-HH-mm-ss"));
|
||||||
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
SiteId = alias.SiteId,
|
user = new User
|
||||||
Username = email,
|
{
|
||||||
DisplayName = email,
|
SiteId = alias.SiteId,
|
||||||
Email = email,
|
Username = email,
|
||||||
LastLoginOn = null,
|
DisplayName = email,
|
||||||
LastIPAddress = ""
|
Email = email,
|
||||||
};
|
LastLoginOn = null,
|
||||||
user = _users.AddUser(user);
|
LastIPAddress = ""
|
||||||
|
};
|
||||||
|
user = _users.AddUser(user);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
var _notifications = httpContext.RequestServices.GetRequiredService<INotificationRepository>();
|
var _notifications = httpContext.RequestServices.GetRequiredService<INotificationRepository>();
|
||||||
string url = httpContext.Request.Scheme + "://" + alias.Name;
|
string url = httpContext.Request.Scheme + "://" + alias.Name;
|
||||||
string body = "You Recently Used An External Account To Sign In To Our Site.\n\n" + url + "\n\nThank You!";
|
string body = "You Recently Used An External Account To Sign In To Our Site.\n\n" + url + "\n\nThank You!";
|
||||||
var notification = new Notification(user.SiteId, user, "User Account Notification", body);
|
var notification = new Notification(user.SiteId, user, "User Account Notification", body);
|
||||||
_notifications.AddNotification(notification);
|
_notifications.AddNotification(notification);
|
||||||
|
|
||||||
// add user login
|
// add user login
|
||||||
await _identityUserManager.AddLoginAsync(identityuser, new UserLoginInfo(providerType, id, ""));
|
await _identityUserManager.AddLoginAsync(identityuser, new UserLoginInfo(providerType + ":" + alias.SiteId.ToString(), id, providerName));
|
||||||
|
|
||||||
_logger.Log(user.SiteId, LogLevel.Information, "ExternalLogin", Enums.LogFunction.Create, "User Added {User}", user);
|
_logger.Log(user.SiteId, LogLevel.Information, "ExternalLogin", Enums.LogFunction.Create, "User Added {User}", user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
identity.Label = ExternalLoginStatus.UserNotCreated;
|
||||||
|
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add User {Email}", email);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
identity.Label = ExternalLoginStatus.UserNotCreated;
|
identity.Label = ExternalLoginStatus.UserNotCreated;
|
||||||
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add User {Email}", email);
|
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add Identity User {Email} {Error}", email, result.Errors.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
identity.Label = ExternalLoginStatus.UserNotCreated;
|
identity.Label = ExternalLoginStatus.UserDoesNotExist;
|
||||||
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add Identity User {Email} {Error}", email, result.Errors.ToString());
|
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Creation Of New Users Is Disabled For This Site. User With Email Address {Email} Will First Need To Be Registered On The Site.", email);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
identity.Label = ExternalLoginStatus.UserDoesNotExist;
|
|
||||||
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Creation Of New Users Is Disabled For This Site. User With Email Address {Email} Will First Need To Be Registered On The Site.", email);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
var logins = await _identityUserManager.GetLoginsAsync(identityuser);
|
|
||||||
var login = logins.FirstOrDefault(item => item.LoginProvider == (providerType + ":" + alias.SiteId.ToString()));
|
|
||||||
if (login != null)
|
|
||||||
{
|
{
|
||||||
if (login.ProviderKey == id)
|
var logins = await _identityUserManager.GetLoginsAsync(identityuser);
|
||||||
|
var login = logins.FirstOrDefault(item => item.LoginProvider == (providerType + ":" + alias.SiteId.ToString()));
|
||||||
|
if (login == null)
|
||||||
{
|
{
|
||||||
user = _users.GetUser(identityuser.UserName);
|
// new external login using existing user account - verification required
|
||||||
|
var _notifications = httpContext.RequestServices.GetRequiredService<INotificationRepository>();
|
||||||
|
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
|
string url = httpContext.Request.Scheme + "://" + alias.Name;
|
||||||
|
url += $"/login?name={identityuser.UserName}&token={WebUtility.UrlEncode(token)}&key={WebUtility.UrlEncode(id)}";
|
||||||
|
string body = $"You Recently Signed In To Our Site With {providerName} Using The Email Address {email}. ";
|
||||||
|
body += "In Order To Complete The Linkage Of Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
||||||
|
var notification = new Notification(alias.SiteId, email, email, "External Login Linkage", body);
|
||||||
|
_notifications.AddNotification(notification);
|
||||||
|
|
||||||
|
identity.Label = ExternalLoginStatus.VerificationRequired;
|
||||||
|
_logger.Log(alias.SiteId, LogLevel.Information, "ExternalLogin", Enums.LogFunction.Create, "External Login Linkage Verification For Provider {Provider} Sent To {Email}", providerName, email);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -334,48 +349,36 @@ namespace Oqtane.Extensions
|
|||||||
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Provider Key Does Not Match For User {Username}. Login Denied.", identityuser.UserName);
|
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Provider Key Does Not Match For User {Username}. Login Denied.", identityuser.UserName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else // email invalid
|
||||||
|
{
|
||||||
|
identity.Label = ExternalLoginStatus.InvalidEmail;
|
||||||
|
if (!string.IsNullOrEmpty(email))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The Email Address {Email} Is Invalid Or Does Not Match The Domain Filter Criteria. Login Denied.", email);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// new external login using existing user account - verification required
|
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Provider Did Not Return An Email To Uniquely Identify The User.");
|
||||||
var _notifications = httpContext.RequestServices.GetRequiredService<INotificationRepository>();
|
|
||||||
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
|
||||||
string url = httpContext.Request.Scheme + "://" + alias.Name;
|
|
||||||
url += $"/login?name={identityuser.UserName}&token={WebUtility.UrlEncode(token)}&key={WebUtility.UrlEncode(id)}";
|
|
||||||
string body = $"You Recently Signed In To Our Site With {providerName} Using The Email Address {email}. ";
|
|
||||||
body += "In Order To Complete The Linkage Of Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
|
||||||
var notification = new Notification(alias.SiteId, email, email, "External Login Linkage", body);
|
|
||||||
_notifications.AddNotification(notification);
|
|
||||||
identity.Label = ExternalLoginStatus.VerificationRequired;
|
|
||||||
_logger.Log(alias.SiteId, LogLevel.Information, "ExternalLogin", Enums.LogFunction.Create, "External Login Linkage Verification For Provider {Provider} Sent To {Email}", providerName, email);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// manage user
|
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
// create claims identity
|
|
||||||
identity = UserSecurity.CreateClaimsIdentity(alias, user, _userRoles.GetUserRoles(user.UserId, user.SiteId).ToList());
|
|
||||||
identity.Label = ExternalLoginStatus.Success;
|
|
||||||
|
|
||||||
// update user
|
|
||||||
user.LastLoginOn = DateTime.UtcNow;
|
|
||||||
user.LastIPAddress = httpContext.Connection.RemoteIpAddress.ToString();
|
|
||||||
_users.UpdateUser(user);
|
|
||||||
_logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} Using Provider {Provider}", user.Username, providerName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else // email invalid
|
|
||||||
|
// manage user
|
||||||
|
if (user != null)
|
||||||
{
|
{
|
||||||
identity.Label = ExternalLoginStatus.InvalidEmail;
|
// create claims identity
|
||||||
if (!string.IsNullOrEmpty(email))
|
var _userRoles = httpContext.RequestServices.GetRequiredService<IUserRoleRepository>();
|
||||||
{
|
identity = UserSecurity.CreateClaimsIdentity(alias, user, _userRoles.GetUserRoles(user.UserId, user.SiteId).ToList());
|
||||||
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "The Email Address {Email} Is Invalid Or Does Not Match The Domain Filter Criteria. Login Denied.", email);
|
identity.Label = ExternalLoginStatus.Success;
|
||||||
}
|
|
||||||
else
|
// update user
|
||||||
{
|
user.LastLoginOn = DateTime.UtcNow;
|
||||||
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Provider Did Not Return An Email To Uniquely Identify The User.");
|
user.LastIPAddress = httpContext.Connection.RemoteIpAddress.ToString();
|
||||||
}
|
_users.UpdateUser(user);
|
||||||
|
_logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} Using Provider {Provider}", user.Username, providerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user