mkuligowski
mkuligowski

Reputation: 1594

Restricting access to AWS S3 objects

I am using AWS S3 to store photos in conversations between users in my chat application (backend is written in Java / Spring Boot). At the moment, access to the bucket is public, which means that every user who would guesses the url will be able to see the picture.

What I would like to achieve is to restrict access to the resource only to interlocutors who belong to the given conversation so that they can see the photos sent between them.

I don't want to run all the traffic through my backend, I just want to delegate authorization to the S3. Is it possible to set some kind of "auth token" to restrict access to the given object on s3? I would generate this token on my backend and possibly refresh it from time to time. Are there any other recommended options for this task?

Upvotes: 1

Views: 181

Answers (2)

stdunbar
stdunbar

Reputation: 17495

As indicated, you can presign the URL. In Java (API V1) the basics are something like:

String bucketName = "the-bucket-name";
String objectKey = "/your/object/keyname.jpg";

AmazonS3 s3Client = AmazonS3ClientBuilder.standard().build();

// Set the presigned URL to expire after one hour.
Date expiration = new Date();
long expTimeMillis = expiration.getTime() + 1000 * 60 * 60;
expiration.setTime(expTimeMillis);

// Generate the presigned URL.
GeneratePresignedUrlRequest generatePresignedUrlRequest = 
                new GeneratePresignedUrlRequest(bucketName, objectKey)
                .withMethod(HttpMethod.GET)
                .withExpiration(expiration);

URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);

System.out.println("Pre-Signed URL: " + url.toString());

This allows anyone to access the image for one hour if they have the URL. Presumably you could generate the URL to include on a web page and the likelihood of sharing the link is low.

If you must have a guarantee that only the correct person can access the image then you'll need some sort of server side component. You can route it through your server or possibly a API Gateway/Lambda component.

Upvotes: 3

August Williams
August Williams

Reputation: 929

You can create presigned URLs for S3 objects. This generates a temporary link that grants access to an S3 object, even if the bucket is not public.

As an example/test, you could run the aws s3 presign command in the AWS CLI:

aws s3 presign s3://BucketName/SomePhoto.png --expires-in 86400

This command will return an address that can be used to access SomePhoto.png. The URL will be valid for 86400 seconds, which is one day. --expires-in is optional.

More details on the command lind reference can be found here.

Upvotes: 2

Related Questions