I have a DRF api which does not have any authentication system (because the concept of a user is meaningless there). And yet I want to make the api be restricted only to known clients. In other words, I want to come up with an api-to-api authentication rather than user-to-api authentication. Is that possible in DRF ? And are there any ready-to-use libs out there ?
You can use a permission class for it. Define a permission class that inherited from permissions.BasePermission
from rest_framework import permissions
class SamplePermission(permissions.BasePermission):
def has_permission(self, request, view):
return request.META.get('HTTP_YOUR_KEY','') in ['some_key']
and define it inside your view as permission_classes
class SampleViewSet(views.APIView):
...
permission_classes = [SamplePermission]
I can't say this is the best way but you can use it with this.
Related
I'm using Django rest-auth for authentication and account creation with Django rest framework. Currently, I have six providers set up and I'd like to start connecting them.
It's not clear from the documentation (either rest-auth or all-auth) what I have to do to connect the accounts.
For example, if I try to connect a Google account to a LinkedIn one (same email address), even if I make a POST request to /rest-auth/linkedin/connect/ with the correct access token for the Google provider, I get a 400 response saying: "non-field-errors": [ "Incorrect value" ].
I'm using JWTs for authentication, and providing the correct token in the Authorization header.
views.py
class GoogleConnect(SocialConnectView):
adapter_class = GoogleOAuth2Adapter
class LinkedInConnect(SocialConnectView):
adapter_class = LinkedInOAuth2Adapter
I've written a tutorial that should cover your question. This should be the part you are looking for.
In short: You have to write your own ConnectView which inherits from the rest_auth view like this:
class GoogleCallbackConnect(SocialConnectView):
"""
Connects the provider's user account to the currently logged in user.
"""
adapter_class = GoogleOAuth2Adapter
client_class = OAuth2Client
#property
def callback_url(self):
url = self.adapter_class(self.request).get_callback_url(
self.request,
None,
)
return url
I setup a contentful account for downloading videos and its returning 403 when i tried to add a webhhok to an api in my django rest project. I am new to both django rest and contentful.
http://my_server_id/testhook
I setup the hook and added my api url. So it called my api when the event triggered. But all time in django rest it shows forbidden.What extra measures should i choose when integrating webhook with django rest?
Your problem probably because of csrf token, you should pass it in a header with a POST request.
X-CSRFToken: value.
docs about csrf
Like #Linovia said in comment, csrf_exempt already exempted in a view, but because of session there is still an explicit check.
Here is a nice answer about this problem:
Django Rest Framework remove csrf
In a nutshell you could inherit from SessionAuthentication class and override enforce_csrf.
from rest_framework.authentication import SessionAuthentication
class CsrfExemptSessionAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return # To not perform the csrf check previously happening
Set it in a view or in a basic Django REST config:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
Using the TokenAuthentication from DRF to authenticate the web frontend. We have a situation where some times the CSRF cookie becomes invalid due to using different URLs to access the same website. Of cause the user needs to clear the cookies before they can log in again (all expected behaviour).
Would like to delete the cookies with Django by setting the CSRF_FAILURE_VIEW value within the django setting and have a custom view that calls request.session.delete()
But...
DRF overrides the function _reject for the Django class CsrfViewMiddleware which means the setting CSRF_FAILURE_VIEW is never accessed.
class CSRFCheck(CsrfViewMiddleware):
def _reject(self, request, reason):
# Return the failure reason instead of an HttpResponse
return reason
Any ideas as to how this can be addressed?
I've set a default authentication class as I needed most of apis to be authenticated before being accessible. However, I need login api to be available to all user.
I don't see negative authentication class in django-rest-framework.
How do I let my login api to be available to guest users while not making view level authentication_classes declarations?
This problem arose because I'm not using django's User model. How do I create AnonymousUser instance for my custom User model (not inherited from django's user model) and then permit that user to interact with the apis?
EDIT
Mark Galloway reminded me of mentioning the same issue with permission_classes.
Authentication alone does not prevent a user from accessing resources. A combination of authentication and permissions is the actual determiner for this. For example, if your permissions are set to 'permissions.IsAuthenticatedOrReadyOnly' then users who fail to authenticate (eg/ no valid token) can still access the retrieve and list endpoints.
How exactly you want to define your permissions is up to you. For most of my implementations I use a global permissions setting but tag my log in endpoint with view-level AllowAny permissions. Additionally, view-level authentication for a specific is the only way to override global authentication settings.
For example:
class login(viewsets.GenericViewSet):
permission_classes = (permissions.AllowAny,)
I have an app without models or any database connectivity.
I have a method defined in the ApplicationController called "api_call" which does all api calls within the app. This method uses the ruby session to store things about the user, such as authentication info, access token info, and user info. In the session I store an Authentication hash for sending to the api for security when the user is logged.
Two things:
I'd like to put all api calls (the api_call method) in models (that don't use db or validation), but the problem is I don't have access session.
If I use a module, the module in the model also doesn't have access to the session.
If I create a model class without using ActiveRecord, should I use class methods rather than object methods?
How about passing the "authentication hash" to the API model's constructor?
class Api
def initialize auth
#auth = auth
end
end
class FooController < ApplicationController
def index
api = Api.new session[:auth]
end
end
Also, if you haven't see Pratik Naik's article about this, it's pretty funny.