Next Js static site refresh not working on AWS s3 bucket [duplicate] - reactjs

For a while, I was simply storing the contents of my website in a s3 bucket and could access all pages via the full url just fine. I wanted to make my website more secure by adding an SSL so I created a CloudFront Distribution to point to my s3 bucket.
The site will load just fine, but if the user tries to refresh the page or if they try to access a page using the full url (i.e., www.example.com/home), they will receive an AccessDenied page.

S3 doesn't understand route open when you reload and open in new tab. You need to tell S3 is for this route used index.html.Whenever new route open its gives 403 [access denied ] error. for this you need to do setting CloudFront to set 403 error page redirect to index.html
Go to aws cloud front and open your configuration then go to Error page tab you will see same as above screenshot
Here is details blog : https://www.internetkatta.com/host-angular-2-or-4-or-5-version-in-aws-s3-using-cloudfront

Related

retrive file from one drive from a next.js application

I am using react-onedrive-filepicker to retrieve file content from a selected file located on OneDrive.
My code is like:
<ReactOneDriveFilePicker
clientID={process.env.NEXT_PUBLIC_MICROSOFT_CLIENT_ID}
action="query"
multiSelect={false}
advanced={{
redirectUri: "https://graph.microsoft.com/v1.0/me/"
}}
onSuccess={(result) => {
alert(JSON.stringify(result));
}}
onCancel={(result) => {
alert(JSON.stringify(result));
}}
>
<Button className="btn btn-md btn-primary">MSOneDrive</Button>
</ReactOneDriveFilePicker>
I am actually getting this error
I am at a loss here, because I have no idea what URI is supposed to expect nor how to pass it... I have registered https://login.live.com/oauth20_desktop.srf on my Azure app, but it appears not to be the right address to show a user's OneDrive folder...
Where am I going wrong here?
I have also opened a issue on the react-onedrive-filepicker GitHub, but I am afraid the repo might be unmaintained..
EDIT
I am now passing the redirectUri value for MS Graph to the component, but it claims that redirect uri is not in the same domain as picker sdk... Now, it looks like a never-ending loop:
I cannot put the page URL where the picker is hosted, because it is a dynamic address...
but even if I put there the local URI, what's the point? I won't see the OneDrive files of my user...
What is impressive is how easy it is to make the Google picker work, and how incredibly difficult it is to make the MS work...
TL;DR
Your apps URL should be the path at which you can access your app in the browser. This URL has to be registered as redirect URI both in the Azure client configuration as well as in your ReactOneDriveFilePicker component.
To access Microsoft APIs, there are different steps to follow. First, you have to register your application with Microsoft. Then the user authorizes your application to access their data and only then you are allowed to access the files. Your struggles may actually come from the authorization step. Microsoft uses the OAuth protocol for managing access to their API resources (Docs: Auth and available auth flows), during which the user gets redirected to the Microsoft site, authorizes your app and gets redirected back to your application:
(diagram by ArchitectXChange.com)
Only then, you can access the API resources, in your case the OneDrive files.
The redirect URI now refers to the exact address your file picker is located at. Lets say you are running your application on localhost with the path /onedrive-filepicker, then your redirect URI will be http://localhost/onedrive-filepicker, since this is the place your button is located at. Now you have to put this URL into the app registration with Azure, so that Azure makes sure no one is kidding around on behalf of your application. And of course you have to confirm the redirect URI when calling the API using the redirectUri property.
You can find more on this in the OneDrive File Picker SDK docs and on their set up section.
EDIT:
If you have a dynamic url for your picker, you will need some fixed redirect route. This can be http://localhost/redirect. Before starting the Auth flow, you have to store the current state/route, e.g. inside local storage. After the redirect, you finish the authorization and redirect the user once again to the previously stored state/route.
The point on redirecting the user to your own application and not to their OneDrive is, that your application wants to access the files. If the user gets redirected to OneDrive, maybe they will see their files, but OneDrive will not know how to send the information back to your app. If you redirect to your app, it stays in control of the UI, can prompt the user to select a file and receive the selected file using the OneDrive SDK.
Maybe it will help you to follow along the Microsoft docs to use the SDK right away instead of building up on an undocumented third-party component.
Go to you client app you (I assume) opened in Azure, you need to register the base URI of your choice - you can see a full guide here:
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
Under "Add a redirect URI"

React App url parameter with S3 and CloudFront

