I'm using AWS signV4 to sign requests for calling AWS API Gateway.
Using Requests with headers are not suited for my use case hence the initiative to work with signed urls and query strings.
I had used AWS Sample Python sample that works great for IAM user creation.
the same Access Key and Secret are used in both cases (IAM Creation , API Gateway call) so its definitely not an issue of wrong access key / secret.
The main issue i see is that the signature i get is different than the one the API Gateway thinks i should send.
I've added all the documented query string but still get the below error.
What am i missing here?
Here is the request URL:
https://*******.execute-api.us-east-1.amazonaws.com/******?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=**********%2F20170424%2Fus-east-1%2Fexecute-api%2Faws4_request&X-Amz-Date=20170424T124521Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host&X-Amz-Signature=**********821742cee7661ef3a0ab1e5c
While using it with the execute-api service i had received the following error :
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'GET\n/*******\nX-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=*********%2F20170424%2Fus-east-1%2Fexecute-api%2Faws4_request&X-Amz-Date=20170424T124521Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host\nhost:*******.execute-api.us-east-1.amazonaws.com\n\nhost\n*********'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20170424T124521Z\n20170424/us-east-1/execute-api/aws4_request\n**********'\n"
}
I've Checked also the java implementation using the samples from : AWS Signer Java
but the results were the same.
SigV4 signing and this error message isn't anything specific to API Gateway itself. The signing algorithm and the verification at the AWS end is common for all AWS services.
Can you compare the canonical string that is in the error message and the one that you are generating while sending the request? That should help you identify the issue.
Also, go through the step-by-step explanation to see if you are doing everything right. One of the common issues is case-sensitivity of header names and the sorting order of parameters.
Related
So I've created the java algorithm for AWS signature creation, following the guidelines of AWS >https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
The algorithm is available on my github >https://github.com/marcodag/aws_signature_creation/blob/main/SignatureCreation.java
These are the steps that I take:
retrieve secret key, access key and token from AWS account
create call on Postman (for Linux) v8.12.5, by using AWS Signature auth
the call goes OK.
I retrieve the signature that it created and the X-AMZ-DATE used
I run my java algorithm and check if the signature is the same as postman produced
they're the same.
So a colleague tries the same steps, but with latest postman version (9+). Postman call goes OK, but it generates a different signature from the java one. Also, he created a js algorithm based on the java one and the js and java make the same signature. Just, my postman matches the signature, his not.
The number and type of headers generated are the same.
What could be the problem?
SOLVED
Well, my postman was calling an url like
https://s3.eu-west-1.amazonaws.com/a_bucket/a_key
with the dot between s3 and eu. And my colleague was calling
https://s3-eu-west-1.amazonaws.com/a_bucket/a_key
with the dash between s3 and eu. AWS is accepting both.
Of course the host is used to create the signature, hence the differences.
I'm trying to generate an access token following the docusign documentation, but when it arrives at the part of the sequence incorporated in the url, I can't generate the signature compatible with what is requested RSA-256.
This is the token that returns in the url, how should i proceed to generate the correct token to get the access token to the methods.
eyJ0eXAiOiJNVCIsImFsZyI6IlJTMjU2Iiwia2lkIjoiNjgxODVmZjEtNGU1MS00Y2U5LWFmMWMtNjg5ODEyMjAzMzE3In0.AQsAAAABAAYABwCAWdDpkO_YSAgAgOVWMZHv2EgCAC8x_aWgjDdEpqZZDhWJAksVAAEAAAAYAAIAAAAFAAAAHQAAAA0AJAAAADY4ZDFlYTk3LTk5ZDMtNDM4MS05MmY5LTg3ZTdlMWFiMWIzOCIAJAAAADY4ZDFlYTk3LTk5ZDMtNDM4MS05MmY5LTg3ZTdlMWFiMWIzODAAgFnQ6ZDv2EgSAAEAAAALAAAAaW50ZXJhY3RpdmU3AF2EwqcBnYBHm1UeBpeUZIA.5AiJJl_ugWRECf7jTD7DchgUZV_Mk30cXJwmPAMkThH9dwtu2A9ehMwkARi0QvmSIoo1Pk-gUj2U_GMAk9flG5IAHVYIPcy9hbWMcRyr7RMYldKqvh2V8UH4-Uv5BBQNHkwQ36spfuYFaafDLHVq86Mt91m4MK-ZByRzZkboQKNHCaNjani-hPNTlhHkkWuKOPTu8R9GY24TvNhRu9ILYRgRUFsXG3E-ptNFTyhdKM8_RuNQrqed9ZA2oPo4WjNm-b1VIFdVElU3duniBS-inWJD2ifzp8N1zKFm_Nv8UMjpZOtitdW0M4QQ7rXG6Q-6xoNE_ODWQZUWsD2mQaz4_A
Is there any configuration in the sandbox that may be generating this token wrongly? Whatever it is i need help to generate this token in postman, because i need to integrate with my API and test the methods before coding.
Here is how you generate a token with Postman using Authorization Code Grant:
Open a browser and go to this URL (after you updated it with your info) https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature&client_id={iKey}&redirect_uri={callback}
If it's configured correctly, you should now be redirected back to your redirectUri with an additional URL parameter called code.
Copy/paste this code into your Postman application. You would have to copy/paste the code that you obtained from the URL parameter into the Body key/value pair (replacing the {{codeFromUrl}} value). Note that the code is valid for two minutes only. If you don’t send this information to DocuSign quickly enough, you will have to obtain a new code again. Hit the Send button at the top of Postman to make the call to DocuSign.
Now, you indicated you are using Java, so another approach for you may be to use our Quickstart and select Java. That will take care of all the Auth configuration for you.
I'm inheriting a codebase that makes use of the Java AWS SDK to generate presigned S3 URLs for both Putting and Getting Objects. The code looks something like this:
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, filename);
request.setMethod(HttpMethod.PUT);
request.setExpiration(new DateTime().plusMinutes(30).toDate());
request.setContentType("image/jpeg");
String url = awss3.generatePresignedUrl(request);
And this existing codebase has always worked, and is very close to working. However, one business requirement that changed is that we need to encrypt the contents of the S3 bucket. So, naturally, I set the default encryption on the bucket to AWS-KMS (since it seemed like the most modern) and choose the default "aws/s3" key that had been created for my account.
However, now when an end user tries to actually utilize the URLs I generate in their browser, this is the error message that appears:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<code>InvalidArgument</code>
<Message>Requests specifying Server Side Encryption with AWS KMS managed keys require AWS Signature Version 4.</Message>
<ArgumentName>Authorization</ArgumentName>
<ArgumentValue>null</ArgumentValue>
<RequestId>...</RequestId>
<HostId>...</HostId>
</Error>
My question is utlimately: how do I get this working again? As I see it there are two different paths I could take. Either: 1) I could downgrade the bucket encryption from AWS-KMS to AES-256 and hope that it all works, or 2) I can make some change to my client code to support KMS, which I'm guessing would probably involve downloading the KMS key through the AWS SDK and using it to sign the requests, and possibly also adding some Authorization and other headers.
Option 1 seems like less work but also less ideal, because who knows if a less secure form of encryption will always be supported. And Option 2 seems like the better choice conceptually, but also raises some concerns because it does seem like a lot more work and I'm worried about having to include extra headers. The code I've shown above reflects the equivalent of a PutObject request (proxied through the generated URL), but there are also equivalents of GetObject requests to download the images, which are possibly rendered directly in the browser. It would be a lot harder to write frontend code there to use different headers just to render an image. (I wonder if query parameters can be substituted for headers?)
Anyways, what would I need to change in my Java to get this working with AWS KMS? Do I need to use the AWS SDK to "download" the KMS key first as I suspected? And should I go about doing it that way, or would AES-256 really be the better option?
Signing signature verion 4 has been the default for several years. Unless you are overriding the signature in your AWS SDK profile, then you are using version 4. You can override this using the following code:
AmazonS3Client s3 = new AmazonS3Client(new ClientConfiguration().withSignerOverride("AWSS3V4SignerType"));
Most likely the real issue is that you need to specify server side encryption when you create the presigned URL.
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
myBucket, myKey, HttpMethod.PUT)
.withSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());
request.setExpiration(new DateTime().plusMinutes(30).toDate());
request.setContentType("image/jpeg");
URL puturl = s3.generatePresignedUrl(request);
I'm trying to adapt this example to use with GAE: https://bitbucket.org/b_c/jose4j/wiki/JWT%20Examples
Above example requires a private key (secret) to sign JWT header + payload. AppIdentityService provides a way to sign arbitrary bytes but it does not explain how to verify the signature using PublicCertificate.
I need help to identify 2 things-
How to store and manage secret key in Google App Engine?
How to verify signature using AppIdentityService?
A reference to some working example which uses JWT with GAE would be very helpful.
An adaptation of the example at https://bitbucket.org/b_c/jose4j/wiki/JWT%20Examples that should work, if GAE signs using RSASSA-PKCS1-v1_5 using SHA-256, is in the first comment of https://bitbucket.org/b_c/jose4j/issues/33/using-jwt-with-google-app-engine
I have couple of doubts regarding the usage and working of /venue/stats Foursquare API.
Q1. I would be using /venue/stats for getting information provided a venue id. So I have registered my app and got the client id and secret values. I went to Foursquare API endpoint and tried using /venue/stats api and I noticed a oauth_token generated automatically by FSQ so is this oauth_token the same token that I am required to use everytime I use this api ? Do I need to do the authentication steps mentioned ?
Q2. Try the api generates a link which has /simulate in the api URL. I assume that this is due to the fact that I am testing the API so FSQ has categorized such api calls as simulate calls. Please confirm my understanding. If this is so then whenever I use the api as mentioned i.e. /v2/venues/venue_id/stats I get an error JSON stating that I am unauthorized to view venue stats. Can you please tell me why ? If this is due to access_token issue then the same issue should have been with simulate call also ?
Hoping to get a reply soon.
Right underneath the API Explorer bar it says "OAuth token automatically added". You do not use this token. I am sure it is either temporary or created using your log in info if you are loggged in while using the API Explorer. You will still have to use the authentication process to get a valid access token. However, you can save this access token and use it again skipping the Auth process. An access token serves as a key unique to a user and app. Read more about it here: https://developer.foursquare.com/overview/auth
The simulate feature is used mostly for API calls that normally would require you to be a manager of the venue. There are certain calls that can not be done unless the app is by a user that is the manager or unless you make the call using an access token of a manager.