25 changed files with 91 additions and 124 deletions
@ -1,11 +1,9 @@
@@ -1,11 +1,9 @@
|
||||
using Bit.Core.Services; |
||||
using Microsoft.AspNetCore.Authentication; |
||||
using Microsoft.AspNetCore.Http; |
||||
using Microsoft.AspNetCore.Identity; |
||||
using Microsoft.Extensions.Logging; |
||||
using Microsoft.Extensions.Options; |
||||
|
||||
namespace Bit.Core.Identity; |
||||
namespace Bit.Admin.IdentityServer; |
||||
|
||||
public class PasswordlessSignInManager<TUser> : SignInManager<TUser> where TUser : class
|
||||
{ |
||||
@ -1,108 +1,107 @@
@@ -1,108 +1,107 @@
|
||||
using Microsoft.AspNetCore.Identity; |
||||
|
||||
namespace Bit.Core.Identity; |
||||
namespace Bit.Admin.IdentityServer; |
||||
|
||||
public abstract class ReadOnlyIdentityUserStore : |
||||
IUserStore<IdentityUser>, |
||||
IUserEmailStore<IdentityUser>, |
||||
IUserSecurityStampStore<IdentityUser> |
||||
{ |
||||
public void Dispose() { } |
||||
|
||||
public Task<IdentityResult> CreateAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public Task<IdentityResult> DeleteAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public abstract Task<IdentityUser> FindByEmailAsync(string normalizedEmail, |
||||
CancellationToken cancellationToken = default(CancellationToken)); |
||||
CancellationToken cancellationToken = default); |
||||
|
||||
public abstract Task<IdentityUser> FindByIdAsync(string userId, |
||||
CancellationToken cancellationToken = default(CancellationToken)); |
||||
CancellationToken cancellationToken = default); |
||||
|
||||
public async Task<IdentityUser> FindByNameAsync(string normalizedUserName, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return await FindByEmailAsync(normalizedUserName, cancellationToken); |
||||
} |
||||
|
||||
public Task<string> GetEmailAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(user.Email); |
||||
} |
||||
|
||||
public Task<bool> GetEmailConfirmedAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(user.EmailConfirmed); |
||||
} |
||||
|
||||
public Task<string> GetNormalizedEmailAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(user.Email); |
||||
} |
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(user.Email); |
||||
} |
||||
|
||||
public Task<string> GetUserIdAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(user.Id); |
||||
} |
||||
|
||||
public Task<string> GetUserNameAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(user.Email); |
||||
} |
||||
|
||||
public Task SetEmailAsync(IdentityUser user, string email, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public Task SetEmailConfirmedAsync(IdentityUser user, bool confirmed, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public Task SetNormalizedEmailAsync(IdentityUser user, string normalizedEmail, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
user.NormalizedEmail = normalizedEmail; |
||||
return Task.FromResult(0); |
||||
} |
||||
|
||||
public Task SetNormalizedUserNameAsync(IdentityUser user, string normalizedName, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
user.NormalizedUserName = normalizedName; |
||||
return Task.FromResult(0); |
||||
} |
||||
|
||||
public Task SetUserNameAsync(IdentityUser user, string userName, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public Task<IdentityResult> UpdateAsync(IdentityUser user, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
CancellationToken cancellationToken = default) |
||||
{ |
||||
return Task.FromResult(IdentityResult.Success); |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
using Bit.Core.Entities; |
||||
using Bit.Core.Identity; |
||||
using Bit.Core.Settings; |
||||
using Microsoft.AspNetCore.Identity; |
||||
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
||||
namespace Bit.Admin.IdentityServer; |
||||
|
||||
public static class ServiceCollectionExtensions |
||||
{ |
||||
public static Tuple<IdentityBuilder, IdentityBuilder> AddPasswordlessIdentityServices<TUserStore>( |
||||
this IServiceCollection services, GlobalSettings globalSettings) where TUserStore : class
|
||||
{ |
||||
services.TryAddTransient<ILookupNormalizer, LowerInvariantLookupNormalizer>(); |
||||
services.Configure<DataProtectionTokenProviderOptions>(options => |
||||
{ |
||||
options.TokenLifespan = TimeSpan.FromMinutes(15); |
||||
}); |
||||
|
||||
var passwordlessIdentityBuilder = services.AddIdentity<IdentityUser, Role>() |
||||
.AddUserStore<TUserStore>() |
||||
.AddRoleStore<RoleStore>() |
||||
.AddDefaultTokenProviders(); |
||||
|
||||
var regularIdentityBuilder = services.AddIdentityCore<User>() |
||||
.AddUserStore<UserStore>(); |
||||
|
||||
services.TryAddScoped<PasswordlessSignInManager<IdentityUser>, PasswordlessSignInManager<IdentityUser>>(); |
||||
|
||||
services.ConfigureApplicationCookie(options => |
||||
{ |
||||
options.LoginPath = "/login"; |
||||
options.LogoutPath = "/"; |
||||
options.AccessDeniedPath = "/login?accessDenied=true"; |
||||
options.Cookie.Name = $"Bitwarden_{globalSettings.ProjectName}"; |
||||
options.Cookie.HttpOnly = true; |
||||
options.ExpireTimeSpan = TimeSpan.FromDays(2); |
||||
options.ReturnUrlParameter = "returnUrl"; |
||||
options.SlidingExpiration = true; |
||||
}); |
||||
|
||||
return new Tuple<IdentityBuilder, IdentityBuilder>(passwordlessIdentityBuilder, regularIdentityBuilder); |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
using Bit.Core.Repositories; |
||||
using Bit.Core.Services; |
||||
using Microsoft.AspNetCore.Identity; |
||||
|
||||
namespace Bit.Core.Identity; |
||||
|
||||
public class ReadOnlyDatabaseIdentityUserStore : ReadOnlyIdentityUserStore |
||||
{ |
||||
private readonly IUserService _userService; |
||||
private readonly IUserRepository _userRepository; |
||||
|
||||
public ReadOnlyDatabaseIdentityUserStore( |
||||
IUserService userService, |
||||
IUserRepository userRepository) |
||||
{ |
||||
_userService = userService; |
||||
_userRepository = userRepository; |
||||
} |
||||
|
||||
public override async Task<IdentityUser> FindByEmailAsync(string normalizedEmail, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
var user = await _userRepository.GetByEmailAsync(normalizedEmail); |
||||
return user?.ToIdentityUser(await _userService.TwoFactorIsEnabledAsync(user)); |
||||
} |
||||
|
||||
public override async Task<IdentityUser> FindByIdAsync(string userId, |
||||
CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
if (!Guid.TryParse(userId, out var userIdGuid)) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
var user = await _userRepository.GetByIdAsync(userIdGuid); |
||||
return user?.ToIdentityUser(await _userService.TwoFactorIsEnabledAsync(user)); |
||||
} |
||||
} |
||||
@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
|
||||
using Bit.Core.Settings; |
||||
using IdentityServer4.Models; |
||||
|
||||
namespace Bit.Core.IdentityServer; |
||||
namespace Bit.Identity.IdentityServer; |
||||
|
||||
public class ApiClient : Client |
||||
{ |
||||
@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
|
||||
using IdentityModel; |
||||
using IdentityServer4.Models; |
||||
|
||||
namespace Bit.Core.IdentityServer; |
||||
namespace Bit.Identity.IdentityServer; |
||||
|
||||
public class ApiResources |
||||
{ |
||||
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
||||
using IdentityServer4.Models; |
||||
|
||||
namespace Bit.Core.IdentityServer; |
||||
namespace Bit.Identity.IdentityServer; |
||||
|
||||
public class ApiScopes |
||||
{ |
||||
@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
|
||||
using Bit.Core.Entities; |
||||
using Bit.Core.Models.Business; |
||||
|
||||
namespace Bit.Core.IdentityServer; |
||||
namespace Bit.Identity.IdentityServer; |
||||
|
||||
public class CustomValidatorRequestContext |
||||
{ |
||||
Loading…
Reference in new issue