Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A JWT authentication service with 2FA option developed using FastAPI and using Celery for asynchronous email sending

NotificationsYou must be signed in to change notification settings

dfm88/fastapi-two-factor-authentication

Repository files navigation

Run

Todo



The application is an authentication microservice, developed with FastAPI framework, for login access via JWT token and possibility to enable two factor authentication (TFA).

Two Factor Authentication

TFA can be enabled choosing by two kind of devices:

  • email (OTP token will be send via email)
  • code generator (on activation a qr code is send to the user that, since than, will have the OTP token in any authenticator app like Microsoft or Google Authenticator apps)

It is only available the TOTP version of OTP validation protocol, based on timestamp and a private key for each user.

Backup Tokens

On TFA activation, independently from the chosen device, an email will be sent to the user with 5 backup tokens that can be used in case qr code was lost or it's somehow not possible to receive the token, these backup tokens are consumed every time one is used.

Email service

Email sending is faked by printing on stout the sent email text. It is anyway handled by a Celery consumer listening on a RabbitMQ message broker.

Services

The app run inside Docker, orchestrated by docker-compose. Database is Postgres, RabbitMq is used as message broker for Celery tasks and Redis is used as a backend for saving tasks results. It is also available a Flower instance to check task status via web dashboard.

servicecontainer namelistening port
FastAPIfastapi_2fa5555
PostgresDBfastapi_2fa-db5454
Redisfastapi_2fa-cache6389
RabbitMQfastapi_2fa-rabbitmq15672
Celery workerfastapi_2fa-celery
Flowerfastapi_2fa-flower5557

image

User model has a One to One relationship with Device model. Device model has a One to Many relationship with BackupTokens model.

  • full_name - user name
  • email - used for login
  • hashed_password - user hashed password
  • tfa_enabled - boolean field to determine if user has TFA enabled
  • user_id - associated user
  • key - here is saved the encrypted version of the user OTP key
  • device_type - string value to determine if TFA device is of typeemail orcode_generator
  • device_id - associated device
  • token - random TOTP backup token

