{"detail": "Authentication credentials were not provided."} postman and DRF - authentication

views.py
class ProductViewSet(viewsets.ModelViewSet):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAdminUser]
queryset = ProductInfo.objects.all().order_by('-id')
serializer_class = ProductSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ['title','code','owner__username']
setting.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
this is my view.. I tried several times to use my token to authenticate my user,, then use IsAdmin User permission to have an access to my view. you know. modelviewset supports POST,GET,PUT,DELETE method.I can't send request with none of them. my main issue is postman... I give my token to postman and I expect to authenticate my user via it's token. but now it looks like I have a big issue with authentication and permission and maybe with postman.
it drives me crazy....
please help me. I'm new to postman... I don't know really about it. I just know it made me crazy.

Related

Trello API: unauthorized permission requested

I'm trying to use the api to get the invitation secret to use it for creating share links. Here's my code:
URL = "https://trello.com/1/boards/" + boardid + "/invitationSecret"
query = {
'key': key,
'token': token
}
response = requests.request("POST", URL, params=query)
On execution, I get 'unauthorized permission requested'. I did checkout this post, but the solutions suggested there don't work for me.
Any help is appreciated.
You have to pay, free version can't write/post

ERPNext: How can I generate user session without Password?

As an ERPNext fresher, I am creating a REST API for the mobile app, where the use case is, the Mobile user will send a request to do login using Face authentication, as a result of Face authentication at the mobile end, it will return User ID(same as ERPNext UserID).
As a Param, I will get UserID and other params of API request, here in response, I have to send a new session generated for that User.
Applied solution:
Tried Login by fetching password of user based on UserID, which basically gives encryption error for encrypted password.
Tried bypass login and generate new session, failed due to password not being added
Decrypt the password to use as param for new session
My current problem is, I don't have Password in normal format, and need to generate a valid user session, for the next operation post face recognization(face validation is already done through SDK).
You can use token based authentication for REST Api, based on your question when you receive emailid (same as erpnext user id), you can identify the user and generate api_key and api_secret, you can return these keys in response to your request, also you can store these secrets keys and use for future requests to authenticate it
You can refer docs here https://frappeframework.com/docs/user/en/api/rest#1-token-based-authentication
Below is sample code, please note code is not tested, posted just for reference
#frappe.whitelist(allow_guest=True)
def validate_user(email):
user_email = frappe.db.get_all('User', filters={'name': email}, fields=['name'])
user = frappe.get_doc('User', user_email[0]['name'])
api_generate = generate_keys(user.name)
user_resp = frappe.get_doc('User', user.name)
frappe.response["message"] = {
"status": 1,
"message": "Authentication success",
"api_key": user_resp.api_key,
"api_secret": api_generate,
"username": user.username,
"email": user_resp.email,
"role": user_resp.roles[0].role
}
def generate_keys(user):
user_details = frappe.get_doc('User', user)
api_secret = frappe.generate_hash(length=15)
if not user_details.api_key:
api_key = frappe.generate_hash(length=15)
user_details.api_key = api_key
frappe.db.set_value('User', user, 'api_secret', api_secret)
return api_secret

Invalid CSRF token error ( symfony 5 ) with VueJs frontend

I am having trouble in making authentication work using an external frontend ( vue ) with my symfony app. The main problem is the "Invalid CSRF token" error. I have a login form in vue which sends an object containing the username, password, and the csrf token ( which I get from symfony tokengenerator ). I have a custom authenticator where I create the user passport and add the token to it.
public function authenticate(Request $request): PassportInterface
{
$username = $request->request->get('username', '');
$request->getSession()->set(Security::LAST_USERNAME, $username);
$this->logger->info('The token is', [$request->get('_csrf_token')]);
$passport = new Passport(
new UserBadge($username),
new PasswordCredentials($request->request->get('password', '')),
);
$passport->addBadge(new CsrfTokenBadge('authenticate', $request->get('_csrf_token')));
return $passport;
}
It makes it through to the AuthenticationManager.php, where it enters the executeAuthenticator method. The error comes after the CheckPassportEvent is dispatched, from CSRFProtectionListener. It fails on the
if (false === $this->csrfTokenManager->isTokenValid($csrfToken)).
I have tried to get the tokenmanager instance inside of my authenticator and create the token there and add it to the passport.
$token = $this->csrfTokenManager->getToken('authenticate'); $passport->addBadge(new CsrfTokenBadge($token->getId(), $token->getValue()));
This lets me get past the authentication, but immediately afterwards, when it redirects to the next path, it gives me an error "Access denied, the user is not fully authenticated; redirecting to authentication entry point.". After some debugging, it seems that the token storage is empty ( the token is saved to the storage when the getToken() method is called ).
When I do the authentication with the twig template, it works flawlessly. How exactly {{ csrf_token('authenticate') }} makes and handles the token I do not understand. Any input would be appreciated.
You have to pass the Authenticationintention as a string. In your example its "authenticate".
$passport->addBadge(new CsrfTokenBadge(' ---> authenticate <--- ', $request->get('_csrf_token')));
To check it you should use a code like this:
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate' $YOUR_TOKEN_HERE))
or from a controller:
$this->isCsrfTokenValid('authenticate', $YOUR_TOKEN_HERE)
enter code here
In Symfony 5 you should work with the CSRF Protection like this:
In Twig, you can generate a CSRF Token with the "csrf_token" method. This Method is described here https://symfony.com/doc/current/security/csrf.html#generating-and-checking-csrf-tokens-manually.
You can validate the token in a controller using the "isCsrfTokenValid" function which lives in the controller class which you are extending.
Check this for more information:
https://symfony.com/doc/4.4/security/csrf.html#generating-and-checking-csrf-tokens-manually
I think the problem is that youre using a new Symfony version but using old practicies.

