Skip to content

Commit

Permalink
finish account recovery
Browse files Browse the repository at this point in the history
  • Loading branch information
GNUGradyn committed Jun 8, 2024
1 parent 1a00499 commit 90b60a4
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 1 deletion.
21 changes: 20 additions & 1 deletion JournalyApiV2/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class AuthController : JournalyControllerBase
{
private readonly IAuthService _authService;
private readonly ICryptoService _cryptoService;

public AuthController(IAuthService authService, ICryptoService cryptoService)
{
_authService = authService;
Expand Down Expand Up @@ -241,4 +241,23 @@ public async Task<JsonResult> GetRecoveryKeys()
{
return new JsonResult(await _authService.GetRecoveryKeys(GetRecoveryToken()));
}

[Route("recover-account")]
[AllowAnonymous]
[HttpPost]
public async Task<JsonResult> RecoverAccount([FromBody] RecoverAccountRequest request)
{
var userId = await _authService.GetUserIdFromRecoveryToken(GetRecoveryToken());
if (userId == null) throw new BadRequestException("Invalid recovery token");
await _authService.RecoverAccount(userId.Value, request.passwordHash, new CryptographicKey
{
DEK = request.DEK,
Salt = request.Salt,
Type = (int)EncryptedDEKType.Primary
});
return new JsonResult(new AuthenticationResponse
{
Token = await _authService.IssueToken(userId.Value)
});
}
}
8 changes: 8 additions & 0 deletions JournalyApiV2/Models/Requests/RecoverAccountRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace JournalyApiV2.Models.Requests;

public class RecoverAccountRequest
{
public string DEK { get; set; }
public string Salt { get; set; }
public string passwordHash { get; set; }
}
21 changes: 21 additions & 0 deletions JournalyApiV2/Services/BLL/AuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public async Task<AuthenticationResponse> SignIn(string email, string password)
}
}

public async Task<string> IssueToken(Guid userId)
{
return await _authDbService.GenerateToken(userId);
}

public async Task VoidToken(string token)
{
await _authDbService.RevokeToken(token);
Expand Down Expand Up @@ -221,4 +226,20 @@ public async Task<CryptographicKey[]> GetRecoveryKeys(string recoveryToken)
{
return await _authDbService.GetRecoveryKeys(recoveryToken);
}

public async Task RecoverAccount(Guid userId, string passwordHash, CryptographicKey primaryKey)
{
if (primaryKey.Type != 1) throw new ArgumentException("Key must be a primary key");
var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null) throw new ArgumentException("UserID invalid");
var resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
await _userManager.ResetPasswordAsync(user, resetToken, passwordHash);
await _cryptoDbService.UpdateDEKForUser(userId, primaryKey.DEK, primaryKey.Salt, EncryptedDEKType.Primary);
await _authDbService.ClearRecoveryTokens(userId);
}

public async Task<Guid?> GetUserIdFromRecoveryToken(string recoveryToken)
{
return await _authDbService.GetUserIdFromRecoveryToken(recoveryToken);
}
}
3 changes: 3 additions & 0 deletions JournalyApiV2/Services/BLL/IAuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ public interface IAuthService
Task<string> IssueRecoveryTokenWithShortCode(string email, string shortCode);
Task<string> IssueRecoveryTokenWithLongCode(string longCode);
Task<CryptographicKey[]> GetRecoveryKeys(string recoveryToken);
Task RecoverAccount(Guid userId, string passwordHash, CryptographicKey primaryKey);
Task<Guid?> GetUserIdFromRecoveryToken(string recoveryToken);
Task<string> IssueToken(Guid userId);
}
17 changes: 17 additions & 0 deletions JournalyApiV2/Services/DAL/AuthDbService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using JournalyApiV2.Data;
using JournalyApiV2.Data.Models;
using JournalyApiV2.Models;
Expand Down Expand Up @@ -233,4 +234,20 @@ public async Task<CryptographicKey[]> GetRecoveryKeys(string recoveryToken)
Type = x.EncryptedDEKTypeId
}).ToArray();
}

public async Task ClearRecoveryTokens(Guid userId)
{
await using var db = _db.Journaly();
db.RemoveRange(db.AccountRecoveryTokens.Where(x => x.UserId == userId));
await db.SaveChangesAsync();
}

public async Task<Guid?> GetUserIdFromRecoveryToken(string recoveryToken)
{
await using var db = _db.Journaly();

var recoveryTokenObj = await db.AccountRecoveryTokens.SingleOrDefaultAsync(x => x.Token == recoveryToken);

return recoveryTokenObj?.UserId;
}
}
2 changes: 2 additions & 0 deletions JournalyApiV2/Services/DAL/IAuthDbService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public interface IAuthDbService
Task RevokeTokens(Guid userId, string[]? exclude);
Task<string> IssueRecoveryToken(Guid userId);
Task<CryptographicKey[]> GetRecoveryKeys(string recoveryToken);
Task ClearRecoveryTokens(Guid userId);
Task<Guid?> GetUserIdFromRecoveryToken(string recoveryToken);
}

0 comments on commit 90b60a4

Please sign in to comment.