public BusinessOperationResult <UserCredentials> VerifyTotp(int userId, string totp) { var userCredential = _readOnlyContext.UserCredentialReadOnlyRepository.GetByUserId(userId); if (userCredential != null) { if (userCredential.TwoFactorEnabled && !string.IsNullOrWhiteSpace(userCredential.TwoFactorKey)) { var encryptedKey = Convert.FromBase64String(userCredential.TwoFactorKey); var key = Decrypt(encryptedKey); Totp totpAlgo = new Totp(key, 30, OtpHashMode.Sha1, 6); if (totpAlgo.VerifyTotp(totp, out long timeStepMatched, new VerificationWindow(2, 2))) { var redisKey = $"TOTP-{userId}-{timeStepMatched}"; if (!_redisCache.Exists(redisKey)) { _redisCache.StringSet(redisKey, string.Empty, TimeSpan.FromSeconds(30)); return(new BusinessOperationResult <UserCredentials>() { ErrorCode = 0, Entity = userCredential }); } else { return(new BusinessOperationResult <UserCredentials>() { ErrorCode = 1004, ErrorMessage = "TOTP already used once. retry after some time." }); } } else { return(new BusinessOperationResult <UserCredentials>() { ErrorCode = 1003, ErrorMessage = "Invalid TOTP." }); } } else { return(new BusinessOperationResult <UserCredentials>() { ErrorCode = 1002, ErrorMessage = "Two factor authentication is not enabled." }); } }
public async Task Invoke(HttpContext httpContext, IRedisCache redisCache) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (redisCache == null) { throw new ArgumentNullException(nameof(redisCache)); } Task task = null; var requestId = httpContext.Request.Headers["x-request-id"]; if (!string.IsNullOrWhiteSpace(requestId)) { if (((string)requestId).Length > 40) { httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; await httpContext.Response.WriteAsync("Invalid x-request-id. x-request-id can have upto 40 charcters."); return; } if (redisCache.Exists($"req-{requestId}")) { httpContext.Response.StatusCode = StatusCodes.Status409Conflict; await httpContext.Response.WriteAsync("{ \"x-request-id\": [ \"duplicate request id.\" ] } "); return; } else { task = redisCache.StringSetAsync($"req-{requestId}", "", TimeSpan.FromMinutes(5)); } } await _next(httpContext); if (task != null) { await task; } }