Skip to main content
DRF And React By Schema - OAuth

drf-react-by-schema-oauth

OAuth 2.1 authorization server + resource server for projects built with drf-react-by-schema (DRBS).

It turns any DRBS Django/DRF project into a standard OAuth 2.1 provider — with PKCE and Dynamic Client Registration (RFC 7591) — so MCP clients such as opencode (and, later, the SPA/mobile app) can authenticate through a server-rendered Django login/consent page, with no React changes.

About the suite

drf-react-by-schema is a suite that builds headless Django + React applications directly from your models:

  • drf-react-by-schema-django (PyPI) — generates the DRF API (serializers, viewsets, filters, schemas) from your models;

  • drf-react-by-schema-react (npm) — consumes those schemas to build the React forms, grids and CRUD interfaces;

  • drf-react-by-schema-oauth (this package) — adds the authorization layer so clients can obtain and use OAuth 2.1 tokens against the same API;

  • drf-react-by-schema-mcp — a generic, schema-driven MCP server that exposes a DRBS project to MCP clients, authorized by this package’s tokens.

About this package

DRBS projects expose a rich DRF API generated from the Django models. This package adds the missing authorization layer on top of django-oauth-toolkit (DOT):

  • an OAuth 2.1 authorization server (authorization code + PKCE S256, refresh token);

  • Dynamic Client Registration (RFC 7591) so opencode mcp auth <sistema> works with no manual client setup;

  • Authorization Server Metadata (RFC 8414) and a helper to build Protected Resource Metadata (RFC 9728; served by the MCP package);

  • a DRF authentication class and read/write scope permissions that authenticate both /mcp and /api/... with the same Bearer token;

  • server-rendered login/consent templates that projects can override.

It is additive and opt-in: it does not replace Django auth or SimpleJWT, and requires no SPA work.

Compatibility

The base DRBS package supports Django ≥ 3.2, and some deployments are still on Django 3.2. Newer django-oauth-toolkit (3.x) requires Django ≥ 4.2, so this package pins the 2.x DOT line (django-oauth-toolkit>=2.4,<3.0), which supports Django 3.2 through 5.x. (The suite’s roadmap is to move consumer apps to Django 5, at which point the DOT pin can be relaxed.)

Pre-requisites

  • Django ≥ 3.2

  • djangorestframework

  • django-oauth-toolkit (2.x, installed automatically)

Quick start

  1. Install:

    pip install drf-react-by-schema-oauth
  2. Add the DOT app and this package to INSTALLED_APPS (order matters — oauth2_provider first):

    INSTALLED_APPS = [
        ...
        'oauth2_provider',
        'drf_react_by_schema_oauth',
    ]
  3. Include the URLs:

    from django.urls import include, path
    
    urlpatterns = [
        ...
        path('', include('drf_react_by_schema_oauth.urls')),
    ]
  4. Migrate (creates DOT’s token/application tables):

    python manage.py migrate

That is the whole consumer contract: two apps, one include(), one migrate.

Accepting OAuth tokens on your API

To let the same Bearer token authenticate /api/... (used by the SPA via JWT and by MCP via OAuth), add the authentication class to your DRF settings or per viewset:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'drf_react_by_schema_oauth.authentication.OAuth2Authentication',
    ),
    ...
}

Then add HasScope where you want OAuth tokens to be scope-limited (e.g. a read-only token cannot write). It is composable: requests authenticated by session/JWT are left to your own permissions, only OAuth tokens are scope-checked.

from rest_framework.permissions import IsAuthenticated
from drf_react_by_schema_oauth.permissions import HasScope

class MyViewSet(viewsets.ModelViewSet):
    authentication_classes = [
        JWTAuthentication,
        SessionAuthentication,
        OAuth2Authentication,
    ]
    permission_classes = [IsAuthenticated, HasScope]

A view can demand an explicit set instead of the default method mapping:

class ReportView(APIView):
    required_scopes = ['read']
    permission_classes = [IsAuthenticated, HasScope]

Settings

All settings live in a single optional DRBS_OAUTH dict:

