public async Task <ActionResult <LogInStatus> > Login(LoginData loginData, CancellationToken cancellationToken = default) { return(await _exceptionHandler.HandleExceptionAsync <ActionResult <LogInStatus> >(async c => { var userName = loginData.UserName.Trim(); var password = loginData.Password.Trim(); User user = await _userQueryableDomainService.Get().SingleOrDefaultAsync(x => x.LoginData.UserName == userName, c).ConfigureAwait(false); if (user.IsNull()) { return NotFound(new LogInStatus { ErrorMessage = "User not present in the system.Please register." }); } else if (await _tokenManager.ValidateTokenAsync(user.Id.ToString(), null, c)) { var loggedInTokenCacheData = await _tokenManager.GetTokenCacheDataAsync(user.Id.ToString(), c); return BadRequest(new LogInStatus { ErrorMessage = "User already logged-in.", Token = loggedInTokenCacheData.Token }); } else if (!PasswordUtility.VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt)) { return NotFound(new LogInStatus { ErrorMessage = "Password incorrect for " + userName + "." }); } else { var userIdString = user.Id.ToString(); var audienceConfig = _configuration.GetSection("Audience"); var jwtToken = await _tokenManager.CreateTokenAsync(new TokenInputData { Issuer = audienceConfig["Iss"], Audience = audienceConfig["Aud"], Secret = audienceConfig["Secret"], Key = userIdString, Expiration = TimeSpan.FromDays(1),//TODO - should be taken from config or "config DB" TokenIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, userIdString), ClaimsToConsiderAfterTokenValidation = new List <Claim> { new Claim(ClaimTypes.Role, user.Role.ToString()) ///Add more claims here, if needed, to suit application needs } }); return Ok(new LogInStatus { Token = jwtToken }); } }, cancellationToken)); }