JWT Auth¶
Docs: https://jwt.io
Important
To use jwt you must install 'django-modern-rest[jwt]' extra.
Requiring auth¶
Note
Current user will always be accessible as self.request.user.
Read more: https://docs.djangoproject.com/en/stable/topics/auth/default/
We provide two classes to require JWT auth in your API:
JWTSyncAuthfor sync viewsJWTAsyncAuthfor async views
Example, how to use the auth class and how to get self.request.user:
1from django.contrib.auth.models import User
2
3from dmr import Controller
4from dmr.plugins.pydantic import PydanticSerializer
5from dmr.security import AuthenticatedHttpRequest
6from dmr.security.jwt import JWTSyncAuth
7
8
9class APIController(Controller[PydanticSerializer]):
10 request: AuthenticatedHttpRequest[User]
11 auth = (JWTSyncAuth(),)
12
13 def get(self) -> str:
14 # Let's test that `User` has the correct type:
15 assert self.request.user.username
16 return 'authed'
Reusing pre-existing views¶
We provide several pre-existing views to get auth tokens. So, users won’t have to write tons of boilerplate code.
JWT with access and refresh tokens¶
We provide two Reusable controllers to obtain pairs of access and refresh tokens:
ObtainTokensSyncControllerfor sync controllersObtainTokensAsyncControllerfor async controllers
To use them, you will need to:
Provide actual types for serializer, request model, and response body
Redefine
convert_auth_payload()to convert your request model into the kwargs ofdjango.contrib.auth.authenticate()to authenticate your requestRedefine
make_api_response()to return the response in the format of your choice
1import datetime as dt
2
3from typing_extensions import override
4
5from dmr.plugins.pydantic import PydanticSerializer
6from dmr.security.jwt.views import (
7 ObtainTokensPayload,
8 ObtainTokensResponse,
9 ObtainTokensSyncController,
10)
11
12
13# You can also use `ObtainTokensAsyncController` if needed:
14class ObtainAccessAndRefreshSyncController(
15 ObtainTokensSyncController[
16 PydanticSerializer,
17 ObtainTokensPayload,
18 ObtainTokensResponse,
19 ],
20):
21 @override
22 def convert_auth_payload(
23 self,
24 payload: ObtainTokensPayload,
25 ) -> ObtainTokensPayload:
26 return payload
27
28 @override
29 def make_api_response(self) -> ObtainTokensResponse:
30 now = dt.datetime.now(dt.UTC)
31 return {
32 'access_token': self.create_jwt_token(
33 expiration=now + self.jwt_expiration,
34 token_type='access',
35 ),
36 'refresh_token': self.create_jwt_token(
37 expiration=now + self.jwt_refresh_expiration,
38 token_type='refresh',
39 ),
40 }
41
Run result
$ curl http://127.0.0.1:8000/api/auth/ -X POST -d '{"username": "test_user", "password": "password"}' -H 'Content-Type: application/json'
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzc2MjcyODc3LCJpYXQiOjE3NzYxODY0NzcsImp0aSI6IjFhMWRkOGY1ZDMyMjQyMmJiZDJiYWNkNWZiOWZjZGE2IiwiZXh0cmFzIjp7InR5cGUiOiJhY2Nlc3MifX0.rUo9421UQ8OrV28g86K0ry_Hfe9_kdan2C4vrMPa23c","refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzc3MDUwNDc3LCJpYXQiOjE3NzYxODY0NzcsImp0aSI6IjQ3MzM5NGU1ODU3YTQ0MjZiZjM4M2Q0ZjJmZmM3NjVlIiwiZXh0cmFzIjp7InR5cGUiOiJyZWZyZXNoIn19.ZDgblKxgCCs7qKht0_jcePnVSNGkKAAk-65m3tYyTKk"}
OpenAPI Schema
Preview openapi.json
{
"components": {
"schemas": {
"ErrorDetail": {
"description": "Base schema for error details description.",
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
]
},
"title": "Loc",
"type": "array"
},
"msg": {
"title": "Msg",
"type": "string"
},
"type": {
"title": "Type",
"type": "string"
}
},
"required": [
"msg"
],
"title": "ErrorDetail",
"type": "object"
},
"ErrorModel": {
"description": "Default error response schema.\n\nCan be customized.\nSee :ref:`customizing-error-messages` for more details.",
"properties": {
"detail": {
"items": {
"$ref": "#/components/schemas/ErrorDetail"
},
"title": "Detail",
"type": "array"
}
},
"required": [
"detail"
],
"title": "ErrorModel",
"type": "object"
},
"ObtainTokensPayload": {
"description": "Payload for default version of a jwt request body.\n\nIs also used as kwargs for :func:`django.contrib.auth.authenticate`.",
"properties": {
"password": {
"title": "Password",
"type": "string"
},
"username": {
"title": "Username",
"type": "string"
}
},
"required": [
"username",
"password"
],
"title": "ObtainTokensPayload",
"type": "object"
},
"ObtainTokensResponse": {
"description": "Default response type for refresh token endpoint.",
"properties": {
"access_token": {
"title": "Access Token",
"type": "string"
},
"refresh_token": {
"title": "Refresh Token",
"type": "string"
}
},
"required": [
"access_token",
"refresh_token"
],
"title": "ObtainTokensResponse",
"type": "object"
}
},
"securitySchemes": {}
},
"info": {
"title": "Django Modern Rest",
"version": "0.1.0"
},
"openapi": "3.2.0",
"paths": {
"/api/obtainaccessandrefreshsynccontroller/": {
"post": {
"deprecated": false,
"operationId": "postObtainaccessandrefreshsynccontrollerApiObtainaccessandrefreshsynccontroller",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ObtainTokensPayload"
}
}
},
"description": "Payload for default version of a jwt request body.\n\nIs also used as kwargs for :func:`django.contrib.auth.authenticate`.",
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ObtainTokensResponse"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Raised when request components cannot be parsed"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Unauthorized"
},
"406": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Raised when provided `Accept` header cannot be satisfied"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Raised when returned response does not match the response schema"
}
},
"summary": "By default tokens are acquired on post."
}
}
}
}
In this example we utilize pre-defined types of request model and response body, only doing the bare minimum with no customizations.
Things that you can customize:
Request body format
Response body format
JWT settings
JWT token class to be
JWTokensubclass with custom logicError messages, see Customizing error messages
Error handling, see Error handling
Response status code and any other regular controller or endpoint features
Here’s an example with a lot more customizations:
1import datetime as dt
2
3from typing_extensions import TypedDict, override
4
5from dmr.plugins.pydantic import PydanticSerializer
6from dmr.security.jwt.views import (
7 ObtainTokensPayload,
8 ObtainTokensSyncController,
9)
10
11
12# Custom request and response models:
13class _RequestModel(TypedDict):
14 email: str
15 password: str
16
17
18class _TokensModel(TypedDict):
19 access: str
20 refresh: str
21
22
23class _ResponseModel(TypedDict):
24 auth: _TokensModel
25
26
27# You can also use `ObtainTokensAsyncController` if needed:
28class ObtainAccessAndRefreshSyncController(
29 ObtainTokensSyncController[
30 PydanticSerializer,
31 _RequestModel,
32 _ResponseModel,
33 ],
34):
35 # Customizes the default jwt settings:
36 jwt_issuer = 'my-awesome-company'
37 jwt_algorithm = 'HS512'
38 jwt_audiences = ('dev', 'qa')
39
40 @override
41 def convert_auth_payload(
42 self,
43 payload: _RequestModel,
44 ) -> ObtainTokensPayload:
45 return {'username': payload['email'], 'password': payload['password']}
46
47 @override
48 def make_api_response(self) -> _ResponseModel:
49 now = dt.datetime.now(dt.UTC)
50 access = self.create_jwt_token(
51 expiration=now + self.jwt_expiration,
52 token_type='access',
53 )
54 refresh = self.create_jwt_token(
55 expiration=now + self.jwt_refresh_expiration,
56 token_type='refresh',
57 )
58 return {
59 'auth': {
60 'access': access,
61 'refresh': refresh,
62 },
63 }
64
Run result
$ curl http://127.0.0.1:8000/api/auth/ -X POST -d '{"email": "test_user", "password": "password"}' -H 'Content-Type: application/json'
{"auth":{"access":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzc2MjcyODc4LCJpYXQiOjE3NzYxODY0NzgsImlzcyI6Im15LWF3ZXNvbWUtY29tcGFueSIsImF1ZCI6WyJkZXYiLCJxYSJdLCJqdGkiOiI4NGFlNWUxYWNlYmU0MjRkODdjMjlkZTJmNDg5YzIyNCIsImV4dHJhcyI6eyJ0eXBlIjoiYWNjZXNzIn19.1SSmUXFYHtXC52aDUYkel6m9AMyjJoemwER_WBdbHeQtAKfBVmz6zMHzL51YPtZpfbK80jP2r2mamt2erh1m5A","refresh":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzc3MDUwNDc4LCJpYXQiOjE3NzYxODY0NzgsImlzcyI6Im15LWF3ZXNvbWUtY29tcGFueSIsImF1ZCI6WyJkZXYiLCJxYSJdLCJqdGkiOiI1ZGExMjNhYWU0ZjM0MGI1YjE2OWU2NjQ5ODYxMjIxOSIsImV4dHJhcyI6eyJ0eXBlIjoicmVmcmVzaCJ9fQ.cqsQwambDaiXRTgQ55ff6JZ_1dVEXGsWowbEpJrC5wIdmB43kzcwFMR3gNd78Dwwx6VSReNCWSmTPmJNa0DS9w"}}
OpenAPI Schema
Preview openapi.json
{
"components": {
"schemas": {
"ErrorDetail": {
"description": "Base schema for error details description.",
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
]
},
"title": "Loc",
"type": "array"
},
"msg": {
"title": "Msg",
"type": "string"
},
"type": {
"title": "Type",
"type": "string"
}
},
"required": [
"msg"
],
"title": "ErrorDetail",
"type": "object"
},
"ErrorModel": {
"description": "Default error response schema.\n\nCan be customized.\nSee :ref:`customizing-error-messages` for more details.",
"properties": {
"detail": {
"items": {
"$ref": "#/components/schemas/ErrorDetail"
},
"title": "Detail",
"type": "array"
}
},
"required": [
"detail"
],
"title": "ErrorModel",
"type": "object"
},
"_RequestModel": {
"properties": {
"email": {
"title": "Email",
"type": "string"
},
"password": {
"title": "Password",
"type": "string"
}
},
"required": [
"email",
"password"
],
"title": "_RequestModel",
"type": "object"
},
"_ResponseModel": {
"properties": {
"auth": {
"$ref": "#/components/schemas/_TokensModel"
}
},
"required": [
"auth"
],
"title": "_ResponseModel",
"type": "object"
},
"_TokensModel": {
"properties": {
"access": {
"title": "Access",
"type": "string"
},
"refresh": {
"title": "Refresh",
"type": "string"
}
},
"required": [
"access",
"refresh"
],
"title": "_TokensModel",
"type": "object"
}
},
"securitySchemes": {}
},
"info": {
"title": "Django Modern Rest",
"version": "0.1.0"
},
"openapi": "3.2.0",
"paths": {
"/api/obtainaccessandrefreshsynccontroller/": {
"post": {
"deprecated": false,
"operationId": "postObtainaccessandrefreshsynccontrollerApiObtainaccessandrefreshsynccontroller",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_RequestModel"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/_ResponseModel"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Raised when request components cannot be parsed"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Unauthorized"
},
"406": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Raised when provided `Accept` header cannot be satisfied"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorModel"
}
}
},
"description": "Raised when returned response does not match the response schema"
}
},
"summary": "By default tokens are acquired on post."
}
}
}
}
This example also provides issuer and audience in the token,
so it can be used together with accepted_issuers and accepted_audiences
configurations of dmr.security.jwt.auth.JWTSyncAuth
to additionally validate aud and iss JWT token claims.
We want to be sure that this class is at the same time:
Easy enough to not write a lot of boilerplate code by default
Customizable enough to be able to change a lot of stuff that can be affected by existing business rules
Always type safe
Blocklisting tokens¶
Note
Add 'dmr.security.jwt.blocklist' to the INSTALLED_APPS
if you want to use tokens blocklist.
JWT tokens might be leaked / outdated / etc. There must be a way to make a valid, non-expired token blocked from auth.
To do so, we provide a default Django app to do so. We store blocked tokens in the database and provide an API to add tokens to the blocklist.
Here’s an example:
1from django.contrib.auth.models import User
2from django.http import HttpRequest
3
4from dmr import Controller
5from dmr.plugins.pydantic import PydanticSerializer
6from dmr.security import AuthenticatedHttpRequest, request_auth
7from dmr.security.jwt import JWTAsyncAuth, request_jwt
8from dmr.security.jwt.blocklist import JWTokenBlocklistAsyncMixin
9
10
11class AuthenticatedRequest(HttpRequest):
12 user: User
13
14
15class JWTAuthWithBlocklist(JWTokenBlocklistAsyncMixin, JWTAsyncAuth):
16 """This class will also check that tokens are not blocklisted."""
17
18
19jwt_blocklist_auth = JWTAuthWithBlocklist()
20
21
22class APIController(Controller[PydanticSerializer]):
23 request: AuthenticatedHttpRequest[User]
24 auth = (jwt_blocklist_auth,)
25
26 async def get(self) -> str:
27 # Disable tokens for users with old domain emails
28 if self.request.user.email.endswith('@old-domain.com'):
29 assert request_auth(self.request) is jwt_blocklist_auth
30 await jwt_blocklist_auth.blocklist(
31 request_jwt(self.request, strict=True),
32 )
33 return 'authed'
We provide two mixin types:
JWTokenBlocklistAsyncMixinfor async authJWTokenBlocklistSyncMixinfor sync auth
API Reference¶
- class dmr.security.jwt.token.JWToken(sub: str, exp: datetime, iat: datetime = <factory>, iss: str | None = None, aud: str | Sequence[str] | None = None, jti: str | None = None, extras: dict[str, ~typing.Any]=<factory>, leeway: dataclasses.InitVar[int] = 0)[source]¶
JWT Token DTO.
- exp¶
Expiration - datetime for token expiration.
- Type:
- iat¶
Issued at - should always be current now.
- Type:
- aud¶
Audience - intended audience(s).
- Type:
str | collections.abc.Sequence[str] | None
- classmethod decode(encoded_token: str, secret: str, algorithm: str, *, leeway: int = 0, accepted_audiences: str | Sequence[str] | None = None, accepted_issuers: str | Sequence[str] | None = None, require_claims: Sequence[str] | None = None, verify_exp: bool = True, verify_iat: bool = True, verify_jti: bool = True, verify_nbf: bool = True, verify_sub: bool = True, strict_audience: bool = False, enforce_minimum_key_length: bool = True) Self[source]¶
Decode a passed in token string and return a Token instance.
- Parameters:
encoded_token – A base64 string containing an encoded JWT.
secret – The secret with which the JWT is encoded.
algorithm – The algorithm used to encode the JWT.
leeway – Number of potential seconds as a clock error for expired tokens.
accepted_audiences – Verify the audience when decoding the token.
accepted_issuers – Verify the issuer when decoding the token.
require_claims – Verify that the given claims are present in the token.
verify_exp – Verify that the value of the
exp(expiration) claim is in the future.verify_iat – Verify that
iat(issued at) claim value is an integer.verify_jti – Check that
jti(JWT ID) claim is a string.verify_nbf – Verify that the value of the
nbf(not before) claim is in the past.verify_sub – Check that
sub(subject) claim is a string.strict_audience – Verify that the value of the
aud(audience) claim is a single value, and not a list of values, and matchesaudienceexactly. Requires the value passed to theaudienceto be a sequence of length 1.enforce_minimum_key_length – Raise an auth error when keys are below minimum recommended length.
- Returns:
A decoded Token instance.
- Raises:
NotAuthenticatedError – If the token is invalid.
- classmethod decode_payload(encoded_token: str, secret: str, algorithms: list[str], *, leeway: int, issuer: str | Sequence[str] | None, audience: str | Sequence[str] | None, options: Options | None) dict[str, Any][source]¶
Decode and verify the JWT and return its payload.
- encode(secret: str | bytes, algorithm: str, headers: dict[str, Any] | None = None) str[source]¶
Encode the token instance into a string.
- Parameters:
secret – The secret with which the JWT is encoded.
algorithm – The algorithm used to encode the JWT.
headers – Optional headers to include in the JWT (e.g., {“kid”: “…”}).
- Returns:
An encoded token string.
- Raises:
InternalServerError – If encoding fails.
- class dmr.security.jwt.auth.JWTSyncAuth(*, user_id_field: str = 'pk', algorithm: str = 'HS256', security_scheme_name: str = 'jwt', auth_header: str = 'Authorization', auth_scheme: str = 'Bearer', secret: str | None = None, token_cls: type[JWToken] = <class 'dmr.security.jwt.token.JWToken'>, leeway: int = 0, accepted_audiences: str | Sequence[str] | None = None, accepted_issuers: str | Sequence[str] | None = None, require_claims: Sequence[str] | None = None, verify_expiry: bool = True, verify_issued_at: bool = True, verify_jwt_id: bool = True, verify_not_before: bool = True, verify_subject: bool = True, strict_audience: bool = False, enforce_minimum_key_length: bool = True)[source]¶
Sync jwt auth.
- __call__(endpoint: Endpoint, controller: Controller[BaseSerializer]) Self | None[source]¶
Does check for the correct jwt token.
- authenticate(request: HttpRequest, token: JWToken) AbstractBaseUser[source]¶
Run all auth pipeline.
- check_auth(user: AbstractBaseUser, token: JWToken) None[source]¶
Run extra auth checks, raise if something is wrong.
- claim_from_token(token: JWToken) str¶
Return claim value from the token object.
Override this method if you want to change how claim is extracted from token. For example, if you create
emailclaim, it will be stored in.extras.So, you would need to use:
token.extras['email'].
- get_token_from_request(request: HttpRequest) str | None¶
Gets the jwt token from the request.
By default, it is in headers. Customize this method to get the token from cookies or body.
- prepare_token(request: HttpRequest) JWToken | None¶
Fetches JWToken instance from the auth header.
- provide_response_specs(metadata: EndpointMetadata, controller_cls: type[Controller[BaseSerializer]], existing_responses: Mapping[HTTPStatus, ResponseSpec]) list[ResponseSpec]¶
Provides responses that can happen when user is not authed.
- property security_schemes: dict[str, SecurityScheme | Reference]¶
Provides a security schema definition.
- set_request_attrs(request: HttpRequest, user: AbstractBaseUser, token: JWToken) None[source]¶
Set current user as authed for this request.
- class dmr.security.jwt.auth.JWTAsyncAuth(*, user_id_field: str = 'pk', algorithm: str = 'HS256', security_scheme_name: str = 'jwt', auth_header: str = 'Authorization', auth_scheme: str = 'Bearer', secret: str | None = None, token_cls: type[JWToken] = <class 'dmr.security.jwt.token.JWToken'>, leeway: int = 0, accepted_audiences: str | Sequence[str] | None = None, accepted_issuers: str | Sequence[str] | None = None, require_claims: Sequence[str] | None = None, verify_expiry: bool = True, verify_issued_at: bool = True, verify_jwt_id: bool = True, verify_not_before: bool = True, verify_subject: bool = True, strict_audience: bool = False, enforce_minimum_key_length: bool = True)[source]¶
Async jwt auth.
- async __call__(endpoint: Endpoint, controller: Controller[BaseSerializer]) Self | None[source]¶
Does check for the correct jwt token.
- async authenticate(request: HttpRequest, token: JWToken) AbstractBaseUser[source]¶
Run all auth pipeline.
- async check_auth(user: AbstractBaseUser, token: JWToken) None[source]¶
Run extra auth checks, raise if something is wrong.
- claim_from_token(token: JWToken) str¶
Return claim value from the token object.
Override this method if you want to change how claim is extracted from token. For example, if you create
emailclaim, it will be stored in.extras.So, you would need to use:
token.extras['email'].
- get_token_from_request(request: HttpRequest) str | None¶
Gets the jwt token from the request.
By default, it is in headers. Customize this method to get the token from cookies or body.
- prepare_token(request: HttpRequest) JWToken | None¶
Fetches JWToken instance from the auth header.
- provide_response_specs(metadata: EndpointMetadata, controller_cls: type[Controller[BaseSerializer]], existing_responses: Mapping[HTTPStatus, ResponseSpec]) list[ResponseSpec]¶
Provides responses that can happen when user is not authed.
- property security_schemes: dict[str, SecurityScheme | Reference]¶
Provides a security schema definition.
- async set_request_attrs(request: HttpRequest, user: AbstractBaseUser, token: JWToken) None[source]¶
Set current user as authed for this request.
- dmr.security.jwt.auth.request_jwt(request: HttpRequest, *, strict: Literal[True]) JWToken[source]¶
- dmr.security.jwt.auth.request_jwt(request: HttpRequest, *, strict: bool = False) JWToken | None
Returns a JWToken from request, if it was authed with it.
When strict is passed and request has no jwt token, we raise
AttributeError.
Pre-defined views to fetch JWT tokens¶
- class dmr.security.jwt.views.ObtainTokensSyncController(**kwargs)[source]¶
Sync controller to get access and refresh tokens.
- jwt_audiences¶
String or sequence of string of audiences for JWT token.
- Type:
ClassVar[str | collections.abc.Sequence[str] | None]
- jwt_expiration¶
Default access token expiration timedelta.
- Type:
ClassVar[datetime.timedelta]
- jwt_refresh_expiration¶
Default refresh token expiration timedelta.
- Type:
ClassVar[datetime.timedelta]
- jwt_secret¶
Alternative token secret for signing. By default uses
secret.SECRET_KEY- Type:
ClassVar[str | None]
- jwt_token_cls¶
Possible custom JWT token class.
- Type:
ClassVar[type[dmr.security.jwt.token.JWToken]]
See also
https://pyjwt.readthedocs.io/en/stable for all the JWT terms and options explanation.
- abstractmethod convert_auth_payload(payload: _ObtainTokensT) ObtainTokensPayload[source]¶
Convert your custom payload to kwargs that django supports.
See
django.contrib.auth.authenticate()docs on which kwargs it supports.Basically it needs
usernameandpasswordstrings.
- create_jwt_token(*, subject: str | None = None, issuer: str | None = None, audiences: str | Sequence[str] | None = None, expiration: datetime | None = None, jwt_id: str | None = None, token_type: Literal['access', 'refresh'] | None = None, secret: str | None = None, algorithm: str | None = None, token_headers: dict[str, Any] | None = None) str¶
Create correct jwt token of a give expiration and type.
- login(parsed_body: _ObtainTokensT) _TokensResponseT[source]¶
Perform the sync login routine for user.
- class dmr.security.jwt.views.ObtainTokensAsyncController(**kwargs)[source]¶
Async controller to get access and refresh tokens.
- jwt_audiences¶
String or sequence of string of audiences for JWT token.
- Type:
ClassVar[str | collections.abc.Sequence[str] | None]
- jwt_expiration¶
Default token expiration timedelta.
- Type:
ClassVar[datetime.timedelta]
- jwt_refresh_expiration¶
Default refresh token expiration timedelta.
- Type:
ClassVar[datetime.timedelta]
- jwt_secret¶
Alternative token secret for signing. By default uses
secret.SECRET_KEY- Type:
ClassVar[str | None]
- jwt_token_cls¶
Possible custom JWT token class.
- Type:
ClassVar[type[dmr.security.jwt.token.JWToken]]
See also
https://pyjwt.readthedocs.io/en/stable for all the JWT terms and options explanation.
- abstractmethod async convert_auth_payload(payload: _ObtainTokensT) ObtainTokensPayload[source]¶
Convert your custom payload to kwargs that django supports.
See
django.contrib.auth.authenticate()docs on which kwargs it supports.Basically it needs
usernameandpasswordstrings.
- create_jwt_token(*, subject: str | None = None, issuer: str | None = None, audiences: str | Sequence[str] | None = None, expiration: datetime | None = None, jwt_id: str | None = None, token_type: Literal['access', 'refresh'] | None = None, secret: str | None = None, algorithm: str | None = None, token_headers: dict[str, Any] | None = None) str¶
Create correct jwt token of a give expiration and type.
- async login(parsed_body: _ObtainTokensT) _TokensResponseT[source]¶
Perform the async login routine for user.
- class dmr.security.jwt.views.ObtainTokensPayload[source]¶
Bases:
TypedDictPayload for default version of a jwt request body.
Is also used as kwargs for
django.contrib.auth.authenticate().
Blocklist app¶
- class dmr.security.jwt.blocklist.auth.JWTokenBlocklistSyncMixin[source]¶
Sync mixin for working with tokens blocklist.