-
-
Notifications
You must be signed in to change notification settings - Fork 795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JSONOAuthLibCore breaks multipart form-data request for django-rest-framework #296
Comments
Hi @sacgup could you provide a minimum working example I can work with? I haven't found a simple workaround and need to investigate further. |
Hi @masci Just override the default oauth2 backend class from OauthLibCore to JSONOauthLibCore in settings.py.
and use the authentication class from oauth2_provider in django rest framework. You will be able to see the error. What i have found out till now: The calls to oauth2_provider to get access token will work. Only call to other rest Api's will fail. |
I stubble upon the same issue today. You can't read the request body twice indeed. A simple fix would be to force users to use the It that's a yes, I'm happy to make a pull request for this. For now my work around is to override the class OAuthHeaderBasedAuthenticationCore(OAuthLibCore):
def extract_body(self, request):
"""
Explanation on why we override this method
NB: because the authentication stage doesn't need to read the request body
indeed the authentication credentials are available in the `Authorization` header
and recent versions of Django it can't be read twice.
So without this custom OAuth2 core class multipart-form request are broken
"""
return {} OAUTH2_PROVIDER = {
#...
# NB: switch the oauth backend to avoid reading the body twice and breaking multipart-forms
'OAUTH2_BACKEND_CLASS': 'apps.apiv1.oauth2_backends.OAuthHeaderBasedAuthenticationCore',
} |
@dulaccc simply use your own backend this way: from rest_framework.request import Request
from oauth2_provider import oauth2_backends
class OAuthLibCore(oauth2_backends.OAuthLibCore):
"""Backend for Django Rest Framework"""
def extract_body(self, request):
"""
DRF object keeps data in request.DATA whether django request
inside POST
"""
if isinstance(request, Request):
try:
return request.DATA.items()
# complex json request (list?) is not easily serializable
except (ValueError, AttributeError):
return ""
return super(OAuthLibCore, self).extract_body(request) |
Nice @pySilver that's a way better implementation, more general in the case handling. |
@dulaccc also, about built in integration with DRF be aware of:
|
Hi @dulacp, I am facing the same issue that is "You cannot access body after reading from request's data stream" when I am trying to POST data to a Django REST API. REST_FRAMEWORK = { ... 'DEFAULT_AUTHENTICATION_CLASSES': ( ... 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ... ), I have downloaded "django-oauth-toolkit" last week using the command: Could you please help? |
I used JSONOAuthLibCore to accept JSON data for getting tokens.
But after using it gives error for multipart form-data request calls to my api's which are made using django-rest-framework. I need to use multipart-form data to upload files only and json for all other requests.
I used below class for authentication in settings.py
Error given is "You cannot access body after reading from request's data stream".
On investigation i found django doesn't support to read from request body twice. Once it is read in JSONOAuthLibCore so when django reads data again in "django/http/request.py" it gives error at that time.
I used JSONOAuthLibCore so that my all api call to my view and oauth2 to get token are similar and accepts only json.
1.) Why oauth2 need to read body data only to authenticate request ? It should only read Authorization header and check the token to validate the user. It should read body data only when granting tokens.
2.) Any workaround for this problem ?
I can make my oauth2 call to send "x-www-form-urlencoded" data from client apps and json for rest of my views but i really don't want to do that.
PS: I am new to django-rest-framework, oauth2 and token authentication. So if i am missing something obvious please bear with me.
The text was updated successfully, but these errors were encountered: