Pre signed aws s3 url slowness - amazon-web-services

I am trying to secure s3 resources and i have created temporary credential using sts service in the same region where bucket exist . I am using these credential to create a pre signed url which will expire after one hour. These url are images and will be shown on a mobile app . But after implementation, we are experiencing slowness in the response from s3 . Does anyone experienced same behaviour ?
This is how i am generating pre signed url
try {
AmazonS3 s3Client = new AmazonS3Client(getTemporaryAwsCredentials());
// Generate the pre signed URL.
LOGGER.info("Generating pre-signed URL for " + unsignedUrl);
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, fileName).withMethod(HttpMethod.GET);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
LOGGER.info("Pre-Signed URL: " + url.toString());
return url.toString();
} catch (Exception e) {
LOGGER.error("Error while generating pre signed url ", e);
}
private AWSCredentials getTemporaryAwsCredentials() {
AWSSecurityTokenServiceClient sts_client = new AWSSecurityTokenServiceClient(getCredentials());
sts_client.setEndpoint("sts.us-west-2.amazonaws.com");
GetSessionTokenRequest session_token_request = new GetSessionTokenRequest();
session_token_request.setDurationSeconds(43200);
GetSessionTokenResult session_token_result = sts_client.getSessionToken(session_token_request);
Credentials session_creds = session_token_result.getCredentials();
BasicSessionCredentials sessionCredentials = new BasicSessionCredentials(
session_creds.getAccessKeyId(),
session_creds.getSecretAccessKey(),
session_creds.getSessionToken());
return sessionCredentials;
}

Related

Amazon Cognito Identity with API Gateway

I'm develop app IOS and Android with Xamarin cross-platform.
I'm trying hard to use credentials receiving from Cognito Identity to authorize app invoking API Gateway.
My user flow is:
Authenticate on Cognito User Pool and get tokens
Exchange tokens for credentials on Cognito Identity Pools
Access API Gateway using credentials retrieved in the previous step.
Step 1 and 2 seems to works fine. But when app try to connect to api gateway it's getting error 403 (Forbidden).
My code:
Authenticate on Cognito User Pool and get tokens
**
public async Task<AppUser> Login(string username, string password)
{
CognitoUser cognitoUser = new CognitoUser(username, Aws.COGNITO_CLIENT_ID, CognitoUserPool, CognitoIdentityProviderClient);
AppUser appUser = new AppUser() { Email = username };
// Send a login request and wait for the response from Amazon
try
{
AuthFlowResponse response = await cognitoUser.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
{
Password = password
});
;
appUser.IsAuthenticated = true;
}
catch (NotAuthorizedException e)
{
appUser.IsAuthenticated = false;
appUser.ErrorMessage = e.Message;
}
await _tokenManagement.SaveTokens(cognitoUser.SessionTokens) ;
return appUser;
}
Exchange tokens for credentials on Cognito Identity Pools
**
public async Task<ImmutableCredentials> GetAppCredentialsAsync()
{
CognitoAWSCredentials cac;
if (_tokenManagement.CheckIsAnonymous())
{
//Anonymous credentials
cac = new CognitoAWSCredentials(Aws.COGINITO_IDENTITY_POLL_ID, RegionEndpoint.USEast1);
}
else
{
//Retrieve saved tokens from previous authentication
var tm = await _tokenManagement.RetrieveTokens();
CognitoUser user = new CognitoUser(null, Aws.COGNITO_CLIENT_ID, CognitoUserPool, CognitoIdentityProviderClient)
{
SessionTokens = new CognitoUserSession(tm.IdToken, tm.AccessToken, tm.RefreshToken, tm.IssuedTime, tm.ExpirationTime)
};
//Retrieve authenticated credentials
cac = user.GetCognitoAWSCredentials(Aws.COGINITO_IDENTITY_POLL_ID, RegionEndpoint.USEast1);
}
}
return await cac.GetCredentialsAsync();
}
Access API Gateway using credentials retrieved in the previous step:
**
public async Task<IList<MediaImage>> GetCoversAWSAsync()
{
// Getting credentials and sign request
var request = await BuildRequestAsync("/listMedia");
var client = new HttpClient();
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
IList<MediaImage> covers = JsonConvert.DeserializeObject<IList<MediaImage>>(await response.Content.ReadAsStringAsync());
return covers;
}
private async Task<HttpRequestMessage> BuildRequestAsync(string service)
{
var request = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(baseURL + service)
};
ImmutableCredentials awsCredential = await _loginService.GetAppCredentialsAsync( );
var signer = new AWS4RequestSigner(awsCredential.AccessKey, awsCredential.SecretKey);
request = await signer.Sign(request, "execute-api", awsRegion);
return request;
}
This code works fine when I hard code credentials from one IAM user. But credentials retrieved from Cognito Identities its getting Forbidden error.
I did a test using SDK for S3 and I was able to successfully list the buckets with the same credentials received from Cognito Identities, but it is not possible to make requests on the API Gateway.
Can you help me? Where did I get lost?
I figure out what was going on.
After ensuring that the permissions settings were correct on AWS.
I found in the documentation that it is necessary to include in the HTTP header the token returned by the cognito (header name x-amz-security-token). So I changed the code to the following:
private async Task<HttpRequestMessage> BuildRequestAsync(string service)
{
var request = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(baseURL + service)
};
ImmutableCredentials awsCredential = await _loginService.GetAppCredentialsAsync( );
//This where I add header to the HTTP request
request.Headers.Add("x-amz-security-token", awsCredential.Token);
var signer = new AWS4RequestSigner(awsCredential.AccessKey, awsCredential.SecretKey);
request = await signer.Sign(request, "execute-api", awsRegion);
return request;
}

TimeoutError while generating AWS s3 Presigned URL

I've created a route that generates a pre-signed URL to upload an object to AWS S3. It was working initially but lately, it's returning a Timeout Error.
Here is my controller code:
async (req, res, next)=>{
const BUCKET = req.params.bucket;
const KEY = 'myKey_'+ uuid.v4();
const EXPIRATION = 60 * 60 * 1000;
let signedUrl;
try{
// Also have a configuration file ~.aws/.credentials
const s3 = new S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
region: 'ap-south-1'
});
// creating a s3 presigner obj
const signer = new S3RequestPresigner({ ...s3.config });
// creating file upload request
const AWSUploadRequest = await createRequest(s3, new PutObjectCommand({
Bucket: BUCKET,
Key: KEY
}));
const expire = new Date(Date.now() + EXPIRATION);
// creating & formating presigned URL
signedUrl = formatUrl(await signer.presign(AWSUploadRequest, expire));
console.log(`Generated Signed URL: ${signedUrl}`);
}catch(err){
console.log(`Error creating presigned url ${err}`);
return next(
new ErrorResponse(
`Error while generating aws s3 presigned url`,
500
)
)}
res.status(200).json({
signedUrl
})
}
Here are my logs:
AWSUploadReq: {"method":"PUT","hostname":"s3.ap-south-1.amazonaws.com","query":{"x-id":"PutObject"},"headers":{"Content-Type":"application/octet-stream","user-agent":"aws-sdk-nodejs-v3-#aws-sdk/client-s3/1.0.0-rc.7 win32/v10.15.3"},"protocol":"https:","path":"/dammnn/myKey_file-c6f198d6-9e91-4892-8c88-8a49e15406c1"}
Error creating presigned url Error: TimeoutError
It's very vague as to why the request is getting timed out. Looking for some guidance on the same. Thanks.

S3 presigned url from api returned to aws contoller does not work

