aws-samples / cloudfront-authorization-at-edge

Protect downloads of your content hosted on CloudFront with Cognito authentication using cookies and Lambda@Edge
https://aws.amazon.com/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/
MIT No Attribution
478 stars 157 forks source link

Getting blocked by CORS policy but unable to figure out the source #233

Closed kjpluck closed 1 year ago

kjpluck commented 1 year ago

I have reasonably successfully deployed this but having trouble with CORS errors.

We host our own app which uses Cognito for authentication. The app requests data from S3 via CloudFront which we didn't have protected during development so recently have been jumping through the hoops to protect it using this authorization technique.

The user visits our app and gets redirected to Cognito to login and are redirected back on success. The app loads and starts making requests to CF like so:

https://zzzzzz.cloudfront.net/data/blahblah/foobar.json

CF redirects (307) the request to Cognito: https://xxxxxx.auth.ap-southeast-2.amazoncognito.com/oauth2/authorize?redirect_uri=https://zzzzzz.cloudfront.net/parseauth&response_type=code&client_id=yyyyy&state=wwwwwww&scope=phone%20email%20openid&code_challenge_method=S256&code_challenge=qqqqqqqqqqq with Access-Control-Allow-Origin: *

All good...

Cognito then responds with a 302 redirect to https://xxxxxx.auth.ap-southeast-2.amazoncognito.com/login?redirect_uri=https://zzzzzz.cloudfront.net/parseauth&response_type=code&client_id=yyyyy&state=wwwwwww&scope=phone%20email%20openid&code_challenge_method=S256&code_challenge=qqqqqqqqqqq

ie from /oauth2/authorize to /login which according to Cognito's docs is correct. I'm assuming that the request to /login will redirect to https://zzzzzz.cloudfront.net/parseauth with appropriate values.

However this time it fails and the browser logs:

Access to XMLHttpRequest at 'https://xxxxxx.auth.ap-southeast-2.amazoncognito.com/oauth2/authorize?redirect_uri=https%3A%2F%2Fzzzzzz.cloudfront.net%2Fparseauth&response_type=code&client_id=yyyyy&state=wwwwwww&scope=phone%20email%20openid&code_challenge_method=S256&code_challenge=qqqqqqqqqqq' (redirected from 'https://zzzzzz.cloudfront.net/data/blahblah/foobar.json') from origin 'http://localhost:31415' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Sure enough the redirect response from /oauth2/authorize doesn't include an Access-Control-Allow-Origin header but I'm not sure if that's where the issue is.

As you can see I'm running this locally which may muddy the waters. As a straw grasping action I added Access-Control-Allow-Origin: * to the response on the local server with no difference.

I'd appreciate some guidance on where to go from here as I am quite stuck.

kjpluck commented 1 year ago

Have also tried this on a dev server and getting same so localhost not a factor

ottokruse commented 1 year ago

Can you share an architecture diagram? And it would help to see the HAR file. If it is too sensitive to share here you can mail it to me at ottokrus at amazon nl

The user visits our app and gets redirected to Cognito to login and are redirected back on success. The app loads and starts making requests to CF like so:

https://zzzzzz.cloudfront.net/data/blahblah/foobar.json

CF redirects (307) the request to Cognito: ...

That's not right. After you signed in successfully you should have cookies with valid JWTs and then should no longer get 307s.

kjpluck commented 1 year ago

As the site is on a different domain to CF and Cognito this isn't possible which may well explain the CORS errors.

If there isn't a way around this then I will be exploring signed urls.

ottokruse commented 1 year ago

As the site is on a different domain to CF and Cognito this isn't possible which may well explain the CORS errors.

If there isn't a way around this then I will be exploring signed urls.

Aha two different domain names. Yes signed URLs is the way. Use an Cognito Identitity Pool to trade your JWTs for temporary AWS credentials with which you can create a signed URL. Amplify Storage makes this easy, does it automatically if you configure Amplify with an Identity Pool.

kjpluck commented 1 year ago

All sorted. Just spent a brain melting day setting up a CF distribution that requires signed urls. Thanks for your help!