Session Auth in Django-Rest-Framwork, Is this really what I have to do to make is CSRF safe?

First off, this code works, it just doesn't feel as clean as it should be for something so simple.
Background:
I'm trying to make a custom login API endpoint in DRF that will be consumed by the React Frontend. It seems you have to manually force a csrf to be sent in DRF so that's what I have done.
I didn't want to send over a Django Form because it didn't seem RESTful, but this is the only method I could find to avoid that. Please let me know if this is clean code.
Serializers.py
from rest_framework import serializers
from django.contrib.auth import get_user_model # If used custom user model
UserModel = get_user_model()
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
user = UserModel.objects.create_user(
username=validated_data['username'],
password=validated_data['password'],
email=validated_data['email'],
)
return user
class Meta:
model = UserModel
# Tuple of serialized model fields (see link [2])
fields = ( "id", "username", 'email', "password", )
View.py
from rest_framework import permissions
from django.contrib.auth import get_user_model # If used custom user model
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import UserSerializer
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
class CreateUserView(APIView):
model = get_user_model()
permission_classes = [
permissions.AllowAny # Or anon users can't register
]
serializer_class = UserSerializer
#method_decorator(ensure_csrf_cookie)
def get(self, request, format = None):
return Response(status=status.HTTP_200_OK)
#method_decorator(csrf_protect)
def post(self,request, format = None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.create(serializer.validated_data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
CSRF is enabled by Django, not DRF. And as specified, CSRF protections only kick in when logged in.
Login and registration actions does not need to be CSRF protected (as the password data is needed, and cannot be guessed, in a CSRF attack scenario) by the attacker.
Also per Django spec, GET actions/views are not protected by CSRF. However, GET actions should not change the state of your application. If it's not the case, and you're able to implemant the CSRF protection on your front (which is possible for REST app, but not with default Django app), you can manually protect it with your decorator.
This is mainly not a DRF issue but a Django issue.

Django rest framework working with django oauth toolkit

I'm creating an API using Django rest framework and I'm adding oauth2 authentication.
I was able to set it up correctly and I can get the token to access my API end points. So far everything good.
My question now is how to be a bit more selective in what is protected and what is public. In my API there is a subset of end points that can be accessed by everybody so that they are anonymous users and they can't get the access token in the same way because username and password doesn't exists.
Here is the related content in my settings.py:
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {
'read': 'Read scope',
'write': 'Write scope',
'groups': 'Access to your groups'
}
}
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAdminUser',
),
'PAGE_SIZE': 10
}
INSTALLED_APPS = (
...
'oauth2_provider',
'rest_framework',
...
)
views.py:
# Everything fine for this end point
class PrivateViewSet(viewsets.ModelViewSet):
serializer_class = custom_serializers.MySerializer
http_method_names = ['get', 'post', 'head', 'options']
permission_classes = (permissions.IsAuthenticated, custom_permissions.IsAdminOrOwner, TokenHasReadWriteScope)
# Getting the error
class PublicViewSet(viewsets.ModelViewSet):
serializer_class = custom_serializers.MyPublicSerializer
permission_classes = (permissions.AllowAny,)
So when I try to access to "PublicViewSet" end point I get the following error:
{"detail": "Authentication credentials were not provided."}
Is there a way to decide to which end points to apply the oauth2 authorization and keep others open publicly?
You are not been able to access the PublicViewSet endpoint because
it is looking for the token in the setting you provided the
DEFAULT_AUTHENTICATION_CLASSES. It follows the classes.
To avoid this in the view you need to pass an empty authentication_classes.
class PublicViewSet(viewsets.ModelViewSet):
serializer_class = custom_serializers.MyPublicSerializer
authentication_classes = ()
permission_classes = (permissions.AllowAny,)