예제 #1
0
        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;
            }
        }