I am creating S3 presigned URl in one of my mvc controllers and that is to be consumed by a python lambda. But getting below error
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AccessDenied</Code>
<Message>There were headers present in the request which were not signed</Message>
<HeadersNotSigned>x-amz-date</HeadersNotSigned>
<RequestId>D7815D6EDC8BB6D0</RequestId>
<HostId>jViPAaaoh+UQDQoMzB9QZXAFyIxgvw7sLr7+Otj4tJFukLkynf07B1Z81iYE8aJ4i+p0B+1Dmwc=</HostId>
</Error>
Tried allowing all actions on S3 bucket.
//This is how I am creating presigned URL
public string BuildPreSignedURL(string bucketName, string objectKey)
{
string urlString = string.Empty;
IAmazonS3 s3Client = new AmazonS3Client();
try
{
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = objectKey,
Expires = DateTime.Now.AddMinutes(preSignedURLExpireTimeInMinutes),
};
urlString = s3Client.GetPreSignedURL(request);
}
catch (Exception ex)
{
throw;
}
return urlString;
}
//Below is now it is returned from controller
string preSignedURL = preSignedBuilder.BuildPreSignedURL(bucketName, entityS3Key);
return new RedirectResult(preSignedURL);
AWS lambda calling my api contoller should be able to download the file.
I don't know about C#, but with Python we need to set also the "method" when we generate the presigned URL. In the example below it uses get_object.
s3_client = session.client('s3')
try:
response = s3_client.generate_presigned_url('get_object',
Params={'Bucket': bucket_name,
'Key': object_name},
ExpiresIn=expiration)
except ClientError as e:
logging.error(e)
return None

Getting error while generating presigned url for SSE-C

I have created a customer key for AWS S3 Server side encryption using customer key (SSE-C).
I am able to upload the object using the key. But when I generate a presigned URL using AWS Java SDK the URL is getting created successfully but when I hit that URL I am getting the below error.
SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided. Check your key and signing method.
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.HttpMethod;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.Headers;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.SSEAlgorithm;
import com.amazonaws.services.s3.model.SSECustomerKey;
import com.amazonaws.util.Base64;
import com.amazonaws.util.Md5Utils;
public class GeneratePresignedURL {
public GeneratePresignedURL() throws IOException {
String bucketName = "abctest";
String keyName = "testnew.mp4";
try {
SSECustomerKey SSE_KEY = new SSECustomerKey("KLgsVafKowMCfKDsbIh597CmMUSoPBn6QJ8OIGxAMBw=");
ClientConfiguration cnf = new ClientConfiguration();
cnf.withSignerOverride("AWSS3V4SignerType");
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withClientConfiguration(cnf)
.withCredentials(new ProfileCredentialsProvider()).build();
// Set the presigned URL to expire after one hour.
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
// Generate the presigned URL.
System.out.println("Generating pre-signed URL.");
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName,
keyName).withMethod(HttpMethod.PUT).withExpiration(expiration).withSSECustomerKey(SSE_KEY);
generatePresignedUrlRequest.setSSECustomerKeyAlgorithm(SSEAlgorithm.AES256);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println("Pre-Signed URL: " + url.toExternalForm());
} catch (AmazonServiceException e) {
// The call was transmitted successfully, but Amazon S3 couldn't process
// it, so it returned an error response.
e.printStackTrace();
} catch (SdkClientException e) {
// Amazon S3 couldn't be contacted for a response, or the client
// couldn't parse the response from Amazon S3.
e.printStackTrace();
}
}
I have tried to follow the code from https://aws.amazon.com/blogs/developer/generating-amazon-s3-pre-signed-urls-with-sse-c-part-5-finale/
I have no problem in using pre-signed url for SSE S3, I am only facing issue with SSE-C
I have tried setting default encryption and other config but of no help. Any pointers would be of great help.
Thanks,
AK
You can not call pre-signed URL direct via browser
You need to pass headers in the request
x-amz-server-side-encryption-customer-algorithm
x-amz-server-side-encryption-customer-key
x-amz-server-side​-encryption​-customer-key-MD5
Please check the document for more information
https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html
When using the presigned URL to upload a new object, retrieve an existing object, or retrieve only object metadata, you must provide all the encryption headers in your client application.
Please check the sample code calling signed URL via Unirest library
https://github.com/pavanpawar4591/s3signurlwith-sse-c
public static void getPreSignedURL() throws URISyntaxException {
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
System.out.println("Generating pre-signed URL.");
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, keyName)
.withMethod(HttpMethod.GET).withExpiration(expiration).withSSECustomerKey(SSE_KEY);
// generatePresignedUrlRequest.setContentType("video/mp4");
generatePresignedUrlRequest.setSSECustomerKeyAlgorithm(SSEAlgorithm.AES256);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println("Pre-Signed URL: " + url.toURI() + " With key: " + SSE_KEY);
System.out.println("------------------------------");
//https://aws.amazon.com/blogs/developer/generating-amazon-s3-pre-signed-urls-with-sse-c-part-4/
// refer to above doc
try {
HttpResponse<String> response = Unirest.get(url.toURI().toString())
.header(Headers.SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM, SSEAlgorithm.AES256.getAlgorithm())
.header(Headers.SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY, Base64.encodeAsString(SECRET_KEY.getEncoded()))
.header(Headers.SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5,
Md5Utils.md5AsBase64(SECRET_KEY.getEncoded()))
.header("cache-control", "no-cache").header("postman-token", "d3453c38-1b59-a12e-fd97-dbe2150eadf5")
.asString();
System.out.println(response.getStatus());
System.out.println(response.getStatusText());
System.out.println(response.getBody());
} catch (UnirestException e) {
e.printStackTrace();
}
}
Thanks #pavan
Any client that needs to use SSE-C, the client must be capable of sending the Below headers.
When using the presigned URL to retrieve an existing object, or retrieve only object metadata, we need to provide all the encryption headers in your client application.
For S3 managed or KMS managed server side encryption, we can generate a presigned URL and directly paste that into a browser or player.
However, this is not true for SSE-C objects because in addition to
the presigned URL, you also need to include HTTP headers that are
specific to SSE-C objects. Therefore, you can use the presigned URL
for SSE-C objects only programmatically.
Upload:
I opted for S3 managed keys instead of customer provided client key.
FileInputStream fin = new FileInputStream(uploadFileName);
byte fileContent[] = new byte[(int) uploadFileName.length()];
// Reads up to certain bytes of data from this input stream into an array of
// bytes.
fin.read(fileContent);
// create string from byte array
// Specify server-side encryption.
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(fileContent.length);
objectMetadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
PutObjectRequest putRequest = new PutObjectRequest(bucketName, keyName,
new ByteArrayInputStream(fileContent), objectMetadata);
// Upload the object and check its encryption status.
PutObjectResult putResult = s3Client.putObject(putRequest);
System.out.println("Object \"" + keyName + "\" uploaded with SSE.");
GET Presigned URL:
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
System.out.println("Generating pre-signed URL.");
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, keyName)
.withMethod(HttpMethod.GET).withExpiration(expiration);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println("Pre-Signed URL: " + url.toURI());
Reference:
https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html

