I am using drf-yasg library for the Django Swagger. I need to add the authentication on username and password level. There are three security schemes available in this library "basic", "apiKey" or "oauth2".
Is there any way I can set my credentials for swagger in my django project settings and authenticate the swagger apidocs based on that?
To have the popup for authentication in 'DRF' and also in 'SWAGGER' panel, simply add these lines of code which I arrowed to your settings.py:
'DRF' implementation
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
# the link you can read about
# https://stackoverflow.com/questions/51906745/django-rest-framework-logout-not-working-after-token-authentication
'rest_framework.authentication.BasicAuthentication', # <<--
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}
In REST_FRAMEWORK, inside the DEFAULT_AUTHENTICATION_CLASSES, (which is a list) add the
rest_framework.authentication.BasicAuthentication.
It tells the djagno to authenticate using the default authentication that djagno provides.
'SWAGGER' implementation
If you want to use it in 'SWAGGER' as well, do the below:
In SWAGGER_SETTINGS, inside the SECURITY_DEFINITIONS which is a dict, add these lines of code to implement that:
'basic': {
'type': 'basic'
},
Default 'swagger' settings would be like this:
SWAGGER_SETTINGS = {
'DOC_EXPANSION': 'list',
'APIS_SORTER': 'alpha',
'USE_SESSION_AUTH': False,
'SECURITY_DEFINITIONS': {
'Bearer': { # <<-- is for JWT access token
'type': 'apiKey',
'name': 'Authorization',
'in': 'header'
},
'basic': { # <<-- is for djagno authentication
'type': 'basic'
},
},
}
Attention that Bearer is for JWT access token. basic is for djagno authentication.
Thant you for reading!
While working with the rest framework and frontend native client, I need to log in with both native clients and directly to the API endpoint for development and testing purpose.
Native client login requires token authentication and direct API login requires session authentication. But if I put both in settings.py as default I get csrf error from the native client and if I remove session auth I am not able to login directly to API (I can still log in to the admin console).
My settings .py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
],
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
}
What can be done to log in from both for development and testing? Any help?
#Daniel This is my current setting, check if this helps you -
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
# 'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
}
AUTHENTICATION_BACKENDS = (
# Needed to login by username in Django admin, regardless of `allauth`
"django.contrib.auth.backends.ModelBackend",
# `allauth` specific authentication methods, such as login by e-mail
"allauth.account.auth_backends.AuthenticationBackend"
)
I'm developing a Django application for Windows with Pyhton 2.7.15. I need to implement an authentication mechanism where if a user has a specific JWT token, he can browse the application (in other words, I just need to verify the token and not generate it). The token is very easy and maybe will be something like this:
Header
{
"alg": "HS256",
"typ": "JWT"
}
Payload
{
"iss": "customIssuer"
}
Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
To implement the verification's service, I installed the Rest framework JWT tools and I modifyed my setting.py in this way:
...
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.TokenAuthentication'
),
}
JWT_AUTH = {
'JWT_ISSUER': 'customIssuer'
}
...
then I modifyed the urls.py:
...
from rest_framework_jwt.views import verify_jwt_token
urlpatterns = [
...
url(r'^api-token-verify/', verify_jwt_token),
...
]
Finally, using Postman, I tryed to send a POST request with the above token but I get a 400 Bad Error error with this body:
{
"non_field_errors": [
"Invalid payload."
]
}
Investigating about the reason I realize that I must add the username claim in the payload but I don't want to. It's possible to configure the application to ignore that claim?
I have a REST API created with Django rest framework. To authenticate my API calls I am using OAuth2 tokens. My question is how can I enable standard username/password authentication in docs generated by Django rest swagger.
Right now i am gettings
401 : {"detail":"Authentication credentials were not provided."} http://127.0.0.1:8000/docs/?format=openapi
settings
REST_FRAMEWORK = {
# Don't perform any authentication on API calls so we don't have any CSRF problems
# :PRODUCTION: Put back authentication for production version when not testing on same server?
'DEFAULT_AUTHENTICATION_CLASSES': [
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
'rest_framework_social_oauth2.authentication.SocialAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'PAGE_SIZE': 1000, # Max number of results returned from a list API call
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
# Use JSONRender so the Web API interface is not shown. This is needed when testing the app on the same server
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
)
}
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'veeu': {
'type': 'oauth2',
'flow': 'password',
'tokenUrl': 'http://localhost:8000/auth/token/',
'scopes': {
'write:all': 'Write all',
'read:all': 'Read all',
}
}
},
}
LOGIN_URL = 'http://localhost:8000/admin/'
When I click Django login it takes me to admin login page. And after I log in, this message is still the same. If I add header Authorization: Bearer TokenHere it works. However, the point is to enable username/password login.
To access Swagger documentation, you need SessionAuth with the following in the settings.py :
# API VERSIONING
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated'
],
}
This allows you to access Swagger generated documentation. Problem is, whatever endpoint you have protected with OAuth2 won't be visible via Swagger, at least if you are generating OAuth via "application". The following code does not work at all and I'm linking the thread discussed asking for anyone to work on that feature:
# TODO Swagger implementation is not working for password since
# it sends client_id and client_secret as query strings and not as
# user separated with "::"
# The "application" flow setting also that does work
#
SWAGGER_SETTINGS = {
'SUPPORTED_SUBMIT_METHODS': [], # Due to bug described above
'SECURITY_DEFINITIONS': {
"customers_auth": {
"type": "oauth2",
"tokenUrl": "/o/token/",
"flow": "password",
"scopes": {
"read": "Read scope",
"write": "Write scope"
}
}
},
}
I am using both great tools DRF and Django-REST-Swagger, however a few of my API views are under token authentication.
So now I'd like to add to my swagger doc page of my API the possibility to test those token auth api urls, including the Token header. How could I do this?.
A snapshot of my class API view is like this:
class BookList(APIView):
"""
List all books, or create a new book.
"""
authentication_classes = (TokenAuthentication, )
permission_classes = (IsAuthenticated,)
...
Since Swagger auto detects a lot of stuff, I was expecting to notice about token auth, and ask me about token or user id in its web interface, but it doesn't. Hence I am testing it manually through CURL commands...
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.
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 :-)
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'
)
}
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.
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.
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.
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
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.