Allows for customizing the invite link, had to update umb-button to support external href, streamlines external login provider configs
This commit is contained in:
@@ -56,8 +56,7 @@ namespace Umbraco.Core
|
||||
public const string AllowedApplicationsClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/allowedapp";
|
||||
public const string SessionIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/sessionid";
|
||||
|
||||
public const string BackOfficeExternalAuthenticationDenyLocalLoginProperty = "UmbracoBackOffice_DenyLocalLogin";
|
||||
public const string BackOfficeExternalAuthenticationAutoLoginRedirectProperty = "UmbracoBackOffice_AutoLoginRedirect";
|
||||
public const string BackOfficeExternalLoginOptionsProperty = "UmbracoBackOfficeExternalLoginOptions";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ Use this directive to render an umbraco button. The directive can be used to gen
|
||||
|
||||
@param {callback} action The button action which should be performed when the button is clicked.
|
||||
@param {string=} href Url/Path to navigato to.
|
||||
@param {string=} type Set the button type ("button" or "submit").
|
||||
@param {string=} type Set the button type ("button" or "submit" or "link").
|
||||
@param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link", "block"). Pass in array to add multple styles [success,block].
|
||||
@param {string=} state Set a progress state on the button ("init", "busy", "success", "error").
|
||||
@param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c").
|
||||
@@ -86,6 +86,7 @@ Use this directive to render an umbraco button. The directive can be used to gen
|
||||
bindings: {
|
||||
action: "&?",
|
||||
href: "@?",
|
||||
hrefTarget: "@?",
|
||||
type: "@",
|
||||
buttonStyle: "@?",
|
||||
state: "<?",
|
||||
@@ -123,6 +124,10 @@ Use this directive to render an umbraco button. The directive can be used to gen
|
||||
vm.innerState = "init";
|
||||
vm.generalActions = vm.labelKey === "general_actions";
|
||||
|
||||
if (!vm.type) {
|
||||
vm.type = "button"; // set the default
|
||||
}
|
||||
|
||||
vm.buttonLabel = vm.label;
|
||||
// is this a primary button style (i.e. anything but an 'info' button)?
|
||||
vm.isPrimaryButtonStyle = vm.buttonStyle && vm.buttonStyle !== 'info';
|
||||
|
||||
@@ -11,10 +11,10 @@ function externalLoginInfoService(externalLoginInfo) {
|
||||
*/
|
||||
function hasDenyLocalLogin(provider) {
|
||||
if (!provider) {
|
||||
return _.some(externalLoginInfo.providers, x => x.properties.UmbracoBackOffice_DenyLocalLogin === true);
|
||||
return _.some(externalLoginInfo.providers, x => x.properties.UmbracoBackOfficeExternalLoginOptions.DenyLocalLogin === true);
|
||||
}
|
||||
else {
|
||||
return provider.properties.UmbracoBackOffice_DenyLocalLogin;
|
||||
return provider.properties.UmbracoBackOfficeExternalLoginOptions.DenyLocalLogin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,32 @@ function externalLoginInfoService(externalLoginInfo) {
|
||||
*/
|
||||
function getLoginProviders(excludeDenyLocalLogin) {
|
||||
if (excludeDenyLocalLogin) {
|
||||
return _.filter(externalLoginInfo.providers, x => !x.properties.UmbracoBackOffice_DenyLocalLogin);
|
||||
return _.filter(externalLoginInfo.providers, x => !x.properties.UmbracoBackOfficeExternalLoginOptions.DenyLocalLogin);
|
||||
}
|
||||
else {
|
||||
return externalLoginInfo.providers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is any external login providers with deny local login, check if any have a custom invite link and return it
|
||||
* @param {any} provider optional to get the invite link directly from the provider, else will return the first one found (if any)
|
||||
*/
|
||||
function getUserInviteLink(provider) {
|
||||
if (!provider) {
|
||||
var denyLocalLoginProviders = _.filter(externalLoginInfo.providers, x => x.properties.UmbracoBackOfficeExternalLoginOptions.DenyLocalLogin);
|
||||
var withInviteLink = _.filter(denyLocalLoginProviders, x => x.properties.UmbracoBackOfficeExternalLoginOptions.CustomUserInviteLink);
|
||||
return withInviteLink.length > 0 ? withInviteLink[0].properties.UmbracoBackOfficeExternalLoginOptions.CustomUserInviteLink : null;
|
||||
}
|
||||
else {
|
||||
return provider.properties.UmbracoBackOfficeExternalLoginOptions.CustomUserInviteLink;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
hasDenyLocalLogin: hasDenyLocalLogin,
|
||||
getLoginProviders: getLoginProviders
|
||||
getLoginProviders: getLoginProviders,
|
||||
getUserInviteLink: getUserInviteLink
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('externalLoginInfoService', externalLoginInfoService);
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<div ng-repeat="login in externalLoginProviders">
|
||||
|
||||
<div ng-if="!login.properties.UmbracoBackOffice_DenyLocalLogin">
|
||||
<div ng-if="!login.properties.UmbracoBackOfficeExternalLoginOptions.DenyLocalLogin">
|
||||
<form ng-submit="linkProvider($event)" ng-if="login.linkedProviderKey == undefined" method="POST" action="{{externalLinkLoginFormAction}}" name="oauthloginform" id="oauthloginform-{{login.authType}}">
|
||||
<input type="hidden" name="provider" value="{{login.authType}}" />
|
||||
<button class="btn btn-block btn-social"
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
<umb-button
|
||||
ng-if="defaultButton"
|
||||
alias="{{defaultButton.alias ? defaultButton.alias : 'groupPrimary' }}"
|
||||
type="button"
|
||||
type="{{defaultButton.type}}"
|
||||
action="defaultButton.handler()"
|
||||
href="{{defaultButton.href}}"
|
||||
href-target="{{defaultButton.hrefTarget}}"
|
||||
button-style="{{buttonStyle}}"
|
||||
state="state"
|
||||
label="{{defaultButton.labelKey}}"
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<a ng-if="vm.type === 'link'"
|
||||
ng-href="{{vm.href}}"
|
||||
ng-attr-target="{{(vm.hrefTarget) ? vm.hrefTarget : undefined}}"
|
||||
class="btn umb-button__button {{vm.style}} umb-button--{{vm.size}} umb-outline"
|
||||
ng-click="vm.clickButton($event)"
|
||||
hotkey="{{vm.shortcut}}"
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
vm.denyLocalLogin = externalLoginInfoService.hasDenyLocalLogin();
|
||||
|
||||
// No buttons with denyLocalLogin
|
||||
// No default buttons with denyLocalLogin
|
||||
// Don't show the invite button if no email is configured
|
||||
if (!vm.denyLocalLogin) {
|
||||
if (Umbraco.Sys.ServerVariables.umbracoSettings.showUserInvite) {
|
||||
@@ -99,6 +99,19 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if deny local login then check if there's an invite link in the config
|
||||
|
||||
var customInviteLink = externalLoginInfoService.getUserInviteLink();
|
||||
if (customInviteLink) {
|
||||
vm.defaultButton = {
|
||||
type: "link",
|
||||
labelKey: "user_inviteUser",
|
||||
href: customInviteLink,
|
||||
hrefTarget: "_blank"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
vm.toggleFilter = toggleFilter;
|
||||
vm.setUsersViewState = setUsersViewState;
|
||||
|
||||
@@ -400,7 +400,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
else
|
||||
{
|
||||
autoLinkOptions = authType.GetExternalAuthenticationOptions();
|
||||
autoLinkOptions = authType.GetExternalSignInAutoLinkOptions();
|
||||
}
|
||||
|
||||
// Sign in the user with this external login provider if the user already has a login
|
||||
|
||||
@@ -54,14 +54,21 @@ namespace Umbraco.Web.Security
|
||||
public static string GetAutoLoginProvider(this IAuthenticationManager manager)
|
||||
{
|
||||
var found = manager.GetExternalAuthenticationTypes()
|
||||
.LastOrDefault(p => p.Properties.ContainsKey(Constants.Security.BackOfficeAuthenticationType) && p.Properties.ContainsKey(Constants.Security.BackOfficeExternalAuthenticationAutoLoginRedirectProperty));
|
||||
.LastOrDefault(p => p.Properties.ContainsKey(Constants.Security.BackOfficeAuthenticationType)
|
||||
&& p.Properties.TryGetValue(Constants.Security.BackOfficeExternalLoginOptionsProperty, out var options)
|
||||
&& options is BackOfficeExternalLoginProviderOptions externalLoginProviderOptions
|
||||
&& externalLoginProviderOptions.AutoRedirectLoginToExternalProvider);
|
||||
|
||||
return found?.AuthenticationType;
|
||||
}
|
||||
|
||||
public static bool HasDenyLocalLogin(this IAuthenticationManager manager)
|
||||
{
|
||||
return manager.GetExternalAuthenticationTypes().Any(p => p.Properties.ContainsKey(Constants.Security.BackOfficeExternalAuthenticationDenyLocalLoginProperty));
|
||||
return manager.GetExternalAuthenticationTypes()
|
||||
.Any(p => p.Properties.ContainsKey(Constants.Security.BackOfficeAuthenticationType)
|
||||
&& p.Properties.TryGetValue(Constants.Security.BackOfficeExternalLoginOptionsProperty, out var options)
|
||||
&& options is BackOfficeExternalLoginProviderOptions externalLoginProviderOptions
|
||||
&& externalLoginProviderOptions.DenyLocalLogin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,81 +9,62 @@ namespace Umbraco.Web.Security
|
||||
{
|
||||
public static class AuthenticationOptionsExtensions
|
||||
{
|
||||
// these are used for backwards compat
|
||||
private const string ExternalSignInAutoLinkOptionsProperty = "ExternalSignInAutoLinkOptions";
|
||||
private const string ChallengeResultCallbackProperty = "ChallengeResultCallback";
|
||||
|
||||
/// <summary>
|
||||
/// When trying to implement an Azure AD B2C provider or other OAuth provider that requires a customized Challenge Result in order to work then
|
||||
/// this must be used.
|
||||
/// Used to specify all back office external login options
|
||||
/// </summary>
|
||||
/// <param name="authOptions"></param>
|
||||
/// <param name="authProperties"></param>
|
||||
/// <remarks>
|
||||
/// See: http://issues.umbraco.org/issue/U4-7353
|
||||
/// </remarks>
|
||||
/// <param name="externalLoginProviderOptions"></param>
|
||||
public static void SetBackOfficeExternalLoginProviderOptions(this AuthenticationOptions authOptions,
|
||||
BackOfficeExternalLoginProviderOptions externalLoginProviderOptions)
|
||||
{
|
||||
authOptions.Description.Properties[Constants.Security.BackOfficeExternalLoginOptionsProperty] = externalLoginProviderOptions;
|
||||
|
||||
// for backwards compat, we need to add these:
|
||||
if (externalLoginProviderOptions.AutoLinkOptions != null)
|
||||
authOptions.Description.Properties[ExternalSignInAutoLinkOptionsProperty] = externalLoginProviderOptions.AutoLinkOptions;
|
||||
if (externalLoginProviderOptions.OnChallenge != null)
|
||||
authOptions.Description.Properties[ChallengeResultCallbackProperty] = externalLoginProviderOptions.OnChallenge;
|
||||
}
|
||||
|
||||
[Obsolete("Use SetBackOfficeExternalLoginProviderOptions instead")]
|
||||
public static void SetSignInChallengeResultCallback(
|
||||
this AuthenticationOptions authOptions,
|
||||
Func<IOwinContext, AuthenticationProperties> authProperties)
|
||||
{
|
||||
authOptions.Description.Properties["ChallengeResultCallback"] = authProperties;
|
||||
authOptions.Description.Properties[ChallengeResultCallbackProperty] = authProperties;
|
||||
}
|
||||
|
||||
public static AuthenticationProperties GetSignInChallengeResult(this AuthenticationDescription authenticationDescription, IOwinContext ctx)
|
||||
{
|
||||
if (authenticationDescription.Properties.ContainsKey("ChallengeResultCallback") == false) return null;
|
||||
var cb = authenticationDescription.Properties["ChallengeResultCallback"] as Func<IOwinContext, AuthenticationProperties>;
|
||||
if (authenticationDescription.Properties.ContainsKey(ChallengeResultCallbackProperty) == false) return null;
|
||||
var cb = authenticationDescription.Properties[ChallengeResultCallbackProperty] as Func<IOwinContext, AuthenticationProperties>;
|
||||
if (cb == null) return null;
|
||||
return cb(ctx);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used during the External authentication process to assign external sign-in options
|
||||
/// that are used by the Umbraco authentication process.
|
||||
/// </summary>
|
||||
/// <param name="authOptions"></param>
|
||||
/// <param name="options"></param>
|
||||
[Obsolete("Use SetBackOfficeExternalLoginProviderOptions instead")]
|
||||
public static void SetExternalSignInAutoLinkOptions(
|
||||
this AuthenticationOptions authOptions,
|
||||
ExternalSignInAutoLinkOptions options)
|
||||
{
|
||||
authOptions.Description.Properties["ExternalSignInAutoLinkOptions"] = options;
|
||||
authOptions.Description.Properties[ExternalSignInAutoLinkOptionsProperty] = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used during the External authentication process to retrieve external sign-in options
|
||||
/// that have been set with SetExternalAuthenticationOptions
|
||||
/// </summary>
|
||||
/// <param name="authenticationDescription"></param>
|
||||
[Obsolete("Use GetExternalSignInAutoLinkOptions instead")]
|
||||
public static ExternalSignInAutoLinkOptions GetExternalAuthenticationOptions(this AuthenticationDescription authenticationDescription)
|
||||
=> authenticationDescription.GetExternalSignInAutoLinkOptions();
|
||||
|
||||
public static ExternalSignInAutoLinkOptions GetExternalSignInAutoLinkOptions(this AuthenticationDescription authenticationDescription)
|
||||
{
|
||||
if (authenticationDescription.Properties.ContainsKey("ExternalSignInAutoLinkOptions") == false) return null;
|
||||
var options = authenticationDescription.Properties["ExternalSignInAutoLinkOptions"] as ExternalSignInAutoLinkOptions;
|
||||
if (authenticationDescription.Properties.ContainsKey(ExternalSignInAutoLinkOptionsProperty) == false) return null;
|
||||
var options = authenticationDescription.Properties[ExternalSignInAutoLinkOptionsProperty] as ExternalSignInAutoLinkOptions;
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When set this will disable all local login ability within Umbraco
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <remarks>
|
||||
/// Even if there are multiple OAuth providers installed if any of these specifies this option then all local login ability is disabled.
|
||||
/// </remarks>
|
||||
public static void DenyLocalLogin(this AuthenticationOptions options)
|
||||
{
|
||||
options.Description.Properties[Constants.Security.BackOfficeExternalAuthenticationDenyLocalLoginProperty] = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When specified this will automatically redirect to the OAuth login provider instead of prompting the user to click on the OAuth button first.
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <remarks>
|
||||
/// This is generally used in conjunction with <see cref="DenyLocalLogin(AuthenticationOptions)"/>. If more than one OAuth provider specifies this, the last registered
|
||||
/// provider's redirect settings will win.
|
||||
/// </remarks>
|
||||
public static void AutoLoginRedirect(this AuthenticationOptions options)
|
||||
{
|
||||
options.Description.Properties[Constants.Security.BackOfficeExternalAuthenticationAutoLoginRedirectProperty] = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the properties of the authentication description instance for use with Umbraco back office
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Security;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Options used to configure back office external login providers
|
||||
/// </summary>
|
||||
public class BackOfficeExternalLoginProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// When specified this will be called to retrieve the <see cref="AuthenticationProperties"/> used during the authentication Challenge response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For example, when trying to implement an Azure AD B2C provider or other OAuth provider that requires a customized Challenge Result in order to work then
|
||||
/// this must be used.
|
||||
/// See: http://issues.umbraco.org/issue/U4-7353
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
public Func<IOwinContext, AuthenticationProperties> OnChallenge { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Options used to control how users can be auto-linked/created/updated based on the external login provider
|
||||
/// </summary>
|
||||
[IgnoreDataMember] // we are ignoring this one from serialization for backwards compat since these options are manually incuded in the response separately
|
||||
public ExternalSignInAutoLinkOptions AutoLinkOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When set to true will disable all local user login functionality
|
||||
/// </summary>
|
||||
public bool DenyLocalLogin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If specified and <see cref="DenyLocalLogin"/> is true then the user invite button in the back office will link through to this custom URL
|
||||
/// </summary>
|
||||
public string CustomUserInviteLink { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When specified this will automatically redirect to the OAuth login provider instead of prompting the user to click on the OAuth button first.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is generally used in conjunction with <see cref="DenyLocalLogin"/>. If more than one OAuth provider specifies this, the last registered
|
||||
/// provider's redirect settings will win.
|
||||
/// </remarks>
|
||||
public bool AutoRedirectLoginToExternalProvider { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
@@ -7,6 +8,7 @@ using Umbraco.Core.Models.Identity;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Options used to configure auto-linking external OAuth providers
|
||||
/// </summary>
|
||||
@@ -33,12 +35,14 @@ namespace Umbraco.Web.Security
|
||||
/// <summary>
|
||||
/// A callback executed during account auto-linking and before the user is persisted
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Action<BackOfficeIdentityUser, ExternalLoginInfo> OnAutoLinking { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A callback executed during every time a user authenticates using an external login.
|
||||
/// returns a boolean indicating if sign in should continue or not.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Func<BackOfficeIdentityUser, ExternalLoginInfo, bool> OnExternalLogin { get; set; }
|
||||
|
||||
|
||||
|
||||
@@ -257,6 +257,7 @@
|
||||
<Compile Include="Search\ExamineUserComponent.cs" />
|
||||
<Compile Include="Search\IUmbracoTreeSearcherFields.cs" />
|
||||
<Compile Include="Search\UmbracoTreeSearcherFields.cs" />
|
||||
<Compile Include="Security\BackOfficeExternalLoginProviderOptions.cs" />
|
||||
<Compile Include="Services\DashboardService.cs" />
|
||||
<Compile Include="Services\IDashboardService.cs" />
|
||||
<Compile Include="Models\Link.cs" />
|
||||
|
||||
Reference in New Issue
Block a user