update identity integration
This commit is contained in:
@@ -4,11 +4,6 @@ public static partial class Constants
|
||||
{
|
||||
public const string ErrorFieldNone = "__zero_no_field";
|
||||
|
||||
public static partial class Tabs
|
||||
{
|
||||
public const string General = "general";
|
||||
}
|
||||
|
||||
public static partial class Auth
|
||||
{
|
||||
public const string SystemUser = "system";
|
||||
@@ -17,86 +12,11 @@ public static partial class Constants
|
||||
public const string BackofficeScheme = "zeroBackoffice";
|
||||
public const string BackofficeCookieName = "zero.be.session";
|
||||
public const string DefaultCookieName = "zero.session";
|
||||
|
||||
public static partial class Claims
|
||||
{
|
||||
public const string IsZero = "zero.claim.iszero";
|
||||
public const string IsSuper = "zero.claim.issuper";
|
||||
public const string UserId = "zero.claim.userid";
|
||||
public const string UserName = "zero.claim.username";
|
||||
public const string Role = "zero.claim.rolealias";
|
||||
public const string SecurityStamp = "zero.claim.securitystamp";
|
||||
public const string Email = "zero.claim.email";
|
||||
public const string Permission = "zero.claim.permission";
|
||||
public const string DefaultAppId = "zero.claim.defaultAppId";
|
||||
public const string AppId = "zero.claim.appId";
|
||||
public const string TicketExpires = "zero.claim.ticketExpires";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static partial class Permissions
|
||||
{
|
||||
public static partial class Groups
|
||||
{
|
||||
public const string Sections = "zero.permissions.groups.sections";
|
||||
public const string Spaces = "zero.permissions.groups.spaces";
|
||||
public const string Settings = "zero.permissions.groups.settings";
|
||||
public const string Pages = "zero.permissions.groups.pages";
|
||||
public const string Modules = "zero.permissions.groups.modules";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static partial class Database
|
||||
{
|
||||
public const string ReservationPrefix = "zero.";
|
||||
public const string Expires = Raven.Client.Constants.Documents.Metadata.Expires;
|
||||
}
|
||||
|
||||
public static partial class Sections
|
||||
{
|
||||
public const string Dashboard = "dashboard";
|
||||
public const string Pages = "pages";
|
||||
public const string Spaces = "spaces";
|
||||
public const string Media = "media";
|
||||
public const string Settings = "settings";
|
||||
}
|
||||
|
||||
public static partial class Settings
|
||||
{
|
||||
public const string Updates = "updates";
|
||||
public const string Applications = "applications";
|
||||
public const string Users = "users";
|
||||
public const string Languages = "languages";
|
||||
public const string Translations = "translations";
|
||||
public const string Countries = "countries";
|
||||
public const string Mails = "mailTemplates";
|
||||
public const string Integrations = "integrations";
|
||||
public const string Logging = "logs";
|
||||
public const string Plugins = "plugins";
|
||||
public const string CreatePlugin = "createplugin";
|
||||
}
|
||||
|
||||
public static partial class PermissionCollections
|
||||
{
|
||||
public const string Sections = "permissionCollectionSections";
|
||||
public const string Spaces = "permissionCollectionSpaces";
|
||||
public const string Settings = "permisssionCollectionSettings";
|
||||
public const string Modules = "permissionCollectionModules";
|
||||
}
|
||||
|
||||
public static partial class Pages
|
||||
{
|
||||
public const string FolderAlias = "zero.folder";
|
||||
public const string DefaultRootPageTypeAlias = "root";
|
||||
public const string PageRouteProviderAlias = "zero.pages";
|
||||
}
|
||||
|
||||
public static partial class Routing
|
||||
{
|
||||
public const string InternalRoutePrefix = "/__zero/";
|
||||
|
||||
public const string ErrorRoute = InternalRoutePrefix + "error";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,10 @@ public static class IdentityBuilderExtensions
|
||||
/// <summary>
|
||||
/// Adds an implementation of identity information stores.
|
||||
/// </summary>
|
||||
public static IdentityBuilder AddZeroIdentityStores<T>(this IdentityBuilder builder) where T : class, IZeroIdentityStoreDbProvider
|
||||
public static IdentityBuilder AddZeroIdentityStores(this IdentityBuilder builder)
|
||||
{
|
||||
Type userStoreType = typeof(ZeroUserStore<,>).MakeGenericType(builder.UserType, builder.RoleType);
|
||||
Type roleStoreType = typeof(ZeroRoleStore<>).MakeGenericType(builder.RoleType);
|
||||
|
||||
builder.Services.AddScoped<IZeroIdentityStoreDbProvider, T>();
|
||||
builder.Services.TryAddScoped(typeof(IUserStore<>).MakeGenericType(builder.UserType), userStoreType);
|
||||
builder.Services.TryAddScoped(typeof(IRoleStore<>).MakeGenericType(builder.RoleType), roleStoreType);
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using zero.Identity;
|
||||
|
||||
namespace zero.Identity;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the default identity system configuration for the specified User and Role types
|
||||
/// </summary>
|
||||
// public static IdentityBuilder AddZeroIdentity<TUser, TRole, TStore>(
|
||||
// this IServiceCollection services)
|
||||
// where TUser : ZeroIdentityUser, new()
|
||||
// where TRole : ZeroIdentityRole, new()
|
||||
// where TStore : class, IZeroIdentityStoreDbProvider
|
||||
// => services.AddIdentity<TUser, TRole>(setupAction: null!);
|
||||
|
||||
/// <summary>
|
||||
/// Adds and configures the identity system for the specified User and Role types
|
||||
/// </summary>
|
||||
public static IdentityBuilder AddZeroIdentity<TUser, TRole, TStore>(
|
||||
this IServiceCollection services,
|
||||
Action<IdentityOptions> setupAction
|
||||
)
|
||||
where TUser : ZeroIdentityUser, new()
|
||||
where TRole : ZeroIdentityRole, new()
|
||||
where TStore : class, IZeroIdentityStoreDbProvider
|
||||
{
|
||||
// Services used by identity
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
|
||||
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
|
||||
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
|
||||
})
|
||||
.AddCookie(IdentityConstants.ApplicationScheme, o =>
|
||||
{
|
||||
o.LoginPath = new PathString("/Account/Login");
|
||||
o.Events = new CookieAuthenticationEvents
|
||||
{
|
||||
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
|
||||
};
|
||||
})
|
||||
.AddCookie(IdentityConstants.ExternalScheme, o =>
|
||||
{
|
||||
o.Cookie.Name = IdentityConstants.ExternalScheme;
|
||||
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
})
|
||||
.AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o =>
|
||||
{
|
||||
o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme;
|
||||
o.Events = new CookieAuthenticationEvents
|
||||
{
|
||||
OnValidatePrincipal = SecurityStampValidator.ValidateAsync<ITwoFactorSecurityStampValidator>
|
||||
};
|
||||
})
|
||||
.AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
|
||||
{
|
||||
o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
|
||||
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
});
|
||||
|
||||
// Hosting doesn't add IHttpContextAccessor by default
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
// Data stores
|
||||
services.AddScoped<IZeroIdentityStoreDbProvider, TStore>();
|
||||
services.TryAddScoped<IUserStore<TUser>, ZeroUserStore<TUser>>();
|
||||
services.TryAddScoped<IRoleStore<TRole>, ZeroRoleStore<TRole>>();
|
||||
|
||||
// Identity services
|
||||
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
|
||||
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
|
||||
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
|
||||
services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
|
||||
services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
|
||||
services.TryAddScoped<IdentityErrorDescriber>();
|
||||
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
|
||||
services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
|
||||
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
|
||||
services.TryAddScoped<IUserConfirmation<TUser>, DefaultUserConfirmation<TUser>>();
|
||||
services.TryAddScoped<UserManager<TUser>>();
|
||||
services.TryAddScoped<SignInManager<TUser>>();
|
||||
services.TryAddScoped<RoleManager<TRole>>();
|
||||
|
||||
if (setupAction != null)
|
||||
{
|
||||
services.Configure(setupAction);
|
||||
}
|
||||
|
||||
return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace zero.Identity;
|
||||
|
||||
/// <summary>
|
||||
/// Represents all the options you can use to configure the cookies middleware used by the identity system.
|
||||
/// </summary>
|
||||
public class ZeroIdentityConstants
|
||||
{
|
||||
public static class CookieNames
|
||||
{
|
||||
private const string CookiePrefix = "zero.id";
|
||||
|
||||
public static readonly string Application = CookiePrefix + ".app";
|
||||
public static readonly string External = CookiePrefix + ".ext";
|
||||
public static readonly string TwoFactorRememberMe = CookiePrefix + ".2fa_rem";
|
||||
public static readonly string TwoFactorUserId = CookiePrefix + ".2fa_id";
|
||||
}
|
||||
|
||||
public static partial class Claims
|
||||
{
|
||||
private const string ClaimPrefix = "zero.claim";
|
||||
|
||||
public static readonly string IsZero = ClaimPrefix + ".iszero";
|
||||
public static readonly string UserId = ClaimPrefix + ".userid";
|
||||
public static readonly string UserName = ClaimPrefix + ".username";
|
||||
public static readonly string Role = ClaimPrefix + ".rolealias";
|
||||
public static readonly string SecurityStamp = ClaimPrefix + ".securitystamp";
|
||||
public static readonly string Email = ClaimPrefix + ".email";
|
||||
public static readonly string Permission = ClaimPrefix + ".permission";
|
||||
public static readonly string TicketExpires = ClaimPrefix + ".ticketExpires";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace zero.Identity;
|
||||
|
||||
public static class ZeroIdentityExtensions
|
||||
{
|
||||
// <summary>
|
||||
/// Adds the default identity system configuration for the specified User and Role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a User in the system.</typeparam>
|
||||
/// <typeparam name="TRole">The type representing a Role in the system.</typeparam>
|
||||
/// <param name="services">The services available in the application.</param>
|
||||
/// <returns>An <see cref="IdentityBuilder"/> for creating and configuring the identity system.</returns>
|
||||
public static IdentityBuilder AddZeroIdentity<TUser, TRole>(this IServiceCollection services)
|
||||
where TUser : ZeroIdentityUser, new()
|
||||
where TRole : ZeroIdentityRole, new() =>
|
||||
AddZeroIdentity<TUser, TRole>(services, null);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds and configures the identity system for the specified User and Role types.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type representing a User in the system.</typeparam>
|
||||
/// <typeparam name="TRole">The type representing a Role in the system.</typeparam>
|
||||
/// <param name="services">The services available in the application.</param>
|
||||
/// <param name="setupAction">An action to configure the <see cref="IdentityOptions"/>.</param>
|
||||
/// <returns>An <see cref="IdentityBuilder"/> for creating and configuring the identity system.</returns>
|
||||
public static IdentityBuilder AddZeroIdentity<TUser, TRole>(this IServiceCollection services,
|
||||
Action<IdentityOptions> setupAction)
|
||||
where TUser : ZeroIdentityUser, new()
|
||||
where TRole : ZeroIdentityRole, new()
|
||||
{
|
||||
// Services identity depends on
|
||||
services
|
||||
.AddOptions()
|
||||
.AddLogging();
|
||||
|
||||
// Services used by identity
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultScheme = IdentityConstants.ApplicationScheme;
|
||||
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
|
||||
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
|
||||
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
|
||||
})
|
||||
.AddCookie(IdentityConstants.ApplicationScheme, o =>
|
||||
{
|
||||
o.LoginPath = new PathString("/Account/Login");
|
||||
o.SlidingExpiration = true;
|
||||
o.ExpireTimeSpan = TimeSpan.FromDays(90);
|
||||
|
||||
o.Cookie.Name = ZeroIdentityConstants.CookieNames.Application;
|
||||
o.Cookie.HttpOnly = true;
|
||||
o.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||
o.Cookie.SameSite = SameSiteMode.Lax;
|
||||
o.Cookie.Path = "/";
|
||||
|
||||
o.Events = new CookieAuthenticationEvents
|
||||
{
|
||||
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
|
||||
};
|
||||
})
|
||||
.AddCookie(IdentityConstants.ExternalScheme, o =>
|
||||
{
|
||||
o.Cookie.Name = ZeroIdentityConstants.CookieNames.External;
|
||||
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
})
|
||||
.AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o =>
|
||||
{
|
||||
o.Cookie.Name = ZeroIdentityConstants.CookieNames.TwoFactorRememberMe;
|
||||
o.Events = new CookieAuthenticationEvents
|
||||
{
|
||||
OnValidatePrincipal = SecurityStampValidator.ValidateAsync<ITwoFactorSecurityStampValidator>
|
||||
};
|
||||
})
|
||||
.AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
|
||||
{
|
||||
o.Cookie.Name = ZeroIdentityConstants.CookieNames.TwoFactorUserId;
|
||||
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
});
|
||||
|
||||
// Hosting doesn't add IHttpContextAccessor by default
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
// Identity services
|
||||
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
|
||||
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
|
||||
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
|
||||
services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
|
||||
services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
|
||||
|
||||
// No interface for the error describer so we can add errors without rev'ing the interface
|
||||
services.TryAddScoped<IdentityErrorDescriber>();
|
||||
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
|
||||
services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
|
||||
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
|
||||
services.TryAddScoped<IUserConfirmation<TUser>, DefaultUserConfirmation<TUser>>();
|
||||
services.TryAddScoped<UserManager<TUser>>();
|
||||
services.TryAddScoped<SignInManager<TUser>>();
|
||||
services.TryAddScoped<RoleManager<TRole>>();
|
||||
|
||||
services.Configure<IdentityOptions>(opts =>
|
||||
{
|
||||
opts.ClaimsIdentity.UserIdClaimType = ZeroIdentityConstants.Claims.UserId;
|
||||
opts.ClaimsIdentity.UserNameClaimType = ZeroIdentityConstants.Claims.UserName;
|
||||
opts.ClaimsIdentity.RoleClaimType = ZeroIdentityConstants.Claims.Role;
|
||||
opts.ClaimsIdentity.SecurityStampClaimType = ZeroIdentityConstants.Claims.SecurityStamp;
|
||||
opts.ClaimsIdentity.EmailClaimType = ZeroIdentityConstants.Claims.Email;
|
||||
|
||||
opts.Password.RequireDigit = false;
|
||||
opts.Password.RequireLowercase = false;
|
||||
opts.Password.RequireUppercase = false;
|
||||
opts.Password.RequireNonAlphanumeric = false;
|
||||
opts.Password.RequiredLength = 8;
|
||||
opts.Password.RequiredUniqueChars = 1;
|
||||
|
||||
opts.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(60);
|
||||
opts.Lockout.MaxFailedAccessAttempts = 5;
|
||||
opts.Lockout.AllowedForNewUsers = true;
|
||||
|
||||
opts.User.RequireUniqueEmail = true;
|
||||
});
|
||||
|
||||
services.Configure<SecurityStampValidatorOptions>(opts => { opts.ValidationInterval = TimeSpan.FromMinutes(90); });
|
||||
|
||||
if (setupAction != null)
|
||||
{
|
||||
services.Configure(setupAction);
|
||||
}
|
||||
|
||||
IdentityBuilder builder = new(typeof(TUser), typeof(TRole), services);
|
||||
|
||||
builder.AddDefaultTokenProviders();
|
||||
builder.AddZeroIdentityStores();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Configures the application cookie.
|
||||
/// </summary>
|
||||
/// <param name="services">The services available in the application.</param>
|
||||
/// <param name="configure">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
|
||||
/// <returns>The services.</returns>
|
||||
public static IServiceCollection ConfigureZeroApplicationCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configure)
|
||||
=> services.Configure(IdentityConstants.ApplicationScheme, configure);
|
||||
|
||||
/// <summary>
|
||||
/// Configure the external cookie.
|
||||
/// </summary>
|
||||
/// <param name="services">The services available in the application.</param>
|
||||
/// <param name="configure">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
|
||||
/// <returns>The services.</returns>
|
||||
public static IServiceCollection ConfigureZeroExternalCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configure)
|
||||
=> services.Configure(IdentityConstants.ExternalScheme, configure);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Antiforgery;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -33,6 +34,8 @@ public class ZeroBuilder
|
||||
services.AddControllers();
|
||||
services.AddRazorPages();
|
||||
|
||||
services.Configure<AntiforgeryOptions>(opts => opts.Cookie.Name = "zero.antiforgery");
|
||||
|
||||
// adds and discovers additional and built-in assemblies
|
||||
new AssemblyDiscovery(Mvc).Execute(_startupOptions.AssemblyDiscoveryRules);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user