Endpoints can be easily tested via FastAPI Swagger on route/docs. here are proposed thecurl version to easily set JWT tokens

  • /api/v1/auth/signup

    POST - Creates a new user.

    device key is required only iftfa_enabled istrue;

    device_type is one betweenemail orcode_generator

    body

    {"email":"user@example.com","tfa_enabled":true,"full_name":"string","password":"123456","device": {"device_type":"email"    }}

    curl (the--output option will save on your filesystem a valid qr-code image only if device type iscode_generator)

    curl -X'POST' \'http://localhost:5555/api/v1/auth/signup' \-H'accept: application/json' \-H'Content-Type: application/json' \-d'{"email": "user@example.com","tfa_enabled": true,"full_name": "string","password": "123456","device": {    "device_type": "email"}}' --output my_qrcode.png
  • /api/v1/auth/login

    POST - Authenticates new user

    form data

    EmailPassword

    curl

    curl -X'POST' \'http://localhost:5555/api/v1/auth/login' \-H'accept: application/json' \-H'Content-Type: application/x-www-form-urlencoded' \-d'grant_type=&username={{ USERNAME }}&password={{ PASSWORD }}&scope=&client_id=&client_secret='
  • /api/v1/auth/test-token

    GET - Test authenticated endpoint to check if user is authenticated, JWT token must be set inAuthorization header

    curl

    curl -X'GET' \'http://localhost:5555/api/v1/auth/test-token' \-H'accept: application/json' \-H'Authorization: Bearer {{ MY_ACCESS_JWT_TOKEN }}'
  • /api/v1/auth/refresh

    POST - given aREFRESH_JWT_TOKEN returns a newACCESS_JWT_TOKEN

    body

    {"refresh_token":"{{ MY_JWT_REFRESH_TOKEN }}"}

    curl

    curl -X'POST' \'http://localhost:5555/api/v1/auth/refresh' \-H'accept: application/json' \-H'Content-Type: application/json' \-d'{"refresh_token": "{{ MY_JWT_REFRESH_TOKEN }}"}'
  • /api/v1/tfa/login_tfa?tfa_token=

    POST - it's the second step after login for users with TFA enabled, it is necessary to have the TOTP token and to have the temporary access token inAuthorization header returned bylogin endpoint for users with TFA enabled

    curl

    curl -X'POST' \'http://localhost:5555/api/v1/tfa/login_tfa?tfa_token={{ MY_TOTP_TOKEN }}' \-H'accept: application/json' \-H'Authorization: Bearer {{ MY_PRE_TFA_JWT_ACCESS_TOKEN }}' \-d''
  • /api/v1/tfa/recover_tfa?tfa_backup_token=

    POST - it's the second step after login for users with TFA enabled that can't receive/recover their TOTP token, so they can use one of the backup tokens sent in signup step. It is necessary to have the temporary access token inAuthorization header returned bylogin endpoint for users with TFA enabled

    curl

    curl -X'POST' \'http://localhost:5555/api/v1/tfa/recover_tfa?tfa_backup_token={{ MY_BACKUP_TOTP_TOKEN }}' \-H'accept: application/json' \-H'Authorization: Bearer {{ MY_PRE_TFA_JWT_ACCESS_TOKEN }}' \-d''
  • /api/v1/tfa/get_my_qrcode

    GET - authenticated endpoint to receive again its own qr code (only for user withcode_generator device)

    curl

    curl -X'GET' \'http://localhost:5555/api/v1/tfa/get_my_qrcode' \-H'accept: application/json' \-H'Authorization: Bearer {{ MY_JWT_ACCESS_TOKEN }}'  --output my_recovered_qr_code.png
  • /api/v1/tfa/enable_tfa

    PUT - enables TFA for authenticated users that didn't enable it on signup step.device_type is one betweenemail orcode_generator

    body

    {"device_type":"code_generator"}

    curl (the--output option will save on your filesystem a valid qr-code image only if device type iscode_generator)

    curl -X'PUT' \'http://localhost:5555/api/v1/tfa/enable_tfa' \-H'accept: application/json' \-H'Authorization: Bearer {{ MY_JWT_ACCESS_TOKEN }}' \-H'Content-Type: application/json' \-d'{"device_type": "code_generator"}' --output my_new_qr_code.png
  • /api/v1/users/users

    GET - test non-authenticated endpoint to get all users in DB

    curl

    curl -X'GET' \'http://localhost:5555/api/v1/users/users' \-H'accept: application/json'
  • /api/v1/tasks/test-celery

    GET - endpoint to test celery send mail function

    curl

    curl -X'GET' \'http://localhost:5555/api/v1/tasks/test-celery' \-H'accept: application/json'
  • /api/v1/tasks/taskstatus?task_id=

    GET - endpoint to retrieve task status.?task_id is returned by ``/api/v1/tasks/test-celery` endpoint

    curl

    curl -X'GET' \'http://localhost:5555/api/v1/tasks/taskstatus?task_id={{ TASK_ID }}' \-H'accept: application/json'

The modules inside this package are responsible to query the DB

The modules inside this package are responsible to handle the core business logic of the application



To run all the services, from the application root run:

docker-compose -f docker/docker-compose.yaml up

The FastAPI server is exposed on port5555, FastAPI swagger is available athttp://localhost:5555/docs#/


To follow only FastAPI logs, from another terminal, run:

docker logs --tail 200 -f fastapi_2fa

To run tests, from another terminal, run:

dockerexec fastapi_2fa pytest --cov-report term --cov=fastapi_2fa tests/


  • reset / recover password
  • encrypt backup tokens
  • throttling for failed login
  • complete tests
  • logging

About

A JWT authentication service with 2FA option developed using FastAPI and using Celery for asynchronous email sending

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp