S3 signed urls change everytime on load even though keys are the same;no caching - reactjs

I have encountered a problem where I need to cache image urls in browser after first load so that on every refresh same files are not fetched again and instead they are obtained from browser cache. The blocker here is that s3 signed url contains 'date' and 'signature' parameters which change on every request and hence I cannot cache it. Is there some workaround to this?
Sample urls :
https://bucket.region-name.amazonaws.com/67/13/14/design1.png_1547473003445/V0/thumbnail/design1.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIATY536SGM6CWFJ%2F20190116%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20190116T093449Z&X-Amz-Expires=900&X-Amz-Security-Token=FQoGZXIvYXdz%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDOQ2d%2FbrCADhrzi5LSKsAVrViSpTmyeTwlv8mgStqYJquyL2u4i3zqSOAFRE8fbHy7EbxH5yAmmWM94clRMm9to9LJDaxP96tAM4Za%2BFSzfr3fBTpHy%2Fq8N8fMT4%2FLv3Q5oX1k%2Fj9meYHpcH539LOLu8LmRuXGrPlbuHb7l4z7ZAWFB5MvootGvp0pfcEh6BqXr9R0iygJq3LWwoBhr5A9dRqSsLfWx9KTRTFi9KBkI%2FYtZCjEejdaVsExooufX74QU%3D&X-Amz-Signature=314c2ab2be7db4a90a3b20a79e2b53e8b915ca612ad3c6794136a4dac0fe6119&X-Amz-SignedHeaders=host
refereshed one :
https://bucket.region-name.amazonaws.com/67/13/14/design1.png_1547473003445/V0/thumbnail/design1.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA536UOMZINFU%2F20190116%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20190116T093659Z&X-Amz-Expires=900&X-Amz-Security-Token=FQoGZXIvYXdz%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDF4rMeLkeIEnbQWu6CKsAWTaVEcUia6oXeuaDObUF5Cirhzko1le9KGQfPKs5ZIwWk6o0qzHIzCe9uYdfBSmanXrfDxRHK33zbccphSwQkPI8mp%2Fl%2FGljXZALFDKZdRny4DnF2MXfy5WiFKBVSYHZ5onNZxSA4VrgNHeYbe6drI6QwMR9cHij13D8RK2XYDlmM6oVaCjGdMgL4QdpdHangaV0ZEq2GfOAYFfIps9nCM0WCH3Z3%2BpJFVfF9kouvb74QU%3D&X-Amz-Signature=5c5dead27c779299f5aef84e60e7c88a13f4cada9baa77e74e62b51caa1c0099&X-Amz-SignedHeaders=host

The presigned URLs are used to give temporal permissons to a URL in a private bucket, you could opt for a public bucket or and an Authentication endpoint to the API.

Related

How to pass active storage images to email

I am using active storage in my Rails application. The frontend is on React. I am uploading an image via react uploader and sending that image to the backend API where I am storing it to S3 bucket using active storage.
This is the API that handles the image:
if image.attached?
opts = ImageUploader.resize_to_fill(blob: image.blob, width: 100)
variation = ActiveStorage::Variation.new(combine_options: opts)
variant = ActiveStorage::Variant.new(image.blob, variation)
return rails_representation_url(variant, only_path: true)
end
This returns the path in the following format:
/rails/active_storage/representations/...../file_name.png
This works all fine when I use this path inside the application, but I want to send this image in email, there the image breaks as the src attribute can not read this path. If I append http://localhost:3000 manually in the email through dev tools, I am able to see the image then.
Weirldy, in the email, I also see the path appended with http by itself like below:
http:/rails/active_storage/representations/...../file_name.png
I did a workaround and gave only_path to false. This way I was able to get back the complete URL but in the email I got duplicate http written somehow.
Desired Result:
Either the email also appends the host_url along the protocol or removes the http also so that I am able to pass the complete valid URL.
If there is a way to alter the api and somehow get the s3 endpoint directly that would really really work but I am not sure how to do so. It would return the url like this: //{bucketName}/uploads/file/id/image.jpeg
Any help please!

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.

How to authenticate requests to images in an angularJS app using an access_token

I have an angularJS application whose authentication system is made with an access_token and communicating with a backend server written in Go
Therefore to authenticate the user, I have to add the access_token to each request ?access_token=SomeTokenHere or via a header Access-Token: SomeTokenHere
It works great.
The issue is that my backend serves protected images, and I cannot put the access token in the image src for some security reasons(If the user copy/paste the link to someone else, the access_token would be given too ...)
What I'd like to do is to inject a header containing my access token, but since the request is made from the browser it doesn't possible.
This could probably be possible with a cookie, but I'd to avoid using a cookie especially because the angularApp and the backend are not on the same sub-domain.
Another idea would be to create a directive that would get the raw data, and set the data to the image. First I don't know if this is possible and is it a good idea for hundreds of images in the webpage ?
If you have any idea, I'd be glad to hear from you !
Thanks
It is typical problem, and fortunately it was already solved - for example on Amazon S3.
Solution idea is simple: instead of directly using secret key - you can generate signature with access policy, using that key.
There is good algorithm designed especially to generate signatures for this purpose - HMAC
You can have one secret key on your server and use it to sign every image URL before it would be sent to client, also you can add some additional policies like url expiration time...

How to get a publicly accessible url for a timeline item attachment?

I wondered how could I get a publicly accessible url for a timeline item attachment (like an image) that doesn't require authentication to access it?
This is unfortunately not possible as image attachments are private to the user: they indeed require an access token to be retrieved.
The only way you could make the image publicly available is by providing some sort of proxy that would fetch the image using a stored token and returning it to the requester.

Can I change the welcome page depending on URL?

I have a single GAE app, which serves two different variations of the application depending on the invoked URL. Is it possible to have a per-url welcome page, without having the request map to a servlet which would slow the page load too much.
So, by way of example...
My app lives at myapp.appspot.com
I have two domains mapped to this app, myapp1.com and myapp2.com
If the user accesses myapp1.com, I want to serve myapp1-index.html, and
if he accesses myapp2.com, I want to serve myapp2-index.html
I never played with GAE on Java but I'm guessing you could do something based on the requested URL. I believe you can check the requested URL with the following inside your request:
httpServletRequest.getRequestURI()
Where httpServletRequest is the HttpServletRequest parameter from your doGet() method.

Resources