Implementation of an Auth REST API service in Python
The purpose of this project is to provide an implementation of an Auth REST API service in Python
- Docker
- Clone the repository
git clone https://github.com/saxenankit123/auth-service.git
- Change directory to
auth-service
cd auth-service
- Give execute permission to the
install.sh
file and run it. This command will build the docker image of auth-service and run it. Once done, you would be able to run the curl commands mentioned in the features section.
chmod +x install.sh
./install.sh
Once successful, the install.sh
script will print the container id for stopping or starting the service later.
- To stop or re-run the auth-service use below commands
docker stop YOUR_AUTH-SERVICE_CONTAINER_ID
docker start YOUR_AUTH-SERVICE_CONTAINER_ID
creation of user using email and password - A new user can signup by providing a valid email id and password. Email id should be unique and password must be atleast 6 characters long.
curl -i --location --request POST 'http://localhost:3000/signup' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "ankit@gmail.com",
"password": "Ind1a@765"
}'
Sample Response
HTTP/1.1 201 CREATED
Server: Werkzeug/3.0.1 Python/3.9.18
Date: Mon, 12 Feb 2024 06:42:41 GMT
Content-Type: application/json
Content-Length: 47
Connection: close
{
"result": "Account successfully created"
}
Response HTTP Codes
HTTP Status Code | Description |
---|---|
400 | Request validation fails; signup unsuccessful |
409 | Record with the provided email id already exists; signup unsuccessful |
201 | User signup successful |
once an account is created, using email and password, client can obtain access_token
and refresh_token
to access protected routes.
curl -i --location --request GET 'http://localhost:3000/authenticate' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "ankit@gmail.com",
"password": "Ind1a@765"
}'
Sample Response
HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.9.18
Date: Mon, 12 Feb 2024 06:43:31 GMT
Content-Type: application/json
Content-Length: 377
Connection: close
{
"access_token": "YOUR_ACCESS_TOKEN",
"refresh_token": "YOUR_REFRESH_TOKEN",
"result": "Authentication successful"
}
access_token
- Authentication token that should be used in every subsequent request to access protected routes. access_stoken has an expiry of 1 minute.
refresh_token
- Token to be used to renew access_token
. refresh_token has an expiry of 2 mins.
How to renew access token ? - while accessing a protected route, client should first check if the access_token
is expired. If yes, then client should initiate call to /refresh-access-token
route to receive new access_token
. If refresh_token
is also expired then client should use /authenticate
to receive new access_token
and refresh_token
by passing valid email and password.
Response HTTP Codes
HTTP Status Code | Description |
---|---|
400 | Request validation fails |
401 | Incorrect email id or password; sign in unsuccessful |
200 | User signin successful |
a protected route to fetch user profile details. You need to pass a valid access_token
to access this route. If the access_token is not valid or expired then this API will return an authentication error.
curl -i --location --request GET 'http://localhost:3000/user' \
--header 'Content-Type: application/json' \
--header 'Authorization: YOUR_ACCESS_TOKEN' \
--data-raw '{
"email": "EMAIL_ADDRESS_OF_USER"
}'
Sample Response
HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.9.18
Date: Mon, 12 Feb 2024 06:57:14 GMT
Content-Type: application/json
Content-Length: 98
Connection: close
{"data": {"email": "EMAIL_ADDRESS_OF_USER"}, "result": "User profile fetched successfully", "status": 200}%
Response HTTP Codes
HTTP Status Code | Description |
---|---|
400 | Request validation fails |
404 | User not found |
200 | User profile fetch successful |
401 | Authentication failed |
if access_token
is expired then client can call this route to refresh the access_token
by passing a valid refresh_token
curl -i --location --request GET 'http://localhost:3000/refresh-access-token' \
--header 'Content-Type: application/json' \
--data '{
"refresh_token":"YOUR_REFRESH_TOKEN"
}'
Sample Response
HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.9.18
Date: Mon, 12 Feb 2024 06:58:21 GMT
Content-Type: application/json
Content-Length: 217
Connection: close
{
"access_token": "YOUR_ACCESS_TOKEN",
"result": "Access token refreshed successfully"
}
Response HTTP Codes
HTTP Status Code | Description |
---|---|
400 | Request validation fails |
404 | Token not present; refresh unsuccessful |
200 | Access token refresh successful |
401 | Refresh token is expired or invalid; refresh unsuccessful |
to remove access_token
forcibly
CAUTION - Preferred secured approach should be to create a simple shell script that can run on the backend server. This script can take takes emailid as input argument and can connect to the token store (database in the current implementation) and delete the token from token store. In the current implementation, an API is exposed to remove the token.
curl -i --location --request DELETE 'http://localhost:3000/access-token' \
--header 'Content-Type: application/json' \
--data-raw '{
"email":"EMAIL_ADDRESS_OF_USER"
}'
Sample Response
HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.9.18
Date: Mon, 12 Feb 2024 06:59:17 GMT
Content-Type: application/json
Content-Length: 39
Connection: close
{
"result": "Access token removed"
}
Response HTTP Codes
HTTP Status Code | Description |
---|---|
400 | Request validation fails |
404 | Token not present; remove unsuccessful |
200 | Access token removed |
- Customize the validation messages: auth-service uses python library
jsonschema
to validate request payload/parameters. As a further improvement, it can be explored to customize the default validation messages for easy understanding. - In current implementation .env is present on the git repo. A safe and secure way should be to store the .env file on the server OR pull the .env file from a service.
- In current implementation, database is being accessed from the controller layer. It can be discussed to create service and database layers to make the code more modular.
- Make a shell script to delete the tokens from backend
- Another way to renew
access_token
be auto-renewal.auth_service
can auto-renew theaccess_token
if the client also sendsrefresh_token
in every subsequent call to access protected routes. Methodcheck_authenticity()
inmiddleware.py
implements this but is commented in the current version.