DRBS_OAUTH = {
    # Canonical public base URL of the authorization server (RFC 8414
    # `issuer`). Set it in production; when unset it is derived from the
    # request origin.
    'ISSUER': 'https://auth.example.org',

    # Scopes advertised and accepted (name -> description).
    'SCOPES': {
        'read': 'Read access to the API.',
        'write': 'Write access to the API.',
    },

    # Dynamic Client Registration.
    'DCR_ENABLED': True,
    'DCR_ALLOWED_REDIRECTS': [  # scheme+host prefixes; loopback by default
        'http://127.0.0.1',
        'http://localhost',
        'http://[::1]',
    ],

    # Optional template overrides (see "Templates" below).
    'LOGIN_TEMPLATE': None,     # defaults to "drbs_oauth/login.html"
    'CONSENT_TEMPLATE': None,   # defaults to "drbs_oauth/authorize.html"

    # Reserved.
    'AUDIENCE': None,
    'ACCESS_TOKEN_TTL': None,
    'REFRESH_TOKEN_TTL': None,
}

Endpoints

  • /.well-known/oauth-authorization-server — Authorization Server Metadata (RFC 8414)

  • /o/authorize/ — authorization endpoint (login + consent)

  • /o/token/ — token endpoint

  • /o/revoke_token/ — token revocation (RFC 7009)

  • /o/introspect/ — token introspection (RFC 7662)

  • /o/register/ — Dynamic Client Registration (RFC 7591)

  • /o/login/ — server-rendered login page

Scopes

Two scopes are defined and advertised:

  • read — safe methods (GET/HEAD/OPTIONS/TRACE);

  • write — unsafe methods (POST/PUT/PATCH/DELETE).

The names are also exported as constants (drf_react_by_schema_oauth.SCOPE_READ / SCOPE_WRITE).

Templates

The login and consent pages are plain server-rendered HTML and require no build step. Override them either by pointing DRBS_OAUTH at your own template names (LOGIN_TEMPLATE / CONSENT_TEMPLATE) or by shadowing drbs_oauth/login.html / drbs_oauth/authorize.html from a project template directory.

Using with MCP (opencode)

Once a project is deployed with this package (and the MCP package mounts /mcp), an opencode user authorizes with:

opencode mcp auth <sistema>

opencode:

  1. discovers the authorization server (via the resource server’s Protected Resource Metadata and/or /.well-known/oauth-authorization-server);

  2. registers a client dynamically at /o/register/;

  3. opens the Django-rendered login/consent page in the browser;

  4. stores a per-user access/refresh token and calls /mcp with it.

No credential is ever centralized: each system authorizes its own users and keeps Django as the permission authority.

Security notes

  • Dynamic client registration creates public clients only (no client secret), and redirect URIs are restricted to loopback by default (RFC 8252); plain http is allowed only for loopback hosts.

  • Access and refresh tokens are stored by DOT as its own hashed records — this package introduces no additional secret store.

  • Set DRBS_OAUTH['ISSUER'] in production so the advertised issuer does not depend on the incoming Host header.

  • Introspection is protected by DOT and requires a Bearer token carrying the introspection scope.

License

GNU General Public License v3 — see LICENSE.

Metadata

Release files for drf-react-by-schema-oauth 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for drf-react-by-schema-oauth 0.1.0
File Size Uploaded
drf_react_by_schema_oauth-0.1.0.tar.gz 594.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for drf-react-by-schema-oauth 0.1.0
File Interpreter ABI Platform
drf_react_by_schema_oauth-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 636.2 kB

Release files / drf_react_by_schema_oauth-0.1.0.tar.gz

Download URL drf_react_by_schema_oauth-0.1.0.tar.gz
Size 594.6 kB
Tags Source
SHA-256 checksum
How to use checksums
76d7b2ffbdd56b3aa466c1f2cfa9821afcc03f506257c7efa165e4c9a3fe3792
BLAKE2b-256 checksum
How to use checksums
07f3e1218f232797a0b22a0c160f6a42a0a01c9b7ee5a2dac6cb292bd19c08aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.9

Release files / drf_react_by_schema_oauth-0.1.0-py3-none-any.whl

Download URL drf_react_by_schema_oauth-0.1.0-py3-none-any.whl
Size 41.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3bfc567254b5fdeecc1a9bd2ab907b2c226601c009e6239055fee8b58ef09d2a
BLAKE2b-256 checksum
How to use checksums
028140a268864ddc9c86c38fbcfb45818248cc8db788ce214765407a43f5aceb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.9

Release history Release notifications | RSS feed

0.1.2

1 release file

0.1.1

1 release file

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page