tsibelman / aws-signer-v4-dot-net Goto Github PK
View Code? Open in Web Editor NEWSign HttpRequestMessage using AWS Signature v4 using request information and credentials.
License: Apache License 2.0
Sign HttpRequestMessage using AWS Signature v4 using request information and credentials.
License: Apache License 2.0
Hey Y'all,
When I use the signer on the new Bedrock API, I get an error back about the content type being incorrect. It's expecting "application/json" and it works with this type in Postman, but for some reason it isn't working with the signer.
Below is the code where I'm setting the type in the request's Content, like your example. But with the below code I get back: "message": "The provided Content Type is invalid or not supported for this model"
, which is the behaviour received in Postman when I change the type from json to something else, like text.
This may be a Bedrock issue, but wondering if this issue has been tracked before.
Thanks!
var signer = new AWS4RequestSigner(_titanAccessKey, _titanSecretKey);
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://bedrock.us-west-2.amazonaws.com/model/amazon.titan-tg1-large/invoke"),
Content = new StringContent(promptJson, Encoding.UTF8, "application/json")
};
request = await signer.Sign(request, "bedrock", "us-west-2");
var client = new HttpClient();
var response = await client.SendAsync(request);
var resultString = await response.Content.ReadAsStringAsync();
SHA256 implements IDisposable. Aws4RequestSigner
should implement IDisposable to clean up that reference.
Is this library compatible with .Net Core? And what is the minimum .Net framework that is supported?
I don't see any locking code inside the sign method?
Hi,
Could you please sign the nuget package? We require strongly-named assemblies in our project.
Thanks!
Marc
Hi tsibelman,
I'm using your example code and it is giving me some errors in the "await" in:
request = await signer.Sign(request, "execute-api", awsSeverLocation);
var response = await client.SendAsync(request);
var responseStr = await response.Content.ReadAsStringAsync();
In the 3 of them the compiler is giving me this: "The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'".
Could you please what could I be missing?
Best regards,
snabulsa
Hello,
I keep getting this error in code but not when I make the call directly in Postman, to Amazon.
"The request signature we calculated does not match the signature you provided"
Service: sts
Region: us-east-1
Action: both AssumeRole and GetSessionToken. Works in direct call to Amazon from Postman but not thru code.
I've done a bunch of Googling for this error and no suggestions work. Like "check time on computer", etc.
Any ideas on what could be happening? I'm more than happy to provide additional information.
I have a problem when i try to pass a parameter into my api call.
I get this error :
SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided. Check your key and signing method.
I use this code.
I want to pass the "versions" parameter.
public static async Task<HttpResponseMessage> GetVersion(string bucketName, string objectName)`
{
return await CallWebservice(HttpMethod.Get, new Uri("https://" + bucketName + "." + service + "." + region + "." + provider + "/?versions));
}
private static readonly string region = "fr-par";
private static readonly string service = "s3";
private static readonly string provider = "scw.cloud";
private static async Task<HttpResponseMessage> CallWebservice(HttpMethod method, Uri uri, byte[] content = null)
{
string sha256Hash = sha256("");
var signer = new AWS4RequestSigner(keyId, secretAccessKey);
var request = new HttpRequestMessage
{
Method = method,
RequestUri = uri
};
if(content != null)
{
request.Content = new ByteArrayContent(content);
sha256Hash = Hash(content);
}
request.Headers.Add("x-amz-content-sha256", sha256Hash);
request = await signer.Sign(request, service, region);
var client = new HttpClient();
var response = await client.SendAsync(request);
return response;
}
private static string Hash(byte[] bytesToHash)
{
SHA256 _sha256 = SHA256.Create();
var result = _sha256.ComputeHash(bytesToHash);
return ToHexString(result);
}
private static string ToHexString(byte[] array)
{
var hex = new StringBuilder(array.Length * 2);
foreach (byte b in array)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
static string sha256(string randomString)
{
var crypt = new SHA256Managed();
var hash = new StringBuilder();
byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
foreach (byte theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString();
}
Can you please help me.
Thank you
You might want to take a look at HexConverter.ToString() for some inspiration.. It's an internal class that does handle lower case byte[] to hex string conversion. It's going to be a bunch faster than a string formatting loop.
According to the pull request for passing a token in addition to the Key and Secret you have added this functionality. I am getting this error from the following code line.
AWS4RequestSigner l_signer = new AWS4RequestSigner(m_sKey, m_sSecret, m_sToken);
I want to sent post request to fetch the data but its showing cannot convert HttpRequestMessage to String. Can you please let me know how should i do it
While writing a some code for uploading files to s3 buckets i encountered a bug where when building the canonicalRequest your code would use "request.RequestUri.AbsolutePath" but that would already escape part of the request uri example: "/Assets/Translations/General/Chinese (Simplified).json" would become "/Assets/Translations/General/Chinese%20(Simplified).json" when accessing AbsolutePath property, i fixed this by calling Uri.UnescapeDataString(request.RequestUri.AbsolutePath)
The final code looks like this for me:
var unescaped = Uri.UnescapeDataString(request.RequestUri.AbsolutePath);
canonicalRequest.Append(string.Join("/", unescaped.Split('/').Select(Uri.EscapeDataString)) + "\n");
Maybe this it was my bad somewhere but maybe this can help you.
Hi
I found another thing
If there is a space in the url itself, not just the query string we have the same problem.
If the url contains space, normally it is encoded to + or %20
But then it is encoded again with the % to %25 so the %20 becomes %2520
AWS complains about that – the message that “the canonical string should be …”
The solution is to Escape also the URL, but one must be careful since it wants to encode also the / characters:
So:
In the place where you have:
canonical_request.Append( request.RequestUri.AbsolutePath + "\n" );
use this:
string sanitizedUrl = SanitizeUrl( request.RequestUri.AbsolutePath );
canonical_request.Append( sanitizedUrl + "\n" );
and add SanitizeUrl method:
private string SanitizeUrl( string absolutePath )
{
StringBuilder sb = new StringBuilder();
string[] segments = absolutePath.Split( new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries );
foreach( var s in segments )
{
sb.Append( "/" );
sb.Append( Uri.EscapeDataString( s ) );
}
return sb.ToString();
}
Thank you
All request.Content.Headers are lost when signing a request. Specifically seeing this with Content-Type.
Hi,
I just used your package to use my service, but getting a 403 error. Can you please suggest what can be wrong here? I can use the service call from Postman but not able to call it from code.
I am emailing you the keys and request if you can help me with that.
Regards,
Mufaddal
New to github so sorry if this is the wrong place to ask. I am pretty confused with AWS singing and I have to talk to one of their new APIs without any previous experience. Do you have a working example showing a full simple get request using your library to sign it?
I have a problem while requesting "https://example.com/users/{userId}/charities/findByCharityName?offset=20&searchTerm=red wing"
it's responding me as "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."
even I am converting searchTerm to Uri.EscapeDataString(searchTerm).
Can you please help me to resolve this issue.
Thank You....
Base on the comment
//Handles keys without values
it seems to look for the key instead of its value.
Example:
var requestUri = "https://aaa?colorA=&colorB=red";
# create a request with this requestUri
var querystring = HttpUtility.ParseQueryString(request.RequestUri.Query);
foreach (var key in querystring.AllKeys)
querystring is {colorA=&colorB=red}
querystring.AllKeys is an array with "ColorA" and "ColorB"
I don't think it can ever be key == null
.
Probably the check should be on the value instead, querystring[key] == null
.
Also, it seems to mixed up key and value when it creates the escaped value,
maybe the code was meant to be like this:
var escapedKey = Uri.EscapeDataString(key);
//if (key == null)
if (querystring[key] == null)//Handles keys without values
{
//values.Add(Uri.EscapeDataString(querystring[key]), new[] { $"{Uri.EscapeDataString(querystring[key])}=" });
values.Add(escapedKey, new[] { $"{escapedKey}=" });
}
I get forbidden error when trying to request audio data from amazon poly:
"https://polly.us-east-1.amazonaws.com/v1/speech";
// Specify the URL
string apiUrl = "https://polly.us-east-1.amazonaws.com/v1/speech";
// AWS credentials
string _accessKey = "myaccesskey";
string _secretKey = "mysecret";
string _region = "us-east-1";
PollyRequest pollyRequest = new PollyRequest
{
OutputFormat = "json",
Text = "Hello, this is a sample text to be synthesized.",
VoiceId = "Joanna",
SpeechMarkTypes = new[] { "viseme", "word" },
LexiconNames = new string[] { },
SampleRate = "22050",
TextType = "text",
LanguageCode = "en-US"
};
// Convert the object to JSON
string _json = JsonConvert.SerializeObject(pollyRequest);
var signer = new Aws4RequestSigner.AWS4RequestSigner(_accessKey, _secretKey);
var content = new StringContent(_json, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(apiUrl),
Content = content
};
request = await signer.Sign(request, "Polly", _region);
var client = new HttpClient();
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
I recommend escaping the querystring[key] in your GetCanonicalQueryParams method
like:
var queryParams = keys.Select( key => $"{key}={Uri.EscapeDataString( querystring[key] )}" );
This will help avoiding problems with some character encoding like space which can be + or %20.
This has caused issues in my case
I am trying to call getCatalogItem operation with multiple comma separated values in IncludedData parameter.
When I am including more than one value (i.e. attributes,identifiers,images,summaries), it has generated wrong canonical string and throws a signature error. (Note: It is adding 'includedData=' for each values)
@tsibelman I think this is caused by https://github.com/tsibelman/aws-signer-v4-dot-net/pull/25/files changes. I have tried to revert those changes in my code with some modification and it gives me correct Querystring (includedData=attributes%2Csummaries%2Cidentifiers%2Cimages&locale=en-US&marketplaceIds=XXXXXXXXXXXXXX)
I am using 1.0.3.0 package version of Aws4RequestSigner.
Generated canonical string using current code/package:
GET
/catalog/2020-12-01/items/
includedData=attributes&includedData=identifiers&includedData=images&includedData=summaries&locale=en-US&marketplaceIds=XXXXXXXXXXXXXX
host:sellingpartnerapi-fe.amazon.com
x-amz-access-token: <XXXXXXX.....>
x-amz-content-sha256:<XXXXXXX.....>
x-amz-date:20220420T001006Z
x-amz-security-token:<XXXXXXX.....>
Error:
{
"errors": [
{
"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.
The Canonical String for this request should have been
'GET
/catalog/2020-12-01/items/
includedData=attributes%2Csummaries%2Cidentifiers%2Cimages&locale=en-US&marketplaceIds=XXXXXXXXXXXXXX
host:sellingpartnerapi-fe.amazon.com
x-amz-access-token:<XXXXXXX.....>
x-amz-content-sha256:<XXXXXXX.....>
x-amz-date:20220419T235917Z
x-amz-security-token:<XXXXXXX.....>
host;x-amz-access-token;x-amz-content-sha256;x-amz-date;x-amz-security-token
<XXXXXXX.....>'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20220419T235917Z
20220419/us-west-2/execute-api/aws4_request
'
",
"code": "InvalidSignature"
}
]
}
See below for reference:
https://developer-docs.amazon.com/sp-api/docs/catalog-items-api-v2020-12-01-use-case-guide
Endpoint: GET https://sellingpartnerapi-na.amazon.com/catalog/2020-12-01/items/XXXXXXXXXX
?marketplaceIds=ATVPDKIKX0DER
&includedData=attributes,identifiers,images,summaries
Does anyone have any idea how I can resolve this issue?
Hi,
First of all thanks for your time and acknowledgment.
I clone your solution to test my aws account but always return 403.
However, if I try the same with a java solution they run correctly.
Can you test and certificate than the code run correctly and the problem is my?
Thanks!
Hi,
I am trying to make a simple request to the AWS Elastic search service but I am getting a 403 error
"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"
I am pretty sure I have set up access to the service correctly and got the correct access keys.
I'm using es
as the service parameter on the Sign method but I am not sure this is correct. This documentation uses the string es
but I'm still not 100% sure this is right.
Do you know where I can confirm that this is the correct service name string?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.