SakaDream / actix-web-rest-api-with-jwt

A simple CRUD backend app using Actix-web, Diesel and JWT

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to get User data in controllers?

Cosaquee opened this issue · comments

Hi,

First of all I would like to say that this repository is a really nice example of implementing JWT for Actix. It is a really helpful resource to start playing with Actix, thank you for your work.

If you have a minute to spare would you be able to suggest how to pass JWT token to the different controllers? What I would like to achieve is to have a way of extracting user_id from incoming request to automatically create relation between models and user that is creating them in the app, without a need to send user_id with every request from frontend.

If you don't want to or do not have time to, feel free to close this issue :)

Had the same problem when taking inspiration from this repo for my own API with actix (for training).

The JWT is embedded in the request. In a single controller that takes request: &actix_web::HttpRequest as the argument you can extract the authentication header with request.headers().get("Authorization"), then unpack the authentication header like so :

use crate::{jwt::user_token::UserToken, toolbox::errors::CustomError};
use actix_web::HttpRequest;


pub fn get_uid_from_request(request: &HttpRequest) -> Result<i32, CustomError> {
    let authen_header = match request.headers().get("Authorization") {
        Some(authen_header) => authen_header,
        None => {
            return Err(
                // the authentication middleware should have checked this already
                CustomError::new(400, "Something went very wrong".to_string()),
            );
        }
    };
    let authen_str = authen_header.to_str()?;
    if !authen_str.starts_with("bearer") && !authen_str.starts_with("Bearer") {
        return Err(CustomError::new(
            400,
            "The authentication header doesn't start with 'bearer'".to_string(),
        ));
    }
    let raw_token = authen_str[6..authen_str.len()].trim();
    let token = UserToken::decode_token(raw_token.to_string())?;
    let uid = token.uid;
    Ok(uid)
}

And call this function in a controller. As an example :

// GET HOST/persons
pub async fn find_all(
    request: HttpRequest,
    pool: web::Data<Pool>,
) -> Result<HttpResponse> {
    let uid = get_uid_from_request(&request)?;
    let persons = Person::find_all(uid, &pool)?;
    Ok(HttpResponse::Ok().json(persons))
}

Feel free to ask questions on my own repo. Happy coding :-)