Django Rest Framework: redirecting to Amazon S3 does not work when using Token authentication

I use token authentication in DRF and for a specific API call, I want to redirect to S3 (using a URL, for example https://my_bucket.s3.amazonaws.com/my/file/path/my_file.jpg?Signature=MY_AWS_SIGNATURE&AWSAccessKeyId=MY_AWS_ACCESS_KEY_ID ). However, I get the following error from AWS:

 <Error> <Code>InvalidArgument</Code> <Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message> <ArgumentName>Authorization</ArgumentName> <ArgumentValue>Token a3f61c10592272399099882eb178bd4b755af5bf</ArgumentValue> <RequestId>E4038228DD1E6330</RequestId> <HostId>9c2xX59cugrR0CHjxQJR8IBE4MXBbNMX+wX2JdPJEuerkAftc32rufotM7COKLIavakByuRUXOo=</HostId> </Error> 

This is understandable why this happens - the Authorization header with the DRF marker is propagated by redirection, and he does not like S3.

After researching and testing a million ways to get rid of this header, I refused and decided to try and redefine the title with the value S3: AWS MY_AWS_SIGNATURE:MY_AWS_ACCESS_KEY_ID , after which I get another error:

 <Error> <Code>InvalidArgument</Code> <Message>Unsupported Authorization Type</Message> <ArgumentName>Authorization</ArgumentName> <ArgumentValue>Token a3f61c10592272399099882eb178bd4b755af5bf</ArgumentValue> <RequestId>94D5ADA28C6A5BFB</RequestId> <HostId>1YznL6UC3V0+nCvilsriHDAnP2/h3MoDlIJ/L+0V6w7nbHbf2bSxoQflujGmQ5PrUZpNiH7GywI=</HostId> </Error> 

As you can see, the end result is the same - even if I override the Authorization header in my answer, it still retains the original authentication value of the DRF identifier.

 # relevant portion of my response construction headers = {'Location': 'https://my_bucket.s3.amazonaws.com/my/file/path/my_file.jpg', 'Authorization': 'AWS %s:%s' % (params['AWSAccessKeyId'], params['Signature'])} return Response(status=status.HTTP_302_FOUND, headers=headers) 

So my question is: how can the Authorization header in a DRF response be deleted or redefined?

+5
source share
1 answer

Redirecting the Authorization header is the responsibility of the client (e.g. browsers, cURL, HTTP libraries / toolkits).

For example, Paw, my toolkit for requesting my APIs offers this configuration: Paw Application Redirection Configuration

Basically, major browsers tend to redirect the Authorization header, which causes a conflict on S3.

I also suspect that you misunderstood how redirects are performed:

  • When the DRF issues a redirect, it returns an HTTP 301 or 302 response to the client containing the new Location header (the request is not forwarded directly through DRF)
  • The client then requests this new URI

And finally, you do not overlap the Authorization header when you use your 302 , as this is the answer ... to the client (which may contain the Authorization header, but is useless).


Right now you have a bunch of solutions (so not out of the box ...):

  • Passing your token through another header to avoid conflict (e.g. X-Token)
  • Passing a token through the HTTP GET parameter ( ?token=blah )
  • Using the DRF View to Proxy an S3 Object (No Forwarding)

The first two solutions may somehow violate the consistency of your API, but in some way are fair enough. They will need a custom TokenAuthentication or get_authorization_header (from rest_framework.authorization ).

The latter is transparent, but may be completely unsuitable depending on the object that you choose on S3 and / or hosting restrictions ...

That’s all I can tell you. As you know, I also adhered to the same situation . I would be so happy if anyone could offer a better solution.

+3
source

All Articles