Merge pull request #2444 from sbwalker/dev
fix #2432 - add support for roles as part of external login via OIDC
This commit is contained in:
commit
7a3d5d0429
|
@ -286,6 +286,15 @@ else
|
||||||
<input id="emailclaimtype" class="form-control" @bind="@_emailclaimtype" />
|
<input id="emailclaimtype" class="form-control" @bind="@_emailclaimtype" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="roleclaimtype" HelpText="The name of the role claim provided by the provider" ResourceKey="RoleClaimType">Role Claim:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="roleclaimtype" class="form-control" @bind="@_roleclaimtype" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="domainfilter" HelpText="Provide any email domain filter criteria (separated by commas). Domains to exclude should be prefixed with an exclamation point (!). For example 'microsoft.com,!hotmail.com' would include microsoft.com email addresses but not hotmail.com email addresses." ResourceKey="DomainFilter">Domain Filter:</Label>
|
<Label Class="col-sm-3" For="domainfilter" HelpText="Provide any email domain filter criteria (separated by commas). Domains to exclude should be prefixed with an exclamation point (!). For example 'microsoft.com,!hotmail.com' would include microsoft.com email addresses but not hotmail.com email addresses." ResourceKey="DomainFilter">Domain Filter:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
|
@ -385,6 +394,7 @@ else
|
||||||
private string _redirecturl;
|
private string _redirecturl;
|
||||||
private string _identifierclaimtype;
|
private string _identifierclaimtype;
|
||||||
private string _emailclaimtype;
|
private string _emailclaimtype;
|
||||||
|
private string _roleclaimtype;
|
||||||
private string _domainfilter;
|
private string _domainfilter;
|
||||||
private string _createusers;
|
private string _createusers;
|
||||||
|
|
||||||
|
@ -436,8 +446,9 @@ else
|
||||||
_parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
|
_parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
|
||||||
_pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
|
_pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
|
||||||
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
||||||
_identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
|
_identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "sub");
|
||||||
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
|
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "email");
|
||||||
|
_roleclaimtype = SettingService.GetSetting(settings, "ExternalLogin:RoleClaimType", "");
|
||||||
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
||||||
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
||||||
|
|
||||||
|
@ -555,6 +566,7 @@ else
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:PKCE", _pkce, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:PKCE", _pkce, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:IdentifierClaimType", _identifierclaimtype, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:IdentifierClaimType", _identifierclaimtype, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:RoleClaimType", _roleclaimtype, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
|
||||||
|
|
||||||
|
|
|
@ -211,25 +211,25 @@
|
||||||
<value>Allow Login?</value>
|
<value>Allow Login?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Authority.HelpText" xml:space="preserve">
|
<data name="Authority.HelpText" xml:space="preserve">
|
||||||
<value>The Authority Url or Issuer Url associated with the OpenID Connect provider</value>
|
<value>The authority url or issuer url associated with the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Authority.Text" xml:space="preserve">
|
<data name="Authority.Text" xml:space="preserve">
|
||||||
<value>Authority:</value>
|
<value>Authority:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AuthorizationUrl.HelpText" xml:space="preserve">
|
<data name="AuthorizationUrl.HelpText" xml:space="preserve">
|
||||||
<value>The endpoint for obtaining an Authorization Code</value>
|
<value>The endpoint for obtaining an authorization code</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AuthorizationUrl.Text" xml:space="preserve">
|
<data name="AuthorizationUrl.Text" xml:space="preserve">
|
||||||
<value>Authorization Url:</value>
|
<value>Authorization Url:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientID.HelpText" xml:space="preserve">
|
<data name="ClientID.HelpText" xml:space="preserve">
|
||||||
<value>The Client ID from the provider</value>
|
<value>The client id for the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientID.Text" xml:space="preserve">
|
<data name="ClientID.Text" xml:space="preserve">
|
||||||
<value>Client ID:</value>
|
<value>Client ID:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientSecret.HelpText" xml:space="preserve">
|
<data name="ClientSecret.HelpText" xml:space="preserve">
|
||||||
<value>The Client Secret from the provider</value>
|
<value>The client secret for the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientSecret.Text" xml:space="preserve">
|
<data name="ClientSecret.Text" xml:space="preserve">
|
||||||
<value>Client Secret:</value>
|
<value>Client Secret:</value>
|
||||||
|
@ -247,7 +247,7 @@
|
||||||
<value>Domain Filter:</value>
|
<value>Domain Filter:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailClaimType.HelpText" xml:space="preserve">
|
<data name="EmailClaimType.HelpText" xml:space="preserve">
|
||||||
<value>The name of the email address claim provided by the provider</value>
|
<value>The name of the email address claim provided by the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailClaimType.Text" xml:space="preserve">
|
<data name="EmailClaimType.Text" xml:space="preserve">
|
||||||
<value>Email Claim:</value>
|
<value>Email Claim:</value>
|
||||||
|
@ -259,7 +259,7 @@
|
||||||
<value>Lockout Settings</value>
|
<value>Lockout Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MetadataUrl.HelpText" xml:space="preserve">
|
<data name="MetadataUrl.HelpText" xml:space="preserve">
|
||||||
<value>The discovery endpoint for obtaining metadata for this provider. Only specify if the OpenID Connect provider does not use the standard approach (ie. /.well-known/openid-configuration)</value>
|
<value>The discovery endpoint for obtaining metadata for this identity provider. Only specify if the identity provider does not use the standard approach (ie. /.well-known/openid-configuration)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MetadataUrl.Text" xml:space="preserve">
|
<data name="MetadataUrl.Text" xml:space="preserve">
|
||||||
<value>Metadata Url:</value>
|
<value>Metadata Url:</value>
|
||||||
|
@ -268,7 +268,7 @@
|
||||||
<value>Password Settings</value>
|
<value>Password Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PKCE.HelpText" xml:space="preserve">
|
<data name="PKCE.HelpText" xml:space="preserve">
|
||||||
<value>Indicate if the provider supports Proof Key for Code Exchange (PKCE)</value>
|
<value>Indicate if the identity provider supports proof key for code exchange (PKCE)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PKCE.Text" xml:space="preserve">
|
<data name="PKCE.Text" xml:space="preserve">
|
||||||
<value>Use PKCE?</value>
|
<value>Use PKCE?</value>
|
||||||
|
@ -286,25 +286,25 @@
|
||||||
<value>Provider Type:</value>
|
<value>Provider Type:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RedirectUrl.HelpText" xml:space="preserve">
|
<data name="RedirectUrl.HelpText" xml:space="preserve">
|
||||||
<value>The Redirect Url (or Callback Url) which usually needs to be registered with the provider</value>
|
<value>The redirect url (or callback url) which usually needs to be registered with the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RedirectUrl.Text" xml:space="preserve">
|
<data name="RedirectUrl.Text" xml:space="preserve">
|
||||||
<value>Redirect Url:</value>
|
<value>Redirect Url:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Scopes.HelpText" xml:space="preserve">
|
<data name="Scopes.HelpText" xml:space="preserve">
|
||||||
<value>A list of Scopes to request from the provider (separated by commas). If none are specified, standard Scopes will be used by default.</value>
|
<value>A list of scopes to request from the identity provider (separated by commas). If none are specified, standard Scopes will be used by default.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Scopes.Text" xml:space="preserve">
|
<data name="Scopes.Text" xml:space="preserve">
|
||||||
<value>Scopes:</value>
|
<value>Scopes:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TokenUrl.HelpText" xml:space="preserve">
|
<data name="TokenUrl.HelpText" xml:space="preserve">
|
||||||
<value>The endpoint for obtaining an Auth Token</value>
|
<value>The endpoint for obtaining an auth token</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TokenUrl.Text" xml:space="preserve">
|
<data name="TokenUrl.Text" xml:space="preserve">
|
||||||
<value>Token Url:</value>
|
<value>Token Url:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UserInfoUrl.HelpText" xml:space="preserve">
|
<data name="UserInfoUrl.HelpText" xml:space="preserve">
|
||||||
<value>The endpoint for obtaining user information. This should be an API or Page Url which contains the users email address.</value>
|
<value>The endpoint for obtaining user information. This should be an API endpoint or page url which contains the users email address.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UserInfoUrl.Text" xml:space="preserve">
|
<data name="UserInfoUrl.Text" xml:space="preserve">
|
||||||
<value>User Info Url:</value>
|
<value>User Info Url:</value>
|
||||||
|
@ -373,15 +373,21 @@
|
||||||
<value>Last Login</value>
|
<value>Last Login</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IdentifierClaimType.HelpText" xml:space="preserve">
|
<data name="IdentifierClaimType.HelpText" xml:space="preserve">
|
||||||
<value>The name of the unique user identifier claim provided by the provider</value>
|
<value>The name of the unique user identifier claim provided by the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IdentifierClaimType.Text" xml:space="preserve">
|
<data name="IdentifierClaimType.Text" xml:space="preserve">
|
||||||
<value>Identifier Claim:</value>
|
<value>Identifier Claim:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Parameters.HelpText" xml:space="preserve">
|
<data name="Parameters.HelpText" xml:space="preserve">
|
||||||
<value>Optionally specify any additional parameters as name/value pairs to send to the provider (separated by commas if there are multiple).</value>
|
<value>Optionally specify any additional parameters as name/value pairs to send to the identity provider (separated by commas if there are multiple).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Parameters.Text" xml:space="preserve">
|
<data name="Parameters.Text" xml:space="preserve">
|
||||||
<value>Parameters:</value>
|
<value>Parameters:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="RoleClaimType.HelpText" xml:space="preserve">
|
||||||
|
<value>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.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RoleClaimType.Text" xml:space="preserve">
|
||||||
|
<value>Role Claim Type:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@ -157,6 +158,9 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
|
||||||
public static IServiceCollection ConfigureOqtaneAuthenticationOptions(this IServiceCollection services, IConfigurationRoot Configuration)
|
public static IServiceCollection ConfigureOqtaneAuthenticationOptions(this IServiceCollection services, IConfigurationRoot Configuration)
|
||||||
{
|
{
|
||||||
|
// prevent remapping of claims
|
||||||
|
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
|
||||||
|
|
||||||
// settings defined in appsettings
|
// settings defined in appsettings
|
||||||
services.Configure<OAuthOptions>(Configuration);
|
services.Configure<OAuthOptions>(Configuration);
|
||||||
services.Configure<OpenIdConnectOptions>(Configuration);
|
services.Configure<OpenIdConnectOptions>(Configuration);
|
||||||
|
|
|
@ -56,6 +56,10 @@ namespace Oqtane.Extensions
|
||||||
options.ClientId = sitesettings.GetValue("ExternalLogin:ClientId", "");
|
options.ClientId = sitesettings.GetValue("ExternalLogin:ClientId", "");
|
||||||
options.ClientSecret = sitesettings.GetValue("ExternalLogin:ClientSecret", "");
|
options.ClientSecret = sitesettings.GetValue("ExternalLogin:ClientSecret", "");
|
||||||
options.UsePkce = bool.Parse(sitesettings.GetValue("ExternalLogin:PKCE", "false"));
|
options.UsePkce = bool.Parse(sitesettings.GetValue("ExternalLogin:PKCE", "false"));
|
||||||
|
if (!string.IsNullOrEmpty(sitesettings.GetValue("ExternalLogin:RoleClaimType", "")))
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters.RoleClaimType = sitesettings.GetValue("ExternalLogin:RoleClaimType", "");
|
||||||
|
}
|
||||||
options.Scope.Clear();
|
options.Scope.Clear();
|
||||||
foreach (var scope in sitesettings.GetValue("ExternalLogin:Scopes", "openid,profile,email").Split(',', StringSplitOptions.RemoveEmptyEntries))
|
foreach (var scope in sitesettings.GetValue("ExternalLogin:Scopes", "openid,profile,email").Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
|
@ -230,6 +234,18 @@ namespace Oqtane.Extensions
|
||||||
var identity = await ValidateUser(email, id, claims, context.HttpContext);
|
var identity = await ValidateUser(email, id, claims, context.HttpContext);
|
||||||
if (identity.Label == ExternalLoginStatus.Success)
|
if (identity.Label == ExternalLoginStatus.Success)
|
||||||
{
|
{
|
||||||
|
// external roles
|
||||||
|
if (!string.IsNullOrEmpty(context.HttpContext.GetSiteSettings().GetValue("ExternalLogin:RoleClaimType", "")))
|
||||||
|
{
|
||||||
|
foreach (var claim in context.Principal.Claims.Where(item => item.Type == ClaimTypes.Role))
|
||||||
|
{
|
||||||
|
if (!identity.Claims.Any(item => item.Type == ClaimTypes.Role && item.Value == claim.Value))
|
||||||
|
{
|
||||||
|
identity.AddClaim(new Claim(ClaimTypes.Role, claim.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
identity.AddClaim(new Claim("access_token", context.SecurityToken.RawData));
|
identity.AddClaim(new Claim("access_token", context.SecurityToken.RawData));
|
||||||
context.Principal = new ClaimsPrincipal(identity);
|
context.Principal = new ClaimsPrincipal(identity);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user