Flask (Python) app with two-factor authentication based on time - One-Time password.
- Sign in, register, reset password panels
- Fresh login requirement to crucial operations
- Reset password by email
- Activate and deactivate 2FA
- Two latest OTP are valid
- QR Code rendered at client-side (by a pure Javascript library)
- Easy translations with Flask-Babel
- Content Security Policy Level 3
Since client get only secret code (asynchronous), it is no need to deal with images and its caching by robots etc.
pyotp library allows to generate and check OTP at given time, e.g. for last 30 seconds:
totp.at(datetime.datetime.now()-timedelta(seconds=30))
- Clone this repository
git clone https://github.com/onyxcherry/OnyxcherryOTP.git
- Create and activate python virtual environment
cd OnyxcherryOTP
python3 -m venv venv
source venv/bin/activate
- Install dependencies
pip install -r requirements.txt
- Compile translations
flask translate compile
- Create database
This project uses sqlite3 by default for the convenience. You could use anything else.
flask shell
>>> db.create_all()
flask run
or - on production - use Gunicorn.
Whether or not development purpose, you have to run the app with https if you want to use Webauthn:
gunicorn --bind 127.0.0.1:5777:5777 --certfile /path/to/server.crt --keyfile /path/to/server.key --access-logfile - --error-logfile - --reload onyxcherryotp:app
- Build the image
docker build -t onyxcherryotp:commit_id -f Dockerfile .
- Copy or create
.env
file, add or update variables, especialyDATABASE_URL
- Run the database server, create a database and tables (by running migration scripts or
flask shell
anddb.create_all()
) - Run the container
docker run --name onyxcherryotp_commit_id_one -d -p 127.0.0.1:5333:5777 --mount type=bind,source=/path/outside/docker/to/config.py,destination=/home/onyxcherry/OnyxcherryOTP/config.py,readonly --mount type=bind,source=/path/outside/docker/to/.env,destination=/home/onyxcherry/OnyxcherryOTP/.env,readonly onyxcherryotp:commit_id
Both Gunicorn (due to at least 2 workers) and multiple containers of Docker need to specify same environment variables, especially SECRET_KEY
. Unless specified, you will have troubles with correctly cookies' sign.
Therefore use e.g
python -c 'from os import urandom; from base64 import b64encode; print(b64encode(urandom(32)).decode("utf-8"))'
and pass it as SECRET_KEY.
Update other variables.
pytest
(you might have typed pip install -e .
)
OnyxcherryOTP uses SendGrid to sending emails. Set MAIL_LOCALHOST=True
in the .env if you want to send emails to localhost.
If so type
python3 -m smtpd -n -c DebuggingServer localhost:8465
in another console window.
- Add
revoke other sessions
button - Add custom front-end (panels)
- Temporarily block user account due to security reasons (and verify & sign in through email)
- Add alternative way to 2FA authenticate (backup codes)
- Add WebAuthn
- Miguel's incredible Flask tutorial
- QR Code svg generator – client-side, pure Javascript
- Bootstrap pretty forms
- Bootstrap Cover theme
- Webauthn developer guide
- Webauthn logo