Setup
① Add authentication, login and refresh views to urlpatterns.
from django.urls import path
from jwt_email_auth.views import SendLoginCodeView, LoginView, RefreshTokenView
urlpatterns = [
...
path("authentication/", SendLoginCodeView.as_view(), name="authentication"),
path("login/", LoginView.as_view(), name="login"),
path("refresh/", RefreshTokenView.as_view(), name="refresh"),
...
]
② Configure settings with the JWT_EMAIL_AUTH
key. Here is a minimal config (some values are defaults):
JWT_EMAIL_AUTH = {
"SENDING_ON": True, # needs to be set explicitly!
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
"REFRESH_TOKEN_LIFETIME": timedelta(days=14),
"LOGIN_CODE_LIFETIME": timedelta(minutes=5),
"EXPECTED_CLAIMS": ["foo", "bar"],
"CACHE_PREFIX": "PREFIX",
"LOGIN_ATTEMPTS": 10,
"LOGIN_COOLDOWN": timedelta(minutes=5),
"CODE_SEND_COOLDOWN": timedelta(minutes=1),
"LOGIN_VALIDATION_AND_DATA_CALLBACK": "path.to.module.function",
}
Here are the rest of the settings and what they mean.
Setting | Description | Type |
---|---|---|
SENDING_ON |
Whether emails should be sent or not. When off, login code is logged instead (for development). |
bool |
SKIP_CODE_CHECKS |
When True, any code will work in login. |
bool |
SKIP_CODE_CHECKS_FOR |
List of emails for which code checks and email sending are off, even if SKIP_CODE_CHECKS=False and/or SENDING_ON=True. Useful for creating review accounts in an otherwise closed system. |
list[str] |
ACCESS_TOKEN_LIFETIME |
How long an access token is valid for. |
timedelta |
REFRESH_TOKEN_LIFETIME |
How long a refresh token is valid for. |
timedelta |
LOGIN_CODE_LIFETIME |
How long a login code is stored in cache. |
timedelta |
LOGIN_COOLDOWN |
After user has exceeded defined number of login attemprs, this is the cooldown until they can attempt login again. |
timedelta |
CODE_SEND_COOLDOWN |
After a user has sent a login code, this is the cooldown until they can send one again. |
timedelta |
NOT_BEFORE_TIME |
How long after the creation of the JWT does it become valid. |
timedelta |
ROTATE_REFRESH_TOKENS |
If True, return a new refresh token when requesting a new access token from RefreshTokenView. The old refresh token will be invalid after the new one is created. |
bool |
LOGIN_ATTEMPTS |
Number of login attempts until user is banned. |
int |
EXPECTED_CLAIMS |
List of expected JWT content. |
list[str] |
UPDATEABLE_CLAIMS |
Which expected claims can be updated without re-authentication using the update view. |
list[str] |
LOGIN_SENDING_EMAIL |
Email sender. | str |
LOGIN_SUBJECT_LINE |
Email subject line. | str |
LOGIN_EMAIL_MESSAGE |
Message to send in email. Must have {code} and {valid}! |
str |
LOGIN_EMAIL_HTML_TEMPLATE |
Path to html_message template. Context must have {{ code }} and {{ valid }}! |
Path |
CACHE_PREFIX |
Cache prefix. | str |
OPTIONS_SCHEMA_ACCESS |
When True (default), OPTIONS requests can be made to the endpoint without token for schema access. |
bool |
CIPHER_KEY |
If set, JWT will be encrypted with AES in GCM-mode using this as the secret key. Should be either 16, 24, or 32 bytes, encoded to base64. |
str |
ISSUER |
Issuer of the JWT. | str |
AUDIENCE |
Intended recipient of the JWT. |
str |
LEEWAY |
A time margin in seconds for the expiration check. |
int |
ALGORITHM |
Algorithm to sign and decrypt the token with. |
str |
HEADER_PREFIX |
Authorization scheme used in Authorization header, as in HEADER_PREFIX token . |
str |
EXTRA_HEADERS |
Additional JWT header fields. |
dict[str, str] |
These settings should be specified in "dot import notation" to a function, which will be imported as the value for the setting.
Setting | Description | Arguments | Returns |
---|---|---|---|
SIGNING_KEY |
Function to load JWT signing key. |
? | |
CODE_GENERATOR |
Function to generate a login code. |
str | |
SEND_LOGIN_CODE_CALLBACK |
Function that sends the login email. |
str, dict[str, Any], Request |
None |
LOGIN_VALIDATION_AND_DATA_CALLBACK |
Function to use for validating user and providing login data. |
str | dict[str, Any] |
LOGIN_BLOCKER_CACHE_KEY_CALLBACK |
Function to generate cache key for storing user's login attempts. |
Request | str |
USER_BLOCKED_ADDITIONAL_HANDLER |
Function for additional handling for blocked users. |
Request | None |
USER_CHECK_CALLBACK |
Function to check if token user still exists in refresh view. |
RefreshToken | None |
IP address spoofing prevention settings:
Setting | Description | Type |
---|---|---|
PROXY_ORDER |
Indicate whether the originating client is on the right or left in the X-Forwarded-For header |
"left-most" "right-most" |
PROXY_COUNT |
Number of proxies between the server and internet. |
int |
PROXY_TRUSTED_IPS |
Only these proxy IPs are allowed connections |
List[str] |
REQUEST_HEADER_ORDER |
Meta precedence order. | List[str] |
Settings when using cookies:
Setting | Description | Type |
---|---|---|
USE_TOKENS |
If True, can authenticate with tokens in Authorization header. Set this to False and USE_COOKIES to True to onlyallow cookie authentication. |
bool |
USE_COOKIES |
If True, can authenticate with tokens in HttpOnly headers. Cookies will be checked before Authorization headers if they are enabled. |
bool |
DEFAULT_LOGIN_METHOD |
Default login method to use if none is given in Prefer-headers. If not set, cookie-based login will be used if enabled, else token-based. |
|
ACCESS_TOKEN_KEY |
Cookie key to use for the access token |
str |
REFRESH_TOKEN_KEY |
Cookie key to use for the refresh token |
str |
SET_COOKIE_SECURE |
Indicates that the cookie is sent to the server only when a request is made with the https: scheme (except on localhost) and therefore, is more resistant to man-in-the-middle attacks. |
bool |
SET_COOKIE_ACCESS_PATH |
Indicates the path that must exist in the requested URL for the browser to send the access token cookie. |
str |
SET_COOKIE_REFRESH_PATH |
Indicates the path that must exist in the requested URL for the browser to send the refresh token cookie. |
str |
SET_COOKIE_DOMAIN |
Defines the host to which the cookie will be sent. If None, this attribute defaults to the host of the current document URL, not including subdomains. |
str |
SET_COOKIE_HTTPONLY |
If True, forbids JavaScript from accessing the cookie. |
bool |
SET_COOKIE_SAMESITE |
Controls whether a cookie is sent with cross-origin requests, providing some protection against cross-site request forgery attacks (CSRF). |
"lax" "strict" "none" |
③ Add OpenSSH based ed25519 SIGNING_KEY
(in PEM format) to environment variables.
You can create one with, e.g., ssh-keygen using the command ssh-keygen -t ed25519
.
The linebreaks in PEM format should be replaced with | (pipe) characters.
If you do not want to use environment variables, override the SIGNING_KEY
setting.
A default signing key is provided for reference in the settings-module, but this should be changed in production environments.
④ Configure Django's email settings (if using django's email sending):
# Not all of these may be required
EMAIL_HOST_USER = ...
EMAIL_HOST_PASSWORD = ...
EMAIL_HOST = ...
EMAIL_PORT = ...
EMAIL_USE_TLS = ...
EMAIL_USE_SSL = ...
EMAIL_BACKEND = ...
EMAIL_SENDER = ...
EMAIL_SUBJECT_PREFIX = ...
DEFAULT_FROM_EMAIL = ...
SERVER_EMAIL = ...
⑤ (Optional) Add default authentication_classes
or permission_classes
:
REST_FRAMEWORK = {
...
"DEFAULT_AUTHENTICATION_CLASSES": [
"jwt_email_auth.authentication.JWTAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"jwt_email_auth.permissions.HasValidJWT",
]
...
}