I'm new to backend.
I'm trying to fetch my data in the backend via API token, and I followed this tutorial: https://www.django-rest-framework.org/api-guide/authentication/
When I add these two lines in my View code, I can't fetch my data:
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
The error is
{
"detail": "Authentication credentials were not provided."
}
and on my backend I got
"GET /hello/ HTTP/1.1" 403 58
But if I delete those two lines, I can fetch my data successfully.
This is my View class:
`class HelloView(APIView):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
print(request.auth)
content = {
'user': str(request.user),
'auth': str(request.auth),
}
return Response(content)`
In the tutorial, it says when I have those two lines, I will be able to view my user name and token in the user router. But I got none for my "auth". However, if I delete those two lines, I can view my "user" and "auth" on my Windows side.
Screenshots:
backend side, with those two lines
frontend side, with those two lines
frontend side, without those two lines
Could anybody explain this to me please? Any help would be nice!
Thank you so much!
Related
I am opening this question as a last resort.
I am learning JWT and want to implement it on my django app. I didn't have any issues regarding Basic auth and Token auth, but JWT doesn't authenticate my user...
This is my settings.py:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
'api.permissions.AdminOrTeacherOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
]
}
This is my view:
class StudentList(APIView):
authentication_classes = []
permission_classes = [AdminOrTeacherOnly]
def get(self, request, format=None):
students = Student.objects.all()
serializer = StudentListSerializer(students, many=True)
if not serializer.data:
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.data, status=status.HTTP_200_OK)
This is my AdminOrTeacherOnly permission class:
class AdminOrTeacherOnly(permissions.BasePermission):
"""
Object-level permission to only allow teachers of a student to edit.
Assumes the model instance has an `owner` attribute.
"""
message = 'Only admin or teacher can edit student detail.'
def has_permission(self, request, view):
# Only teacher and/or admin user will be able to,
# edit and/or list this view.
is_staff = bool(request.user and request.user.is_staff)
is_teacher_group = str(request.user.groups.all().first()) == 'teacher'
return is_staff or is_teacher_group
I am able to get refresh and access token successfully:
Then, I am adding this to Headers as follows and send a request:
On debugger, when it enters the permission class:
Here, request.user returns <django.contrib.auth.models.AnonymousUser object at 0x104f5afd0>
I don't know what I am missing. Looked at related questions but couldn't find anything helpful regarding the SimpleJWT.
You're overriding authentication_classes here:
class StudentList(APIView):
authentication_classes = []
Add JWTAuthentication to that list.
I need to sign in a user using firebase from my django app.I have done what I think I needed to do but I seem to be missing something.I am using the pyrebase library.I have created a user on firebase and now I need to sign them in.
I am posting the email and password on Postman and I get the 'idToken' and 'refreshToken', which means the user gets authenticated on firebase.But this only works when I use the drf Token authentication(DEFAULT AUTH CLASSES) and authorization token of a user previously created on django admin. What am I missing so that I can authenticate the user without the drf token authentication?
views.py
config = {
"apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
"authDomain": "xxxxx.firebaseapp.com",
"databaseURL": "https://xxxxxxxxx-default-rtdb.firebaseio.com",
"storageBucket": "xxxxxxxxx.appspot.com",
}
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
class Auth(APIView):
def post(self, request, format=None):
email = "xxxx#gmail.com"
password = "xxxx"
user = auth.sign_in_with_email_and_password(email, password)
return Response(user)
Settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
}
Yeah so basically, you don't need any authorization in any of the authentication views. Since you have a global default of IsAuthenticated, you need to overwrite the permission_classes in the View.
class Auth(APIView):
permission_classes = []
def post(self, request, format=None):
...
Ideally using django-rest-framework-simplejwt and the authentication class JWTAuthentication, the API should give 403 when I pass the token incorrectly.
Instead, when I am making my API request it is executing successfully even without the Authentication token.
This is a dummy API, my concern is the Authentication should work.
My code looks like this:
class ViewSet(viewsets.ModelViewSet):
queryset = get_user_model().objects.all()
serializer_class = SomeSerializer
http_method_names = ("post", "patch")
authentication_classes = (JWTAuthentication,)
When I debug I see that it is executing JWTAuthentication, which in turn returns None.
Which is expected since I am not passing the Token in the header.
def authenticate(self, request):
header = self.get_header(request)
if header is None:
return None
Now I think the View should give Permission Denied, which is not happening.
Not able to understand what is missing here.
If you pass incorrect token, it'll return 401 status response.
But if you don't put authorization header on your request, django will not return 401 response and behave with request as AnonymousUser request.
If you want only authenticated users have access to your ViewSet, you should put permission_classes = [IsAuthenticated,] in your ViewSet.
IsAuthenticated permission class can be imported from rest_framework.permissions
My API is currently protected by the OAuth2TokenAuthentication from django-oauth-toolkit, so that it can validate API requests that contains access token in following ways:
as query param?access_token=xxxx
in header Authorization: Bearer xxxx
while I can hardcode in my API view to try to get the access token from those 2 places, is there a canonical way to obtain the token?
I dug through the code inside OAuth2TokenAuthentication, and borrowed it into my API View:
class IntrospectView(APIView):
"""
An API view that introspect a given token
"""
serializer_class = TokenIntrospectSerializer
authentication_classes = []
permission_classes = []
def get(self, request, *args, **kwargs):
oauthlib_core = get_oauthlib_core()
valid, r = oauthlib_core.verify_request(request, scopes=[])
if not valid:
raise APIException('Invalid token')
return Response(TokenIntrospectSerializer(r.access_token).data)
I'm using Django Rest Framework on the backend and an ember-cli app on the frontend. The authentication is working correctly, but there seems to be a hole somewhere in authorization.
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
}
# views.py
class CurrentUserView(APIView):
"get the data for the current authenticatd user"
permission_classes = (IsAuthenticated,)
def get_queryset(self, request):
queryset = User.objects.filter(username=request.user.username)
return queryset
def get(self, request):
serializer = UserSerializer(request.user)
return Response(serializer.data)
When I make a request to this endpoint /v1/me/ it responds back with a 403. When I take off the permission class, I get back {"id":null,"username":"","is_active":false} because it doesn't know who I am.
Also, when I use the browsable API, the /v1/me URL works correctly.
On the Ember side of things, I login with my account and correctly get back my Token. In the request the Authorization: Token asdf1234asdf1234asdf1234 is being passed. I would think Django takes that token and knows who I am? Am I missing something?
Try something like
from rest_framework import authentication
class TokenAuthView(APIView):
authentication_classes = (authentication.TokenAuthentication,)
Then,
class CurrentUserView(TokenAuthView)
In the setting you need to add auth_token.
# settings.py
INSTALLED_APP = ('rest_framework.authtoken',)
You don't need to add the authentication_classes on every view.