Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caching image with token (Amazon S3 bucket image) #602

Open
orcunorcun opened this issue Nov 16, 2019 · 19 comments
Open

Caching image with token (Amazon S3 bucket image) #602

orcunorcun opened this issue Nov 16, 2019 · 19 comments
Labels

Comments

@orcunorcun
Copy link

I am trying to cache an image from Amazon S3 bucket, but this url has lots of variables. So I want to cache the image for only first part of url. Is it possible?

for an example:
https://mybucket-dev.s3.ap-northeast-1.amazonaws.com/public/user/805327c1-8a64-4f94-a044-a2f158b2d677/feed/feed_20191117011738039.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA2DSNUBOKIKRUQDRV%2F20191116%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20191116T174021Z&X-Amz-Expires=900&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEFIa

the first part of url always same:
https://mybucket-dev.s3.ap-northeast-1.amazonaws.com/public/user/805327c1-8a64-4f94-a044-a2f158b2d677/feed/feed_20191117011738039.jpg

Can I use this part as a cache key?
Thank you.

@orcunorcun orcunorcun added the bug label Nov 16, 2019
@junkdeck
Copy link

i think you can use headers in source. haven't quite made it work yet, but you'd need to split your presigned URL and decode the reserved characters, e.g. %2F with decodeURIComponent.

@orcunorcun
Copy link
Author

I did but it doesn't work. Is there any example for it?

@junkdeck
Copy link

not that i could find, unfortunately. what does your errors say?

@orcunorcun
Copy link
Author

@junkdeck There is no error. Just it doesn't cache it. :/

@junkdeck
Copy link

how did you fetch the image using the header key? been trying at it without any luck for hours

@roots-ai
Copy link

Any updates here?

@boraikizoglu
Copy link

I have the same problem. Signed urls aren't cached. Is there any update on this?

@andreialecu
Copy link

Take a look here:

aws-amplify/amplify-js#5296 (comment)

You can supply the Authorization header instead, and the url will remain static.

@boraikizoglu
Copy link

Take a look here:

aws-amplify/amplify-js#5296 (comment)

You can supply the Authorization header instead, and the url will remain static.

Hi Andrei,

I checked your getS3SignedHeaders function but couldn't get how you create the signed headers. I realize you use aws-amplify and some credentials in the client side.

Our client side application just has a url like this:
https://your-app.s3.eu-central-1.amazonaws.com/images/7_profileImage_1585830930973.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5K5BXRHZTYRI6JJE%2F20200406%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20200406T132314Z&X-Amz-Expires=86400&X-Amz-Signature=b1c080c8b720532db082ded13699c26bfc4b2540ddebaaa668488d9cdb0d1bec&X-Amz-SignedHeaders=host&response-content-type=application%2Foctet-stream

Is it possible to generate signed headers using this url?

@andreialecu
Copy link

andreialecu commented Apr 6, 2020

@boraikizoglu How are you generating the URL? As you can see it has an expiration date tied to it. Storing signed URLs in a database is not recommended.

The link I added shows a solution that takes advantage of Amazon Cognito based temporary credentials -> the signature is safe to be generated in the React Native app because the accesskey/secretkey/sessiontoken are tied to the currently logged in Cognito user. So, they're temporary and tied to the current user. AWS Amplify makes this easy.

If you cannot generate signatures client side one possible workaround is to set up an API function on your server which returns the set of signed headers based on server side AWS credentials, and then use those in your app to do the request.

@boraikizoglu
Copy link

boraikizoglu commented Apr 6, 2020

@andreialecu, we don't store any signed URL in the database. They are generated in the server side each time user requests an image.


I finally managed to solve this issue.

Instead of sending pre-signed urls, like @andreialecu mentioned, send Authorization headers which are created by your server.
I wrote a function which uses aws4 package to create signed headers. Hope this helps somebody.

import aws4 from 'aws4';

export function getURIWithSignedHeaders(imagePath) {
    if(!imagePath){
        return null;
    }
    const expires = 86400; // 24 hours
    const host = `${process.env.YOUR_S3_BUCKET_NAME}.s3.${process.env.YOUR_S3_REGION}.amazonaws.com`;
    // imagePath should be something like images/3_profileImage.jpg
    const path = `/${imagePath}?X-Amz-Expires=${expires}`;
    const opts = {
        host,
        path,
        headers: {
            'Content-Type': 'image/jpeg'
        }
    };
    const { headers } = aws4.sign(opts, {accessKeyId: process.env.YORU_ACCESS_KEY_ID, secretAccessKey: process.env.YOUR_SECRET_ACCESS_KEY});
    return {
        uri: `https://${host}${path}`,
        headers: {
            Authorization: headers['Authorization'],
            'X-Amz-Content-Sha256': headers['X-Amz-Content-Sha256'],
            'X-Amz-Date': headers['X-Amz-Date'],
            'Content-Type': 'image/jpeg',
        }
    }
}

@randalb1991
Copy link

Hi @boraikizoglu, is it working properly?

@boraikizoglu
Copy link

@randalb1991 it worked fine for me.

@lucianojsjr
Copy link

Hi, I tried the suggested solutions but nothing worked to me. Does anyone have another solution that worked?

@solarisn
Copy link

Using the Authorization headers works with S3 signed URLs but I am using CloudFront which does not support inclusion of the signature info inside of Authorization headers. If you're using S3 directly (not through CloudFront) see here:
https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html

@scornz
Copy link

scornz commented Mar 24, 2022

I am still dealing with this issue. I am using boto3 (in Python) on my backend, and I can't seem to find anything that generates the headers mentioned by boraikizoglu. If anyone could point me in the right direction, it would be much appreciated.

@roots-ai
Copy link

roots-ai commented Jun 20, 2022

aws4 and react-native-aws4 are old packages.

How to do this with @aws-sdk/signature-v4 ?

@solarisn
Copy link

@roots-ai You can use whatever SDK you want to generate the URL signature on your server. You can make caching work once delivering the signed URL to your client by pulling the signature out of the query/URL parameters and including it in the Authorization header like this:
https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html

If you're using CloudFront signed URLs (instead of S3 directly) you can include the signature in a Cookie header instead:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html

@dragonmaster784
Copy link

This repo caters for the above issue but still needs work:
https://github.com/georstat/react-native-image-cache

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants