add passkey infrastructure
This commit is contained in:
@ -463,5 +463,55 @@ namespace Oqtane.Controllers
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/<controller>/passkey
|
||||
[HttpGet("passkey")]
|
||||
[Authorize]
|
||||
public async Task<IEnumerable<Passkey>> GetPasskeys()
|
||||
{
|
||||
return await _userManager.GetPasskeys(_userPermissions.GetUser(User).UserId);
|
||||
}
|
||||
|
||||
// POST api/<controller>/passkey
|
||||
[HttpPost("passkey")]
|
||||
[Authorize]
|
||||
public async Task AddPasskey([FromBody] Passkey passkey)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
passkey.UserId = _userPermissions.GetUser(User).UserId;
|
||||
await _userManager.AddPasskey(passkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Passkey Post Attempt {PassKey}", passkey);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
// PUT api/<controller>/passkey
|
||||
[HttpPut("passkey")]
|
||||
[Authorize]
|
||||
public async Task UpdatePasskey([FromBody] Passkey passkey)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
passkey.UserId = _userPermissions.GetUser(User).UserId;
|
||||
await _userManager.UpdatePasskey(passkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Passkey Put Attempt {PassKey}", passkey);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/passkey?id=x
|
||||
[HttpDelete("passkey")]
|
||||
[Authorize]
|
||||
public async Task DeletePasskey(byte[] id)
|
||||
{
|
||||
await _userManager.DeletePasskey(_userPermissions.GetUser(User).UserId, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Policy;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
@ -35,6 +36,10 @@ namespace Oqtane.Managers
|
||||
Task<UserValidateResult> ValidateUser(string username, string email, string password);
|
||||
Task<bool> ValidatePassword(string password);
|
||||
Task<Dictionary<string, string>> ImportUsers(int siteId, string filePath, bool notify);
|
||||
Task<List<Passkey>> GetPasskeys(int userId);
|
||||
Task AddPasskey(Passkey passkey);
|
||||
Task UpdatePasskey(Passkey passkey);
|
||||
Task DeletePasskey(int userId, byte[] credentialId);
|
||||
}
|
||||
|
||||
public class UserManager : IUserManager
|
||||
@ -369,15 +374,6 @@ namespace Oqtane.Managers
|
||||
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||
if (identityuser != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var passKeysFunctional = await _identityUserManager.GetPasskeysAsync(identityuser);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var error = ex.ToString();
|
||||
}
|
||||
|
||||
var result = await _identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, true);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
@ -827,5 +823,72 @@ namespace Oqtane.Managers
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<Passkey>> GetPasskeys(int userId)
|
||||
{
|
||||
var passkeys = new List<Passkey>();
|
||||
var user = _users.GetUser(userId);
|
||||
if (user != null)
|
||||
{
|
||||
var identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||
if (identityuser != null)
|
||||
{
|
||||
var userpasskeys = await _identityUserManager.GetPasskeysAsync(identityuser);
|
||||
foreach (var userpasskey in userpasskeys)
|
||||
{
|
||||
passkeys.Add(new Passkey { CredentialId = userpasskey.CredentialId, Name = userpasskey.Name, UserId = userId });
|
||||
}
|
||||
}
|
||||
}
|
||||
return passkeys;
|
||||
}
|
||||
|
||||
public async Task AddPasskey(Passkey passkey)
|
||||
{
|
||||
var user = _users.GetUser(passkey.UserId);
|
||||
if (user != null)
|
||||
{
|
||||
var identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||
if (identityuser != null)
|
||||
{
|
||||
var attestationResult = await _identitySignInManager.PerformPasskeyAttestationAsync(passkey.CredentialJson);
|
||||
if (attestationResult.Succeeded)
|
||||
{
|
||||
var addPasskeyResult = await _identityUserManager.AddOrUpdatePasskeyAsync(identityuser, attestationResult.Passkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdatePasskey(Passkey passkey)
|
||||
{
|
||||
var user = _users.GetUser(passkey.UserId);
|
||||
if (user != null)
|
||||
{
|
||||
var identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||
if (identityuser != null)
|
||||
{
|
||||
var userPasskeyInfo = await _identityUserManager.GetPasskeyAsync(identityuser, passkey.CredentialId);
|
||||
if (userPasskeyInfo != null)
|
||||
{
|
||||
userPasskeyInfo.Name = passkey.Name;
|
||||
await _identityUserManager.AddOrUpdatePasskeyAsync(identityuser, userPasskeyInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeletePasskey(int userId, byte[] credentialId)
|
||||
{
|
||||
var user = _users.GetUser(userId);
|
||||
if (user != null)
|
||||
{
|
||||
var identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||
if (identityuser != null)
|
||||
{
|
||||
await _identityUserManager.RemovePasskeyAsync(identityuser, credentialId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
|
||||
namespace Oqtane.Migrations.EntityBuilders
|
||||
{
|
||||
public class AspNetUserTokensEntityBuilder : BaseEntityBuilder<AspNetUserTokensEntityBuilder>
|
||||
{
|
||||
private const string _entityTableName = "AspNetUserTokens";
|
||||
private readonly PrimaryKey<AspNetUserTokensEntityBuilder> _primaryKey = new("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||
private readonly ForeignKey<AspNetUserTokensEntityBuilder> _aspNetUsersForeignKey = new("FK_AspNetUserTokens_AspNetUsers_UserId", x => x.UserId, "AspNetUsers", "Id", ReferentialAction.Cascade);
|
||||
|
||||
public AspNetUserTokensEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
|
||||
{
|
||||
EntityTableName = _entityTableName;
|
||||
PrimaryKey = _primaryKey;
|
||||
ForeignKeys.Add(_aspNetUsersForeignKey);
|
||||
}
|
||||
|
||||
protected override AspNetUserTokensEntityBuilder BuildTable(ColumnsBuilder table)
|
||||
{
|
||||
UserId = AddStringColumn(table, "UserId", 450);
|
||||
LoginProvider = AddStringColumn(table, "LoginProvider", 128);
|
||||
Name = AddStringColumn(table, "Name", 128);
|
||||
Value = AddMaxStringColumn(table, "Value", true);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public OperationBuilder<AddColumnOperation> UserId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> LoginProvider { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Value { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Migrations.EntityBuilders;
|
||||
using Oqtane.Repository;
|
||||
|
||||
namespace Oqtane.Migrations.Tenant
|
||||
{
|
||||
[DbContext(typeof(TenantDBContext))]
|
||||
[Migration("Tenant.10.00.00.02")]
|
||||
public class AddAspNetUserTokens : MultiDatabaseMigration
|
||||
{
|
||||
public AddAspNetUserTokens(IDatabase database) : base(database)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var aspNetUserTokensEntityBuilder = new AspNetUserTokensEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
aspNetUserTokensEntityBuilder.Create();
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user