Using Axum Framework To Create REST API (Part II)

Abhinav Yadav
Intelliconnect Engineering
4 min readAug 11, 2022

This is the Part II of the article `Using Axum Framework To Create Rest API`. In this article, we are going to learn how to protect routes/endpoints of API using JWT Token.

Note: To setup the project, please refer Part I of this article.

You can get the code for this article on GitHub.

The flow of authenticating endpoints

In Part I, we created /register a route. Now we will create a/login route to authenticate a user. This route creates and sends a JWT Token for authenticated registered users. The/user_profile route is a protected route that can only be accessed by authenticated users.

Login route

First, add the below crates to the cargo.toml file

// Cargo.toml
[dependencies]
jsonwebtoken = "8.0"
once_cell = "1.8"

`once_cell` for define secret for the `jsonwebtoken`, in a production server you save it somewhere else and call it inside the server or set an environment variable for it.

Models

Add the below code to src/models/auth.rs

The user model should already be in your code if you followed part I. Keys model is used to store keys for encoding and decoding the JWT token, and `Claims` is used to store any information we want to store in the token, while `exp` expiry of the token in the timestamp.

The login handler

Modify file src/controllers/auth.rs with the below code. There will be no changes in the register function. Add the login function and import the missing modules and structs.

For login, we are first checking if credentials are not empty, then fetching the user from the database with that credential, if the user exists then check if the password matches if it does then generate a token and send it as a response.

Now the code won’t run yet, since we have not created utils module.

Utils module

First, create a file src/utils.rs and add the below code to it.

The get_timestamp_8_hours_from_now the function is used to get a timestamp of 8 hours from the current time for the token expiry.

In Axum, we can derive FromRequest trait for any custom type to extract it from the request body from the handler, so after deriving FromRequest for the `Claims` struct, we can extract it from handlers like

// extract Claims from request
pub async fn handler(claims: Claims) -> Json<serde_json::Value>{}

So it’s like middleware, whenever we extract Claims in a handler, it will verify the token first, so it becomes protected.

Protected route

let’s create a protected route /user_profile, this route fetches the user profile of an authenticated user.

Create a file src/controllers/user.rs and the below code to it

and add the following line to src/controllers.rs to add this file to the `controllers` module

// src/controllers.rs
pub mod user;

Here we are first fetching the Claims model/struct, so we will get an error if we don’t pass the token in the request or if the token is not valid, if the token is valid we will get the email in a JSON as a response.

Testing

For testing, I will be using httpie command . You can also use curl or postman or others that work for you.

First, send a login request to get the JWT token

http localhost:3000/login email=abhinav14@gmail.com password=pass@123

you will get the token in the response if the credentials are correct.

Then use that token to access the /user_profile route

http -A bearer -a eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImFiaGluYXYxNEBnbWFpbC5jb20iLCJleHAiOjE2NTk0NjE0NTV9.R1oNc1MS4xJZXcuyxaCcHpbPwDlsCcIsPuPF2kPXsXE localhost:3000/user_profile

Here I am setting the authentication type to bearer and passing the token. In response, I have set to return “email” as an example.

Debugging

You can compare your code with code on GitHub. Remember to set the DATABASE_URL env variable. Ensure that there is a table with ID, email, and password columns in the database.

Conclusion

If you have any questions, please feel free to reach out. Thanks for reading!

--

--