request signature we calculated does not match the signature you provided - django-views

i want to get presigned url from aws.But i am getting error:"The request signature we calculated does not match the signature you provided. Check your key and signing method."
Here is the django code i have:
Sttings.py:
AWS_ACCESS_KEY_ID = '*********'
AWS_SECRET_ACCESS_KEY = '**********'
AWS_STORAGE_BUCKET_NAME = '******'
AWS_REGION_NAME = '*******'
in views.py:
def post(self, request, key):
bucket_name = settings.AWS_STORAGE_BUCKET_NAME
s3_client = boto3.client('s3',
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
config=Config(signature_version='s3v4'),
region_name=settings.AWS_REGION_NAME
)
try:
response = s3_client.generate_presigned_url('put_object',
Params={'Bucket': bucket_name,
'Key': key},
ExpiresIn=3600)
except ClientError as e:
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR, data={"error_message": str(e)})
else:
return Response({
"url": response
})

We need to create a user and grant getobject, putobject permissions in AWS.The Documentation https://docs.aws.amazon.com/AmazonS3/latest/dev/example-walkthroughs-managing-access-example3.html

Related

How to write url for testing when using viewsets in Django Restframework

I am really noebie for testing. Actuall, I dont know how to write test url for getting response from viewsets.
This is my views,
class AppraisalAPI(viewsets.ReadOnlyModelViewSet):
queryset = Appraisal.objects.all().order_by('-id')
serializer_class = AppraisalSerializer
def get_permissions(self):
if self.action in ['retrieve']:
self.permission_classes = [IsHRUser | IsManagementUser]
elif self.action in ['list']:
self.permission_classes = [IsUser]
return super(self.__class__, self).get_permissions()
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
data = instance.summary()
return Response(data)
This is my urls.py,
router = routers.DefaultRouter()
router.register('appraisal', AppraisalAPI)
urlpatterns = [
path('', include(router.urls)),
]
This is my test function,
def test_appraisal_api_readonly(self):
url = reverse('appraisal-list')
self.client = Client(HTTP_AUTHORIZATION='Token ' + token.key)
resp1 = self.client.get(url, format='json')
self.assertEqual(resp1.status_code, 200)
This test url only went inside list action. when i give detail insteadof list it went only retrieve action.
Here, I want to get Retrive function response, How can i get after getting permission i want to receive retrive function response.
Anyhelp Appreciable,..
Since you use the DefaultRouter, you can trigger the retrieve action with appraisal-detail, and use a primary key of the object, so:
def test_appraisal_api_readonly(self):
url = reverse('appraisal-detail', kwargs={'pk': some_pk})
self.client = Client(HTTP_AUTHORIZATION='Token ' + token.key)
resp1 = self.client.get(url, format='json')
self.assertEqual(resp1.status_code, 200)
with some_pk the primary key (.pk) of some item you construct in the test.

Auth0 save username instead of 'sub'

I finished implementing auth0 to my django and react app. But ever since I signup with a new user, the 'sub' is saved as the username instead of the real 'name'. Is there a way to fix this?
settings.py
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'django.contrib.auth.backends.RemoteUserBackend',
]
JWT_AUTH = {
'JWT_PAYLOAD_GET_USERNAME_HANDLER':
'posts.utils.jwt_get_username_from_payload_handler',
'JWT_DECODE_HANDLER':
'posts.utils.jwt_decode_token',
'JWT_ALGORITHM': 'RS256',
'JWT_AUDIENCE': '<API_IDENTIFIER>',
'JWT_ISSUER': 'https://<APP_DOMAIN>/',
'JWT_AUTH_HEADER_PREFIX': 'Bearer',
}
posts.utils.py
from django.contrib.auth import authenticate
import json
import jwt
import requests
def jwt_get_username_from_payload_handler(payload):
username = payload.get('sub').replace('|', '.')
authenticate(remote_user=username)
return username
def jwt_decode_token(token):
header = jwt.get_unverified_header(token)
jwks = requests.get(
'https://{}/.well-known/jwks.json'.format('<APP_DOMAIN>')).json()
public_key = None
for jwk in jwks['keys']:
if jwk['kid'] == header['kid']:
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(jwk))
if public_key is None:
raise Exception('Public key not found.')
issuer = 'https://{}/'.format('<APP_DOMAIN>')
return jwt.decode(token, public_key, audience='<API_IDENTIFIER>', issuer=issuer, algorithms=['RS256'])
Here are some of my codes I used at the auth0 tutorial. I tried changing the username payload handler but it didn't work yet.

DRF : Custom permission denied message

