From 5e1ac485a09816da2489277f684d636ded06dfaa Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 10 Mar 2023 10:14:57 -0500 Subject: [PATCH] #2655 - add support for capturing user profile infrmation from claims during external login --- Oqtane.Client/Modules/Admin/Users/Index.razor | 9 +++++ .../Resources/Modules/Admin/Users/Index.resx | 10 ++++- ...taneSiteAuthenticationBuilderExtensions.cs | 40 +++++++++++++++++-- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index 40124c61..2b293e2d 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -294,6 +294,12 @@ else +
+ +
+ +
+
}
@@ -395,6 +401,7 @@ else private string _identifierclaimtype; private string _emailclaimtype; private string _roleclaimtype; + private string _profileclaimtypes; private string _domainfilter; private string _createusers; @@ -449,6 +456,7 @@ else _identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "sub"); _emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "email"); _roleclaimtype = SettingService.GetSetting(settings, "ExternalLogin:RoleClaimType", ""); + _profileclaimtypes = SettingService.GetSetting(settings, "ExternalLogin:ProfileClaimTypes", ""); _domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", ""); _createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true"); @@ -568,6 +576,7 @@ else settings = SettingService.SetSetting(settings, "ExternalLogin:IdentifierClaimType", _identifierclaimtype, true); settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true); settings = SettingService.SetSetting(settings, "ExternalLogin:RoleClaimType", _roleclaimtype, true); + settings = SettingService.SetSetting(settings, "ExternalLogin:ProfileClaimTypes", _profileclaimtypes, true); settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true); settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true); diff --git a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx index 90cce059..6b26fb12 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx @@ -387,7 +387,13 @@ Optionally provide the name of the role claim provided by the identity provider. These roles will be used in addition to any internal user roles assigned within the site. - - Role Claim Type: + + Role Claim: + + + Optionally provide a comma delimited list of user profile claims provided by the identity provider, as well as mappings to your user profile definition. For example if the identity provider includes a 'given_name' claim and you have a 'FirstName' user profile definition you should specify 'given_name:FirstName'. + + + User Profile Claims: \ No newline at end of file diff --git a/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs b/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs index f015f917..68284a01 100644 --- a/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs @@ -197,7 +197,7 @@ namespace Oqtane.Extensions } // validate user - var identity = await ValidateUser(email, id, claims, context.HttpContext); + var identity = await ValidateUser(email, id, claims, context.HttpContext, context.Principal); if (identity.Label == ExternalLoginStatus.Success) { identity.AddClaim(new Claim("access_token", context.AccessToken)); @@ -232,7 +232,7 @@ namespace Oqtane.Extensions var claims = string.Join(", ", context.Principal.Claims.Select(item => item.Type).ToArray()); // validate user - var identity = await ValidateUser(email, id, claims, context.HttpContext); + var identity = await ValidateUser(email, id, claims, context.HttpContext, context.Principal); if (identity.Label == ExternalLoginStatus.Success) { // external roles @@ -278,7 +278,7 @@ namespace Oqtane.Extensions return Task.CompletedTask; } - private static async Task ValidateUser(string email, string id, string claims, HttpContext httpContext) + private static async Task ValidateUser(string email, string id, string claims, HttpContext httpContext, ClaimsPrincipal claimsPrincipal) { var _logger = httpContext.RequestServices.GetRequiredService(); ClaimsIdentity identity = new ClaimsIdentity(Constants.AuthenticationScheme); @@ -427,6 +427,40 @@ namespace Oqtane.Extensions user.LastLoginOn = DateTime.UtcNow; user.LastIPAddress = httpContext.Connection.RemoteIpAddress.ToString(); _users.UpdateUser(user); + + // user profile claims + if (!string.IsNullOrEmpty(httpContext.GetSiteSettings().GetValue("ExternalLogin:ProfileClaimTypes", ""))) + { + var _settings = httpContext.RequestServices.GetRequiredService(); + var _profiles = httpContext.RequestServices.GetRequiredService(); + var profiles = _profiles.GetProfiles(user.SiteId); + foreach (var mapping in httpContext.GetSiteSettings().GetValue("ExternalLogin:ProfileClaimTypes", "").Split(',', StringSplitOptions.RemoveEmptyEntries)) + { + if (mapping.Contains(":")) + { + var claim = claimsPrincipal.Claims.FirstOrDefault(item => item.Type == mapping.Split(":")[0]); + if (claim != null && !string.IsNullOrEmpty(claim.Value)) + { + var profile = profiles.FirstOrDefault(item => item.Name == mapping.Split(":")[1]); + if (profile != null) + { + var setting = _settings.GetSetting(EntityNames.User, user.UserId, profile.Name); + if (setting != null) + { + setting.SettingValue = claim.Value; + _settings.UpdateSetting(setting); + } + else + { + setting = new Setting { EntityName = EntityNames.User, EntityId = user.UserId, SettingName = profile.Name, SettingValue = claim.Value, IsPrivate = profile.IsPrivate }; + _settings.AddSetting(setting); + } + } + } + } + } + } + _logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} Using Provider {Provider}", user.Username, providerName); } }