23

When following redirects for a 303 response, in a Chrome, IE, and Firefox, the Authorization header is included.
That's an issue when a request to an internal service respond with a signed S3 URL in the Location header.
S3 will respond with a 400 response, and can't figure out which authentication method to use.

Request to internal service

GET INTERNAL_SERVICE HTTP/1.1
Pragma: no-cache
Origin: https://example.com
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,da;q=0.7,de;q=0.6
Authorization: Bearer g6YQjOy3BDu32es8xKdMRNpcQ2Fkrh5NG7y5fDs5
Accept: application/json, text/plain, */*
Cache-Control: no-cache
Authority: example.com
Host: example.com
Connection: close

Response

HTTP/1.1 303 See Other
Date: Tue, 13 Mar 2018 08:55:12 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Connection: close
Server: nginx
location: S3_SIGNED_URL
Cache-Control: no-cache, private
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Accept, Authorization, X-                        
Requested-With
Access-Control-Max-Age: 28800

Request to S3

GET S3_SIGNED_URL HTTP/1.1
Pragma: no-cache
Origin: https://example.com
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,da;q=0.7,de;q=0.6
Authorization: Bearer g6YQjOy3BDu32es8xKdMRNpcQ2Fkrh5NG7y5fDs5
Accept: application/json, text/plain, */*
Cache-Control: no-cache
Authority: example.com
Host: BUCKET_NAME.s3.eu-central-1.amazonaws.com
Connection: close

Response

HTTP/1.1 400 Bad Request
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
x-amz-request-id: REQUEST_ID
x-amz-id-2: AMZ_ID
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Tue, 13 Mar 2018 09:06:41 GMT
Connection: close
Server: AmazonS3

<?xml version="1.0" encoding="UTF-8"?>
<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>Bearer g6YQjOy3BDu32es8xKdMRNpcQ2Fkrh5NG7y5fDs5</ArgumentValue>
   <RequestId>REQUEST_ID</RequestId>
   <HostId>HOST_ID</HostId>
</Error>

Is there a way to instruct the browser to ignore the Authorization header, or force S3 to ignore the header?

Morten Hauberg
  • 531
  • 1
  • 5
  • 12
  • 1
    What if you use a different redirect code, like 302 or 307? It seems quite wrong in any event for the browser to send an `Authorization` header cross-origin... is CORS configured on the bucket? – Michael - sqlbot Mar 14 '18 at 12:08
  • We've tried both 303 and 307 and it's the same issue. And CORS has been configured – Morten Hauberg Mar 14 '18 at 14:45
  • 1
    If CORS is enabled, here's my next thought... even though I didn't initially *think* it should matter, if you have `Authorization` (or `*`) in the CORS configuration for the bucket, maybe there's an interaction there. https://www.w3.org/TR/cors/#cors-api-specification-redirect – Michael - sqlbot Mar 14 '18 at 15:29
  • 1
    We have tried removing the header from AllowedHeader, but the browser still sends the header, and then we get CORS conflicts instead. The browser doesn't seem to send a preflight request to S3 at all. – Multiply Mar 15 '18 at 07:39
  • 1
    @MortenHauberg were you ever able to solve this? We're facing the exact same issue. – Vinnie Jun 14 '18 at 18:22
  • @Vinnie, no unfortunately not – Morten Hauberg Jun 18 '18 at 07:16
  • 2
    It's 2021 and I still cannot find an answer to this question. This is an incredibly insecure design to redirect Authorization headers to a cross-origin resource, and with S3 being in use more and more, I continually hit this issue. – ezekg Jul 26 '21 at 23:06
  • Facing this too. This must be a big security hole, don't understand why nothing is happening ... – squanto773 Feb 04 '22 at 19:46
  • 2
    It's 2022 and I still cannot find an answer as well ... – janfabian Nov 08 '22 at 14:27

2 Answers2

2

Kind of a kludge, but there is a workaround to this situation by using CloudFront to front S3. More information posted here: ReactJS- remove HTTP header before redirect

Vinnie
  • 12,400
  • 15
  • 59
  • 80
0

I solved this problem by configuring my back-end to support an alternative auth header (X-App-Authorization) and pull its token from that.

This is obviously not ideal because (1) the app has to now make use of a non-standard header at least for the affected endpoint and (2) the app's authorization token is still being "leaked" to AWS.

If these issues are a non-starter for your application, you can solve the problem by using something like NGINX's X-Accel-Redirect and having your reverse proxy stream the S3 download transparently. This is of course less efficient than redirecting to S3 directly.

garrettmills
  • 660
  • 6
  • 13