
Amazon S3 Presigned URLs
Amazon S3 presigned URLs allow you to grant temporary, secure access to specific objects in your S3 bucket without exposing your credentials. Let's learn how to use this from a .NET application.
Table of Contents
Amazon S3 presigned URLs allow you to grant temporary, secure access to specific objects in your S3 bucket without exposing your credentials.
A presigned URL is generated using AWS credentials and includes an expiration time, after which it becomes invalid. These URLs are useful for scenarios like allowing users to upload or download files without needing direct AWS permissions.
Anyone with valid security credentials can create a presigned URL.
In this post, let's
- Explore Amazon S3 Presigned URLs
- Learn how to enable S3 Presigned URLs
- Discover use cases to improve application performance
Thanks to AWS for sponsoring this article in my .NET on AWS Series.
Generate Presigned URL From AWS Console
To generate a presigned URL for an existing object in Amazon S3, navigate to the file in S3.
Under Object Actions → Share with a presigned URL you can generate a URL to share.

It prompts a dialog to specify the time interval until the presigned URL expires. You can select the time in either minutes or hours.

Once created, the presigned URL is copied to your clipboard. You can use/share the link to anyone to access the shared file.
Generate GET Presigned URL From Code
You can also generate a presigned URL from code. Let's use the AmazonS3Client
from the AWSSDK.S3 NuGet package for this.

Below is a minimal API endpoint that takes in a S3 object key name as string and generates a presigned URL to view the file.
the GetPresignedURLAsync
method takes in an S3 object key, the bucket name, the HTTP action associated (in this case GET
), and also an expiry duration.
app.MapGet("/get-presigned-url", async (
[FromQuery] string key,
IAmazonS3 s3Client,
CancellationToken cancellationToken) =>
{
var presignedUrl = await s3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest()
{
BucketName = "<your-bucket-name>",
Key = key,
Verb = HttpVerb.GET,
Expires = DateTime.UtcNow.AddMinutes(1)
});
return new {url = presignedUrl};
})
.WithName("GetPreSignedUrl")
.DisableAntiforgery()
.WithOpenApi();
It generates a presigned URL to view the specified file from the bucket, very similar to the one we created from the AWS Console.

To generate the pre-signed URL, the application must have access to the specified bucket and file.
Generate PUT Presigned URL From Code
We can also upload files into an S3 bucket using PreSigned URLs, like viewing a file.
However, uploading a file to S3 is split into two steps.
- Generate a presigned URL to upload
- Upload the file using presigned URL
Generating a presigned URL is very similar to the code previously, except that we use the HTTP PUT
verb.
app.MapGet("/get-presigned-url-for-upload", async (
[FromQuery] string key,
IAmazonS3 s3Client,
CancellationToken cancellationToken) =>
{
var presignedUrl = await s3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest()
{
BucketName = "<your-bucket-name>",
Key = key,
Verb = HttpVerb.PUT,
Expires = DateTime.UtcNow.AddMinutes(1)
});
return new {url = presignedUrl};
})
.WithName("GetPreSignedUrlForUpload")
.DisableAntiforgery()
.WithOpenApi();
Like before, we need to specify a key to upload the file, which becomes the object key in Amazon S3 once uploaded.
The above code will return a presigned URL that you can use to upload a file.
Amazon S3 Bucket and CORS
If you are using the PUT
presigned URL to upload a file from a web page directly, you must ensure that CORS is enabled on the S3 bucket.
This is because the webpage is running under a different host and is trying to access the URL on a different host (*.amazonaws.com) to upload a file.

You can update the CORS policy by navigating to the Amazon S3 bucket in the AWS Console and clicking on Permissions → Cross-origin resource sharing (CORS).

For now I have enabled all origins by using the *
wildcard operator.
Uploading Files Directly To S3 from Client/Browser
With the CORS policy configured, you can upload files directly to Amazon S3 using the presigned URLs from your web applications.
In the sample repository code shared below, I have two HTML files (generated by ChatGPT) to upload files to S3 using presigned URLs
Index.html
→ Upload to S3 given a Presigned URLIndex - Generate PreSigned.html
→ Hit an API endpoint to generate a presigned URL for a given key and then upload the actual file directly to S3.
Depending on how you want to let users upload files to S3 you can use either of those patterns.
The complete source code and the HTML files are available here.
Rahul Nath Newsletter
Join the newsletter to receive the latest updates in your inbox.