14π
I answer myself since I made it work.
Actually Swagger settings has an option for this, api_key ->
SWAGGER_SETTINGS = {
"exclude_namespaces": [], # List URL namespaces to ignore
"api_version": '0.1', # Specify your API's version
"api_path": "/", # Specify the path to your API not a root level
"enabled_methods": [ # Specify which methods to enable in Swagger UI
'get',
'post',
'put',
'patch',
'delete'
],
"api_key": '', # An API key
"is_authenticated": False, # Set to True to enforce user authentication,
"is_superuser": False, # Set to True to enforce admin only access
}
To me it wasnβt that clear, but Iβve just input a valid token for testing user and it worked for the auth needed views π
36π
If youβre using token authentication, you might want to look at this question
Basically, you just need to add this to your settings.py
:
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'api_key': {
'type': 'apiKey',
'in': 'header',
'name': 'Authorization'
}
},
}
In your Swagger UI page you should see an Authorize button. Click that and enter your Authorization value in the input text field.
- [Django]-Can I use Django F() objects with string concatenation?
- [Django]-Need to convert a string to int in a django template
- [Django]-Django 1.7 β "No migrations to apply" when run migrate after makemigrations
8π
My Problem was that after activating TokenAuthentification my api urls were not shown any more in the swagger UI due to an AuthentificationError.
For me the solution was to activate both authentaction classes in the Django Rest Framework Settings:
SessionAuthentification -> for the Swagger UI
TokenAuthentification -> for the Rest Clients
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
)
}
- [Django]-Django rest framework: set field-level error from serializer validate() method
- [Django]-Django and fieldsets on ModelForm
- [Django]-How to use UUID
8π
The schema view needs to have the permission of AllowAny. This allows the plugin to see which endpoints are available before the user has authenticated. The end points should still be protected if they are setup correctly. Example:
@api_view()
@renderer_classes([SwaggerUIRenderer, OpenAPIRenderer, renderers.CoreJSONRenderer])
@authentication_classes((TokenAuthentication, SessionAuthentication))
@permission_classes((AllowAny,))
def schema_view(request):
generator = schemas.SchemaGenerator(
title='My API end points',
patterns=my_urls,
url="/api/v1/")
return response.Response(generator.get_schema(request=request))
It is best to remove the SessionAuthentication and only use the TokenAuthentication but that is a matter of choice, here I have removed it
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated'
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication'
)
Be sure it add 'rest_framework.authtoken'
into your installed apps and remove the CsrfViewMiddleware
from the middleware classes as it will no longer be needed. And the swagger settings
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'api_key': {
'type': 'apiKey',
'in': 'header',
'name': 'Authorization'
}
},
'USE_SESSION_AUTH': False,
'JSON_EDITOR': True,
}
This will make swagger populate the token into all of the example curl commands as well, which is really nice to have. Leaving the session auth in place seems to disable this.
The swagger authorization dialog asks for the api_key
which needs to be provided. Can not seem improve this, will update this post if I do.
- [Django]-Add an object by id in a ManyToMany relation in Django
- [Django]-Where does pip install its packages?
- [Django]-Installing lxml with pip in virtualenv Ubuntu 12.10 error: command 'gcc' failed with exit status 4
2π
just add to you rest framework setting SessionAuthentication should be at the top
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'mymodule.authentication.CustomeAuthentication',
)
Note: SessionAuthentication will use your Django login session
CustomeAuthentication will be used for rest api for real use case.
- [Django]-How to show related objects in Django/Admin?
- [Django]-Django: multiple models in one template using forms
- [Django]-Using the reserved word "class" as field name in Django and Django REST Framework
1π
if you are implementing the answer of @Melvic Ybanez with django-rest-swagger==2.2.0 and still doesnβt work. Downgrade to django-rest-swagger==2.1.2.
Button authorize should work now.
- [Django]-Request.user returns a SimpleLazyObject, how do I "wake" it?
- [Django]-Django user get_all_permissions() is empty while user_permissions is set
- [Django]-How to auto insert the current user when creating an object in django admin?
0π
I manage to change Swaggerβs default basic authentication to token authentication with this configuration but when try me button is pressed rest swagger accepts any authentication regardless of valid token.
Also note, when I added SessionAuthentication to my REST_FRAMEWORK in my settings.py, my api failed to be displayed on swagger docs.
django-rest-swagger==2.2.0
djangorestframework==3.7.7
settings.py
INSTALLED_APPS = [
'rest_framework',
'rest_framework_swagger',
'rest_framework.authtoken',
]
REST_FRAMEWORK = {
# Parser classes priority-wise for Swagger
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
'rest_framework.parsers.JSONParser',
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
# SWAGGER SETTINGS
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'api_Key': {
'type': 'apiKey',
'in': 'header',
'name': 'Token Authorization'
}
},
}
some helpful documentation https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object
- [Django]-Web application monitoring best practices
- [Django]-Django-rest-framework how to make model serializer fields required
- [Django]-Django : Serving static files through nginx
0π
Please use rest_framework_jwt.authentication.JSONWebTokenAuthentication
instead of rest_framework.authentication.TokenAuthentication
.
My code is
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
'rest_framework.parsers.JSONParser',
),
}
AUTH_USER_MODEL = 'auth.User'
JWT_AUTH = {
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
'JWT_DECODE_HANDLER':
'rest_framework_jwt.utils.jwt_decode_handler',
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
'JWT_PAYLOAD_GET_USER_ID_HANDLER':
'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
'JWT_RESPONSE_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_response_payload_handler',
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 0,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=86400),
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_AUTH_HEADER_PREFIX': 'Bearer',
}
SWAGGER_SETTINGS = {
'SHOW_REQUEST_HEADERS': True,
'SECURITY_DEFINITIONS': {
'Bearer': {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header'
}
},
'USE_SESSION_AUTH': False,
'JSON_EDITOR': True,
'SUPPORTED_SUBMIT_METHODS': [
'get',
'post',
'put',
'delete',
'patch'
],
}
I solved the problem.
- [Django]-ImportError: No module named virtualenv
- [Django]-How to run own daemon processes with Django?
- [Django]-Using mock to patch a celery task in Django unit tests
0π
In my case, beside customizing (inheriting) OpenApiAuthenticationExtension
, I had to also import it some (doesnβt matter which) api.py
. Basically thatβs what Iβve done:
settings.py
INSTALLED_APPS = [
...
"django.contrib.admin",
"django.contrib.auth",
"mozilla_django_oidc", # <-- My custom auth backend uses that.
...
"rest_framework",
...
"drf_spectacular",
...
]
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"apps.auth.backends.CustomBearerTokenAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": (
"rest_framework.permissions.AllowAny",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}
apps.auth.backends:
from django.contrib.auth.backends import BaseBackend
class CustomBearerTokenAuthentication(BaseBackend):
"""Your custom Bearer Token Authentication Backend."""
...
apps.auth.scheme:
from django.utils.translation import gettext_lazy as _
from drf_spectacular.extensions import OpenApiAuthenticationExtension
class CustomTokenScheme(OpenApiAuthenticationExtension):
target_class = "apps.auth.backends.CustomBearerTokenAuthentication" # <-- Points to my custom auth backend.
name = "CustomBearerTokenAuth"
def get_security_definition(self, auto_schema):
return {
"type": "apiKey",
"in": "header",
"name": "Authorization",
"description": _('Token-based authentication with required prefix "%s"')
% "Bearer",
}
apps.users.api:
from django.contrib.auth import get_user_model
from rest_framework import mixins, viewsets
from apps.auth.scheme import CreooxTokenScheme # <-- Only after this import it starts to work!
from .serializers import UserSerializer
User = get_user_model()
class UserViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
serializer_class = UserSerializer
def get_queryset(self):
return User.objects.filter(id=self.request.user.id)
And finally you get:
- [Django]-How can I allow django admin to set a field to NULL?
- [Django]-Django save image from url and connect with ImageField
- [Django]-Parsing a Datetime String into a Django DateTimeField