My apologies if the information that I have provided is vague as I am not so experience with AWS and React.
I have a React Application being deployed on S3 and CloudFront as per what is suggested in the following link.
Use S3 and CloudFront to host Static Single Page Apps (SPAs) with HTTPs and www-redirects
So most of the things are working fine. I have 403 and 404 errors being redirected to index.html. However the issue comes in where I have query parameters in my url. eg. https://example.com/example?sample=123 when I enter the url in my browser the query string gets removed from the url. The end result I got is https://example.com/example I have read some articles about forwarding query parameters but it's not working for me.
AWS Documentation - Query String Parameters
Hope I will be able to get some advise here. Thanks in advance.
The example?sample=123 is redirected to example because S3 sees example?sample=123 as path (a folder named example?sample=123), it will throw 404 as there is no such folder.
As you have mentioned, you have configured 404 -> index.html, the browser then goes back to example, which is very likely the default page of your react app.
Overall it looks like your query string is being cleared, actually it is lost during the redirection.
The solution includes three parts:
React
You can follow these two great tutorials, one for NextJs and another for RCA.
The way it works is to detect #! in the path, keep and store the query string after redirection.
S3
As included in the two links above, you have to set the redirection rule of the S3 Bucket, to add a #!/ prefix before the path on 403 or 404, it helps React to determine which parts of the url include query string. You can configure it in Properties -> Static website hosting -> Redirection rules – optional. You need to also set index.html as the Index document and enable static web hosting with the correct permission configured.
CloudFront
In General, set Default Root Object to index.html, make sure you don't make it as /index.html.
In Origin, set Origin domain to the S3 Static Web Hosting URL (http://[bucket-name].s3-website.[region].amazonaws.com, do not choose the bucket itself.
In Behavior, change Viewer to Redirect HTTP to HTTPS, set Origin request policy - optional to AllViewer to let all query strings go through.
Hope it helps.

Using aws s3 and cloudfront to host React application.Can anyone suggest configuration to access dynamic urls?

For e.g. website url is https://www.myreactapp.com. It has some other pages with dynamic get parameters.
https://www.myreactapp.com/category/1
https://www.myreactapp.com/category/2
It's giving me Access Denied error
I had the same issue where i'm trying to access content at run time using ajax.
Set S3 bucket Access as "Objects can be public", No need to set "Public" Access for Static website hosting.
Use S3 Origin if you want CloudFront to deliver any objects that place in S3 bucket. But if you generate run time content, its batter to use Custom Origin.
For Custom Origin keep Note: https://docs.aws.amazon.com/general/latest/gr/s3.html#s3_website_region_endpoints
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html
The solution for the OP was to update the origin from S3 to Custom Origin domain. This allowed expected behaviour to work.
Validated that bucket was public, error 403 was caused by key not existing.

Redirecting all 404 requests to / in S3

I'm trying to setup S3 to host my static content. I've been following the documentation on AWS website. So far, I managed to see the web page loaded successfully by entering the endpoint of the bucket:
http://my-bucket.s3-website-us-east-1.amazonaws.com
But since this is a single page application and routes are handled inside the web page (it's implemented using React), I need all the URLs pointing to non-existing pages to be redirected to /. So I configured the bucket's Redirection rules like this:
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<ReplaceKeyWith>/</ReplaceKeyWith>
</Redirect>
</RoutingRule>
</RoutingRules>
But the problem is that when I open the URL:
http://my-bucket.s3-website-us-east-1.amazonaws.com/logon
I face 403 Forbidden. It seems to me that AWS is blocking the URL since it is not public but how can I make an object public when it does not exist?
It turned out what I was missing was granting the public access to listing the items in the bucket. But then I realized redirecting is not what I need. So I asked a new question here.

React app served from s3 results in 404 page from edge/IE

So I have a React/Redux application that is being served through Amazon s3 currently. We have configured s3 to render the index.html page on a 4xx error and serve our bundle.js. This allowed the react router to be bootstrapped and take over from there. Until recently this worked without issue. Now when I try to visit the page in IE or Edge I get the IE or Edge 404 page.
If I turn off the "Show friendly HTTP error messages" option on the IE browser everything works without issue. From the research I have done this is my theory on what is happening:
When the client hits the requested route the react router has not been bootstrapped yet. This results in the 404 that has to be rescued by rendering the /index.html page. When the 404 is returned IE/Edge steps in and renders their own 404 page which prevents the index.html from ever being rendered.
I am kind of at a loss as to how to solve this issue without actually using a full on backend. I can configure a redirect in the s3 settings to replace the root url with the index.html but this will break all of the sub-routes off of the main route. Is there a way to configure the application so that it works on all major browsers without actually implementing an actual backend?
EDIT: So I found this article which shows how this issue can be solved using cloudfront by rendering the index on a custom error: https://medium.com/#omgwtfmarc/deploying-create-react-app-to-s3-or-cloudfront-48dae4ce0af. Does anyone know if this is possible using cloud flare? I don't actually have the access to cloudflare personally so I am not sure of the possibilities.
If it works with "Show friendly HTTP error messages" disabled, then the issue can also be fixed by making your error pages longer. By default, IE will show those pages if it is less than 512 bytes.
OK so I discovered:
1) You cannot rescue this error in cloudflare.
2) You can put cloudfront in between S3 and cloudflare and simply implement a custom error rule.
3) Do not use the standard dropdown option when selecting the bucket for cloudfront. If you give the bucket name when configuring the error rule, cloudfront will treat it like a normal file not a static site and thus it fails to intercept the error. You have to use the fully qualified url for the bucket. I hope this saves someone some time. I lost some sleep over this issue.

Resources