HTTP Basic Auth

Docs: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication

Warning

HTTP Basic Auth is very insecure. It is better than nothing, but is not enough for nearly all real use-cases. Please, consider using JWT Auth instead.

The only reasonable use-case for this auth is to use HTTP Basic auth for protecting some public things like API status dashboards.

Note that this auth type does not set request.user by design. Because many users might use the same auth parameters.

Requiring auth

To work with HTTP Basic auth you would need to subclass either HttpBasicSyncAuth or HttpBasicAsyncAuth and override its sync or async (respectively) authenticate method, which will decide whether or not passed username and password are correct.

Here’s how to do it:

Let’s say we defined a horribly weak set of username and password: admin / pass. Let’s check that the auth works:

Run result

$ curl http://127.0.0.1:8000/api/username/ -D - -X POST -d '{"bill": "parking"}' -H 'Content-Type: application/json'
HTTP/1.1 401 Unauthorized
date: Thu, 07 May 2026 12:57:17 GMT
server: uvicorn
Content-Type: application/json
X-Frame-Options: DENY
Vary: Accept-Language
Content-Language: en
Content-Length: 58
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

{"detail":[{"msg":"Not authenticated","type":"security"}]}

$ curl http://127.0.0.1:8000/api/username/ -X POST -d '{"bill": "parking"}' -H 'Content-Type: application/json' -H 'Authorization: Basic YWRtaW46cGFzcw=='
"Processing bill: parking"

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": {
          "bill": {
            "title": "Bill",
            "type": "string"
          }
        },
        "required": [
          "bill"
        ],
        "title": "_RequestModel",
        "type": "object"
      }
    },
    "securitySchemes": {
      "http_basic": {
        "description": "Http Basic auth",
        "scheme": "basic",
        "type": "http"
      }
    }
  },
  "info": {
    "title": "Django Modern Rest",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/api/billcontroller/": {
      "post": {
        "deprecated": false,
        "operationId": "postBillcontrollerApiBillcontroller",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_RequestModel"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "Created"
          },
          "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": "Raised when auth was not successful"
          },
          "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"
          }
        },
        "security": [
          {
            "http_basic": []
          }
        ]
      }
    }
  }
}

Any other authentication method will be better than the one above. Consider using JWT Auth instead.

API Reference

class dmr.security.http.HttpBasicSyncAuth(*, security_scheme_name: str = 'http_basic', header: str = 'Authorization')[source]

Uses HTTP Basic Auth.

Subclass this type to provide actual username/password check according to your needs. This class is used for sync endpoints.

Note that this class does not set request.user by design. Because many users might use the same auth parameters.

Warning

HTTP Basic Auth is not really secure and should not be used for anything serious. Consider using JWT instead.

__call__(endpoint: Endpoint, controller: Controller[BaseSerializer]) Self | None[source]

Does the login routine.

abstractmethod authenticate(endpoint: Endpoint, controller: Controller[BaseSerializer], username: str, password: str) Self | None[source]

Override this method to provide an actual user/password check.

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_requirement: dict[str, list[str]]

Provides a security schema usage requirement.

property security_schemes: dict[str, SecurityScheme | Reference]

Provides a security schema definition.

class dmr.security.http.HttpBasicAsyncAuth(*, security_scheme_name: str = 'http_basic', header: str = 'Authorization')[source]

Uses HTTP Basic Auth.

Subclass this type to provide actual username/password check according to your needs. This class is used for async endpoints.

Note that this class does not set request.user by design. Because many users might use the same auth parameters.

Warning

HTTP Basic Auth is not really secure and should not be used for anything serious. Consider using JWT instead.

async __call__(endpoint: Endpoint, controller: Controller[BaseSerializer]) Self | None[source]

Does the login routine.

abstractmethod async authenticate(endpoint: Endpoint, controller: Controller[BaseSerializer], username: str, password: str) Self | None[source]

Override this method to provide an actual user/password check.

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_requirement: dict[str, list[str]]

Provides a security schema usage requirement.

property security_schemes: dict[str, SecurityScheme | Reference]

Provides a security schema definition.

dmr.security.http.basic_auth(username: str, password: str, *, prefix: str = 'Basic ') str[source]

Return a header value for basic auth for a given username and password.

>>> basic_auth('admin', 'pass')
'Basic YWRtaW46cGFzcw=='

>>> basic_auth('admin', 'pass', prefix='')
'YWRtaW46cGFzcw=='