mercredi 6 janvier 2021

Pattern for get user's informations in all my services from JWT token

I have an api with many controllers. One of these controllers is the authentication one. It use to get a JWT token and call others paths, from this controller or another.

My problem is, for any paths, I need to get the user id in the JWT token, and ask to the database to get informations about user, like check if the user exist or datas linked to him. So in each method, I have to call a specific method to retrieve informations.

In fact, the authentication layer is only used in order to check if the JWT Token is valid. I don't know if is it possible to add some logic in this layer. And how.

Can I implement any pattern in order to retrieve automatically user's information ?

I thought about singleton, but I'm not sure about the scope of the object. The goal is to stay in the request scope.

I thought to create an User Service, but I think it is not a good way because services are about treatment, not keep datas in these.

I thought to implement a custom middleware, but I'm not sure about the way to do it.

The objective is to implement all the user logic in the same place, and each service can call it in order to deal with it :

Request (with JWT Token) --> Controller --> Service --> Call the object with all user's stuff and logic and treatment
or
Request (with JWT token) --> middleware (get all user's informations) --> Controller --> Call the object created in middleware with all user's stuff

For information, there are my login method and the way I create the JWT token :

public async Task<ServiceResponse<UserLoginResponseDto>> Login(ServiceRequest<UserLoginRequestDto> request)
{
    ServiceResponse<UserLoginResponseDto> response = new ServiceResponse<UserLoginResponseDto>();
    User user = await _context.Users.FirstOrDefaultAsync(x => x.Username.ToLower().Equals(request.Data.Username.ToLower()));
    if (user == null)
    {
        response.Success = false;
        response.Message = "User not found";
    }
    else if (user.IsLocked)
    {
        response.Success = false;
        response.Message = "User locked";
    }
    else if (!user.IsActivated)
    {
        response.Success = false;
        response.Message = "User not activated";
    }
    else if (!VerifyPasswordHash(request.Data.Password, user.PasswordHash, user.PasswordSalt))
    {
        response.Success = false;
        response.Message = "Wrong password";
    }

    else
    {
        response.Data = _mapper.Map<UserLoginResponseDto>(user);
        response.Data.JWtToken = CreateToken(user);
    }

    return response;
}

private string CreateToken(User user)
{
    List<Claim> claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
        new Claim(ClaimTypes.Name, user.Username),
    };

    SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection("AppSettings:Token").Value));

    SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

    SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.Now.AddDays(1),
        SigningCredentials = creds
    };

    JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
    SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);

    return tokenHandler.WriteToken(token);
}

Aucun commentaire:

Enregistrer un commentaire