This is the documentation of the development version, check the Stable Version documentation.

Resource Server

Protect users resources, so that only the authorized clients with the authorized access token can access the given scope resources.

A resource server can be a different server other than the authorization server. Here is the way to protect your users’ resources in Django:

from authlib.integrations.django_oauth2 import ResourceProtector, BearerTokenValidator
from django.http import JsonResponse

require_oauth = ResourceProtector()
require_oauth.register_token_validator(BearerTokenValidator(OAuth2Token))

@require_oauth('profile')
def user_profile(request):
    user = request.oauth_token.user
    return JsonResponse(dict(sub=user.pk, username=user.username))

If the resource is not protected by a scope, use None:

@require_oauth()
def user_profile(request):
    user = request.oauth_token.user
    return JsonResponse(dict(sub=user.pk, username=user.username))

# or with None

@require_oauth(None)
def user_profile(request):
    user = request.oauth_token.user
    return JsonResponse(dict(sub=user.pk, username=user.username))

The decorator require_oauth will add an oauth_token property on request, which is the instance of current in-use Token.

Multiple Scopes

Changed in version v1.0.

You can apply multiple scopes to one endpoint in AND, OR and mix modes. Here are some examples:

@require_oauth(['profile email'])
def user_profile(request):
    user = request.oauth_token.user
    return JsonResponse(dict(sub=user.pk, username=user.username))

It requires the token containing both profile and email scope.

@require_oauth(['profile', 'email'])
def user_profile(request):
    user = request.oauth_token.user
    return JsonResponse(dict(sub=user.pk, username=user.username))

It requires the token containing either profile or email scope.

It is also possible to mix AND and OR logic. e.g.:

@app.route('/profile')
@require_oauth(['profile email', 'user'])
def user_profile(request):
    user = request.oauth_token.user
    return JsonResponse(dict(sub=user.pk, username=user.username))

This means if the token will be valid if:

  1. token contains both profile and email scope
  2. or token contains user scope

Optional require_oauth

There is one more parameter for require_oauth which is used to serve public endpoints:

@require_oauth(optional=True)
def timeline_api(request):
    if request.oauth_token:
        return get_user_timeline(request.oauth_token.user)
    return get_public_timeline(request)