How to change the default DRF-Permission Denied message from {"detail":"You do not have permission to perform this action."} to something like this,
{"status": False, "message": "You do not have permission to perform this action."}
I found this SO Answer, but it doesn't help to change the Key for the message
To include status to the error response you can write custom error handler:
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
if response.status_code == 403:
response.data = {'status': False, 'message': response.data['detail']}
return response
In settings:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER':
'my_project.my_app.utils.custom_exception_handler'
}
You can create a custom permission by extending the BasePermission class and use a custom exception with custom status_code and default_detail to use in that custom permission.
class CustomForbidden(APIException):
status_code = status.HTTP_403_FORBIDDEN
default_detail = "custom error message"
class CustomPermission(permissions.BasePermission):
def has_permission(self, request, view):
if not_allowed:
raise CustomForbidden

Why doesn't the rest_framework.authentication.BasicAuthentication is not working in my codes?

My API:
from rest_framework.authentication import BasicAuthentication
"""A simple API for file upload."""
class FileUploadView(APIView):
parser_classes = (MultiPartParser,)
authentication_classes = (BasicAuthentication,)
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(FileUploadView, self).dispatch(request, *args, **kwargs)
def put(self, request):
print "request:", str(request.META)
print "request:", str(request.user.username)
try:
data = {'files': 'testing'}
response = Response(data)
except Exception as e:
print "Exception when put file:", e
data = { 'error' : str(e) }
response = Response(data)
return response
The above is my API views.py. I used postman to do PUT. I did not add anything in the header authorization (No HTTP_AUTHORIZATION in the request header), I can get {'files': 'testing'} as my response.
Why? Anything missing? Thanks
You added authentication class but did not restrict access to your view. By default the DRF has unrestricted access . See the documentation section:
If not specified, this setting defaults to allowing unrestricted access:
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
Setting the permission policy

How to create new user and new django allauth social account when given access token over api?

I have a mobile app that allows users to sign up via Facebook. Once I receive the access token from FB, I send it to the Django backend.
But then what?
Is there a method inside of django-allauth that I can feed the access token to to have it create the new user/social account?
Or do I need to do it all manually?
I always seem to figure out the answers right after I post the question. In any case, the following is a custom method on UserResource (tastypie api using ApiKeyAuthentication). Most of it was taken from the login_by_token method in allauth.socialaccount.providers.facebook.views.
I won't select my answer as correct for a while in case anyone posts a better answer.
def facebook_login(self, request, **kwargs):
self.method_check(request, allowed=['post'])
data = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))
access_token = data.get('access_token', '')
from allauth.socialaccount import providers
from allauth.socialaccount.models import SocialLogin, SocialToken, SocialApp
from allauth.socialaccount.providers.facebook.views import fb_complete_login
from allauth.socialaccount.helpers import complete_social_login
try:
app = SocialApp.objects.get(provider="facebook")
token = SocialToken(app=app,
token=access_token)
login = fb_complete_login(app, token)
login.token = token
login.state = SocialLogin.state_from_request(request)
ret = complete_social_login(request, login)
#if we get here we've succeeded
return self.create_response(request, {
'success': True,
'username': request.user.username,
'user_id': request.user.pk,
'api_key': request.user.api_key.key,
} )
except:
# FIXME: Catch only what is needed
return self.create_response(request, {
'success': False,
'reason': "Bad Access Token",
}, HttpForbidden )
Modern readers (2017) may want to look at django-rest-auth, which builds on allauth but is built with single page apps in mind:
http://django-rest-auth.readthedocs.io/en/latest/introduction.html
Working Source Code:
In class UserResource(ModelResource):
def override_urls(self):
return [
url(r"^(?P<resource_name>%s)/facebook_login%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('facebook_login'), name="api_facebook_login"),
]
def facebook_login(self, request, **kwargs):
self.method_check(request, allowed=['post'])
data = self.deserialize(
request,
request.raw_post_data,
format=request.META.get('CONTENT_TYPE', 'applicaton/json'))
access_token = data.get('access_token', '')
print(access_token)
from allauth.socialaccount import providers
from allauth.socialaccount.models import SocialLogin, SocialToken, SocialApp
from allauth.socialaccount.providers.facebook.views import fb_complete_login
from allauth.socialaccount.helpers import complete_social_login
try:
app = SocialApp.objects.get(provider="facebook")
print(app)
token = SocialToken(app=app,
token=access_token)
login = fb_complete_login(app, token)
login.token = token
login.state = SocialLogin.state_from_request(request)
ret = complete_social_login(request, login)
#if we get here we've succeeded
return self.create_response(request, {
'success': True,
'username': request.user.username,
'user_id': request.user.pk,
'api_key': request.user.api_key.key,
} )
except:
# FIXME: Catch only what is needed
return self.create_response(request, {
'success': False,
'reason': "Bad Access Token",
}, HttpForbidden )
Then:
curl --dump-header - -H "Content-Type: application/json" -X POST
--data '{"access_token":"xxxxxxxx"}' http://xx.xxxxxx.com:8000/api/v1/user/facebook_login/
Test OK, Create User OK.
Thank you.