drf-passwordless-jwt
is a RESTful API service that offers passwordless
authentication using JWT. In other words, it's a Single Sign-On (SSO)
service that allows users to log in without using a password.
- Email login token
- Obtain JWT token
- Verify JWT token
- Dummy accounts used for development and testing purposes.
# Email login token
$ curl -X POST -d "[email protected]" localhost:8000/auth/email/
{"detail":"A login token has been sent to your email."}
Enter this token to sign in: 527389
# Obtain JWT token
$ curl -X POST -d "[email protected]&token=527389" localhost:8000/auth/jwt/
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw","email":"[email protected]"}
# Verify JWT token
$ curl -X POST -d "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw" \
localhost:8000/auth/
{"email":"[email protected]","exp":"2023-02-01T15:54:04Z"}
# or verify via http header
$ curl -X GET -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw" \
localhost:8000/auth/header/
{"email":"[email protected]","exp":"2023-02-01T15:54:04Z"}
# or verify via http cookie
$ curl -X GET --cookie "Authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw" \
localhost:8000/auth/header/
{"email":"[email protected]","exp":"2023-02-01T15:54:04Z"}
It uses Django REST framework, so you can also access this interface through your browser.
During development and testing, you may want to use dummy accounts to save time. To do this, you can configure environment variables. For example, if you want to use the email address [email protected] to log in, you can set the environment variable:
$ export EMAIL_TEST_ACCOUNT_a_at_a_com=123456
Then, you can use the command:
$ curl -X POST -d "[email protected]&token=123456" localhost:8000/auth/jwt/
to directly obtain a JWT token without having to first obtain a login token via email. This way, you can cut out the step of first getting a login token via email, and immediately receive a JWT token. This hack could save you significant time.
You should customize your configuration to suit your requirements. All configurations can be set via environment variables. The following are the configured default values:
# 0: production, 1: development
DJANGO_DEBUG = 1
# specify hosts separated by commas
DJANGO_ALLOWED_HOSTS = '*'
# 1: print email to screen, not sending
EMAIL_BACKEND_TEST = 0
# email from
OTP_EMAIL_ADDRESS = '[email protected]'
# token expire time, default 5 minutes
OTP_TOKEN_EXPIRE_SECONDS = 300
# email subject
OTP_EMAIL_SUBJECT = 'Your Login Token'
# email text message
OTP_EMAIL_PLAINTEXT = 'Enter this code to sign in: %s'
# email html message template file
# set it to 'passwordless_zh_token_email.html' to use the built-in Chinese template.
OTP_EMAIL_HTML = 'passwordless_token_email.html'
# the http header name if you like to pass token via http header
# it's useful when setup this as a forward auth service
# for API gateway like using APISIX forward-auth plugin.
AUTH_HEADER_NAME = 'Authorization'
# verify via http cookie name as a forward auth service
AUTH_COOKIE_NAME = 'Authorization'
# 1: ssl smtp
EMAIL_USE_SSL = 0
# 1: tls smtp
EMAIL_USE_TLS = 0
EMAIL_HOST = 'smtp.mydomain.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 465
EMAIL_FROM = '[email protected]'
# fail if smtp server response too slow
EMAIL_TIMEOUT = 3
# regex, for example: '.*@mail1.com$|.*@mail2.com'
EMAIL_WHITE_LIST = r'.*'
# message on rejection
EMAIL_WHITE_LIST_MESSAGE = 'unacceptable email address'
# dummy account env prefix
EMAIL_TEST_ACCOUNT_PREFIX = 'EMAIL_TEST_ACCOUNT_'
# specify hosts separeated by commas
CORS_ALLOWED_ORIGINS = ''
# 1: accept any remote host
CORS_ALLOW_ALL_ORIGINS = 0
DB_ENGINE = 'django.db.backends.sqlite3'
DB_NAME = BASE_DIR / 'db.sqlite3'
DB_USER = 'postgres'
DB_PASSWORD = ''
DB_HOST = ''
DB_PORT = ''
# JWT secret string
JWT_SECRET = 'secret-for-jwt'
# JWT expire time, default 30 days
JWT_EXPIRE_SECONDS = 2592000
During development, you can build and run it on your local host:
$ docker build -t auth .
$ docker run --rm -p 8000:8000 -e EMAIL_BACKEND_TEST=1 auth
There are pre-built docker images.
You can use docker-compose for deployment.
This is a template of docker-compose.yml
:
version: "3"
services:
auth:
image: xieyanbo/drf-passwordless-jwt:latest
container_name: auth
environment:
- TZ=Asia/Hong_Kong
- DJANGO_SECRET_KEY=secret-string
- DJANGO_DEBUG=0
- [email protected]
- OTP_TOKEN_EXPIRE_SECONDS=300
- OTP_EMAIL_SUBJECT=Your Login Token
- OTP_EMAIL_PLAINTEXT=Enter this code to sign in: %s
- OTP_EMAIL_HTML=passwordless_token_email.html
- EMAIL_BACKEND_TEST=0
- EMAIL_USE_SSL=0
- EMAIL_USE_TLS=1
- EMAIL_HOST=smtp.mydomain.com
- EMAIL_PORT=465
- [email protected]
- EMAIL_HOST_PASSWORD=password
- EMAIL_FROM=xyb@mydomain
- EMAIL_WHITE_LIST=.*@mydomain.com$$|.*@mydomain2.com$$
- EMAIL_WHITE_LIST_MESSAGE=for mydomain.com and mydomain2.com only
- JWT_SECRET=secret-for-jwt
- JWT_EXPIRE_SECONDS=2592000
ports:
- 8000:8000
restart: always