Generate a Pre-signed URL Using the AWS SDK for Java

I was following the example from https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURLJavaSDK.html to create pre-signed s3 urls (v4) and I get Access Denied error when I try to access the signed the url
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>0FB02ECDDF5EAC7B</RequestId>
<HostId>vA+mmsv9PCunNe5uPkPrmpqqN3vFctQ13c9dIRlKWTYsT0zNA1V9g+4YS+lCItrBlyQtdHpyspg=</HostId>
</Error>
The following is the code snippet
public class GeneratePresignedURL {
public static void main(String[] args) throws IOException {
String clientRegion = "us-east-1";
String bucketName = "com-example-bucket";
String objectKey = "path/to/file.img"; // No leading `/`
// https://com-example-bucket.s3.amazonaws.com/path/to/file.img
try {
AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();
// Assuming that us-east-1 defaults to v4, couldn't find a way to set it explicitly
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withCredentials(awsCredentialsProvider)
.build();
// Set the presigned URL to expire after 10 minutes.
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 10;
expiration.setTime(expTimeMillis);
// Generate the presigned URL.
System.out.println("Generating pre-signed 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());
/*
sample signature:
https://com-example-bucket.s3.amazonaws.com/path/to/file.img?X-Amz-Security-Token=FQoDYXdzEDcaDLjUOdj2hDTZvWUQaiK3AxulqM%2BOPlp%2Bnq71P0LyuI0vj8tT%2F9i24Wd3jY8dUbudWbhUH9IAsPnl7asujO90GlaFP4dXujDDLwIakMjCJSfOFM4IoGJz8XtcjXkqJCNaenbrTA%2F3PfSl%2Fe9wQwJlY8gOu8%2Byioq2ElHULMKv52nEZj8s3v4dD0pGHQTYc4hGV7ty9CYwXNgz6w3TREhxuFdAewNgTRnY1uFNy7on6NDF5IE15vlJ2PxqrX53ZMLKP%2FdU8i5BcpZ3ySVhNpBpU3GJAPMOh%2B2ztCAk1zPjW4G0N5n9BlnjTMGs3vGBb9IW%2F8dzAoxaG9U9%2B%2FCp8euJN562dYYSZ9wmQgsfOVqc5OksdnHVkPJW400ObOcKmc9mqIRyqA%2B3Mv4z0%2Fx6iLYRJ3UaloFSGbmR6VlIxMl%2F67aHrmCnBE23a1%2BNMWgzLx%2FogqZy3CD%2F%2Fs6Jt1qkxUrRwC0RPK93LHD74qm8rjqZcEKFrBOrZsYtcl3zKgRIEHCbatQ7dwT634sdF0MwaD0vwTsbsStZDW903k5C%2FDuz4rEmkPv6c5CmFvxp4xOkUtMbDk4B8Z641CoeAMMOKICH%2FlW7%2F1as3nQo07Ow2QU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180621T214222Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3000&X-Amz-Credential=<access_key>%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=<signature>
*/
}
catch(AmazonServiceException e) {
// The call was transmitted successfully, but Amazon S3 couldn't process
// it, so it returned an error response.
e.printStackTrace();
}
catch(SdkClientException e) {
// Amazon S3 couldn't be contacted for a response, or the client
// couldn't parse the response from Amazon S3.
e.printStackTrace();
}
}
}
The signature format seems to be correct and I am not sure if I am missing some other s3 client config.
Since I don't get a signature mismatch error or invalid url error, I assume that the Access Key used to sign the url is correct.
Here are steps to generate aws-s3 pre-signed url to access the content stored in s3 through java can create with simple step
First add maven dependency in your pom
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.870</version>
</dependency>
Get S3 credential accessKey, secretKey, region of s3 storage it must needed
Write java class
First get s3Client connection using below code snippet providing your own credential
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
final AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new
AWSStaticCredentialsProvider(awsCreds)).withRegion(region).build();
You must have your bucketName if you don't have create bucket and store your content
Use below code snippet to generate pre-signed url
// Set the expiry time
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
Pass your objectKey is noting but your existed s3 base filename
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, objecKey)
.withMethod(HttpMethod.GET)
.withExpiration(expiration);
URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println("Pre-Signed URL: " + url.toString());
It is due to the region mismatch. You have set clientRegion to be us-east-1 but if you are accessing it from any other region it will give access denied error. You can only access the object from us-east-1 region or just change it to your region. It's ap-south-1 for Indian clients.
The issue seems to be that the role didn't have permissions to access the s3 bucket path/to/file
Try to add .withPathStyleAccessEnabled(true) as mentioned in below snap.
// Assuming that us-east-1 defaults to v4, couldn't find a way to set it explicitly
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withPathStyleAccessEnabled(true)
.withCredentials(awsCredentialsProvider)
.build();
Change/check this change CROS properties of AWS S3 bucket.
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
Be mindful of assigning the cognito auth-role with access to S3 else the permission will be denied in case you are using the cognito-credentials user pool session to provide the required access to s3client. This was an issue which i was facing as well.
import com.amazonaws.AmazonServiceException;
import com.amazonaws.HttpMethod;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.163</version>
</dependency>
String GeneratePresignedUrlAndUploadObject() {
String accesskey = "XXXXXXXXXXXXXXXXXXXXXX";
String secretkey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
String bucketName = "your-bucket-Name";
Regions regions = Regions.US_EAST_1;
String objecKey = "your-file-name-you-need-url";
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accesskey, secretkey);
//
final AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds)).withRegion(regions).build();
// Set the expiry time
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objecKey)
.withMethod(HttpMethod.GET).withExpiration(expiration);
//
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println("Pre-Signed URL: " + url.toString());
return url.toString();
}