| | | 1 | | using System.Security.Claims; |
| | | 2 | | using Syki.Back.Domain.Identity; |
| | | 3 | | using Syki.Back.Features.Cross.SignIn; |
| | | 4 | | using Microsoft.AspNetCore.Authentication; |
| | | 5 | | |
| | | 6 | | namespace Syki.Back.Features.Identity.TwoFactorLogin; |
| | | 7 | | |
| | 40 | 8 | | public class TwoFactorLoginService( |
| | 40 | 9 | | SignInService service, |
| | 40 | 10 | | IHttpContextAccessor httpCtx, |
| | 40 | 11 | | UserManager<SykiUser> userManager) : ISykiService |
| | | 12 | | { |
| | | 13 | | public async Task<OneOf<TwoFactorLoginOut, SykiError>> Login(TwoFactorLoginIn data) |
| | | 14 | | { |
| | 40 | 15 | | var authResult = await httpCtx.HttpContext.AuthenticateAsync(IdentityConstants.TwoFactorUserIdScheme); |
| | 40 | 16 | | var userId = authResult.Principal?.FindFirstValue(ClaimTypes.Name); |
| | 46 | 17 | | if (userId == null) return InvalidTwoFactorToken.I; |
| | | 18 | | |
| | 34 | 19 | | var user = await userManager.FindByIdAsync(userId); |
| | 34 | 20 | | if (user == null) return InvalidTwoFactorToken.I; |
| | | 21 | | |
| | 38 | 22 | | if (await userManager.IsLockedOutAsync(user)) return InvalidTwoFactorToken.I; |
| | | 23 | | |
| | 30 | 24 | | var token = data.Token!.OnlyNumbers(); |
| | 30 | 25 | | var tokenProvider = userManager.Options.Tokens.AuthenticatorTokenProvider; |
| | 30 | 26 | | var isValid = await userManager.VerifyTwoFactorTokenAsync(user, tokenProvider, token); |
| | | 27 | | |
| | 30 | 28 | | if (!isValid) |
| | | 29 | | { |
| | 24 | 30 | | await userManager.AccessFailedAsync(user); |
| | 24 | 31 | | return InvalidTwoFactorToken.I; |
| | | 32 | | } |
| | | 33 | | |
| | 6 | 34 | | await userManager.ResetAccessFailedCountAsync(user); |
| | | 35 | | |
| | | 36 | | // Clear the 2FA cookie (we use JWT for auth) |
| | 6 | 37 | | await httpCtx.HttpContext.SignOutAsync(IdentityConstants.TwoFactorUserIdScheme); |
| | | 38 | | |
| | 6 | 39 | | var jwtResult = await service.SignIn(user.Email); |
| | | 40 | | |
| | 6 | 41 | | return jwtResult.ToTwoFactorLoginOut(); |
| | 40 | 42 | | } |
| | | 43 | | } |