Amazon (AWS) - The request must contain the parameter Signature - c#

I'm struggling with the final part of getting my first bit of code working with the AWS - I have got this far, I attached the web reference in VS and this have this
amazon.AWSECommerceService service = new amazon.AWSECommerceService();
// prepare an ItemSearch request
amazon.ItemSearchRequest request = new amazon.ItemSearchRequest();
request.SearchIndex = "DVD";
request.Title = "scream";
request.ResponseGroup = new string[] { "Small" };
amazon.ItemSearch itemSearch = new amazon.ItemSearch();
itemSearch.AssociateTag = "";
itemSearch.Request = new ItemSearchRequest[] { request };
itemSearch.AWSAccessKeyId = ConfigurationManager.AppSettings["AwsAccessKeyId"];
itemSearch.Request = new ItemSearchRequest[] { request };
ItemSearchResponse response = service.ItemSearch(itemSearch);
// write out the results
foreach (var item in response.Items[0].Item)
{
Response.Write(item.ItemAttributes.Title + "<br>");
}
I get the error
The request must contain the parameter Signature.
I know you have to 'sign' requests now, but can't figure out 'where' I would do this or how? any help greatly appreciated?

You have to add to the SOAP request headers including your Amazon access key ID, a timestamp, and the SHA256 hash of the request operation and the timestamp. To accomplish that, you would need access to the SOAP message just before it is going to be sent out. There's a walkthrough and a sample project I put together at http://flyingpies.wordpress.com/2009/08/01/17/.

For the record:
Another reason to get this error is due to keywords with spaces in it.
Example:
'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=xxx&AssociateTag=usernetmax-20&Version=2011-08-01&Operation=ItemSearch&ResponseGroup=Medium,Offers&SearchIndex=All&Keywords=Baby
Stroller&MerchantId=All&Condition=All&Availability=Available&ItemPage=1&Timestamp=2012-05-16T02:17:32Z&Signature=ye5c2jo99cr3%2BPXVkMyXX8vMhTC21UO4XfHpA21%2BUCs%3D'
It should be:
'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=xxx&AssociateTag=usernetmax-20&Version=2011-08-01&Operation=ItemSearch&ResponseGroup=Medium,Offers&SearchIndex=All&Keywords=Baby%20Stroller&MerchantId=All&Condition=All&Availability=Available&ItemPage=1&Timestamp=2012-05-16T02:17:32Z&Signature=ye5c2jo99cr3%2BPXVkMyXX8vMhTC21UO4XfHpA21%2BUCs%3D'
PHP solution:
$Keywords = str_replace(' ', '%20', $Keywords);
or
$Keywords = urlencode($Keywords);

Related

TikTok api user/info/ endpoint return error code 6007063

I implemented TikTok PI and everything works well. In the last days I encountered a problem that the user/info/ endpoint returns 'error code': '6007063', 'message': 'auth user info is required'. This is happening for some of the accounts while others succeeded (there is nothing different between the accounts), I guess it's on tiktok side.
var Client = new HttpClient();
var userDataRequest = new UserDataRequest
{
open_id = tokenObj.data.open_id,
access_token = tokenObj.data.access_token,
fields = new HashSet<string> { "open_id", "union_id", "avatar_url", "avatar_url_100", "avatar_url_200", "avatar_large_url", "display_name" }
};
var json = JsonConvert.SerializeObject(userDataRequest);
var body = new StringContent(json, Encoding.UTF8, "application/json");
var response = await Client.PostAsync("https://open-api.tiktok.com/user/info/", body).ConfigureAwait(false);
How can I solve the problem and what does this error mean?
https://developers.tiktok.com/doc/login-kit-user-info-basic
I encountered the same issue and I found that the way I refresh the access token is incorrect. POST https://open-api.tiktok.com/oauth/refresh_token/
For this API, we should put client_key, grant_type, and refresh_token in the query instead of in the body or post data.
POST https://open-api.tiktok.com/oauth/refresh_token/?client_key={my_client_key}&grant_type=refresh_token&refresh_token={my_client_token}
This solves my problem. Maybe you could check the way you refresh your access token to solve this issue.
Indeed, all data should be in the link, and not in the body of the request. And then when receiving a token by reference https://open-api.tiktok.com/oauth/access_token/ it works correctly when using it further
Doc: https://developers.tiktok.com/doc/login-kit-manage-user-access-tokens/
let url_access_token = 'https://open-api.tiktok.com/oauth/access_token/';
url_access_token += '?client_key=' + CLIENT_KEY;
url_access_token += '&client_secret=' + CLIENT_SECRET;
url_access_token += '&code=' + code;
url_access_token += '&grant_type=authorization_code';

Http 403 server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature

I generated SAS url with below code
var blobBuilder = new BlobSasBuilder()
{
ExpiresOn = DateTimeOffset.UtcNow.AddDays(2),
Protocol = SasProtocol.Https,
StartsOn = DateTimeOffset.UtcNow.AddDays(-2),
BlobContainerName = _containerName
};
var blockBlob = _blobContainer.GetBlobClient(fileName);
blobBuilder.SetPermissions(BlobAccountSasPermissions.Read);
var isBlobExist = blockBlob.Exists();
if (isBlobExist)
{
var uriData = blockBlob.GenerateSasUri(blobBuilder);
if (uriData != null)
{
path = uriData.AbsoluteUri;
}
}
Generated URI is working most of the time for mobile users but sometimes it returns this error message when trying to download file
server returned http 403 server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature
I am not sure what wrong am I doing here because it works most of the time but doesn't work sometime.
I am also wondering if this is the case when someone try to override the file and other user is trying to read it. Please suggest

Adding note to cell in google sheets c#

Is it possible to add notes to cells using Google? Apis.Sheets.v4?
It seems possible in python: Is it possible to use the Google Spreadsheet API to add a comment in a cell? but I've had no success duplicate it to c#, Insert a comment in a Google Sheet with google-sheets-api describes how to add it using an https call, but I would much rather use the google c# library than start sending HTTP calls myself if at all possible.
It would be a huge help if anyone know-how, or can point me towards a working example.
Thanks in advance.
Using Rafa Guillermos advice i got it to work.
public async void AddNote(string sheet, int column, int row, int sheetId, string noteMessage)
{
await Task.Delay(1);
var requests = new List<Request>();
// Grid range for a single cell, end column, and row have to be +1, otherwise, sheet throws error trying to write outside bounds.
var gridRange = new Google.Apis.Sheets.v4.Data.GridRange
{
EndColumnIndex = column + 1, StartColumnIndex = column, EndRowIndex = row + 1, StartRowIndex = row, SheetId = sheetId
};
// Building a request for update cells.
var request = new Google.Apis.Sheets.v4.Data.Request();
request.UpdateCells = new Google.Apis.Sheets.v4.Data.UpdateCellsRequest();
request.UpdateCells.Range = gridRange;
request.UpdateCells.Fields = "note";
request.UpdateCells.Rows = new List<Google.Apis.Sheets.v4.Data.RowData>();
request.UpdateCells.Rows.Add(new Google.Apis.Sheets.v4.Data.RowData());
request.UpdateCells.Rows[0].Values = new List<Google.Apis.Sheets.v4.Data.CellData>();
request.UpdateCells.Rows[0].Values.Add(new Google.Apis.Sheets.v4.Data.CellData());
request.UpdateCells.Rows[0].Values[0].Note = noteMessage;
requests.Add(request);
var requestBody = new Google.Apis.Sheets.v4.Data.BatchUpdateSpreadsheetRequest();
requestBody.Requests = requests;
var service = _authenticatorService.GetSheetsService(new[] { SheetsService.Scope.Spreadsheets} );
var batchRequest = service.Spreadsheets.BatchUpdate(requestBody, _spreadsheetId);
batchRequest.Execute();
}
_authenticatorService gives an authenticated sheet service to work with.
Answer:
In exactly the same way as python, you need to build your note as a batch request in C#.
Code Snippets:
You need to build your data request as list like:
List<Data.Request> requests = new List<Data.Request>();
and assign the values to the request body for the batch:
Data.BatchUpdateSpreadsheetRequest requestBody = new Data.BatchUpdateSpreadsheetRequest();
requestBody.Requests = requests;
before building the request object:
SpreadsheetsResource.BatchUpdateRequest request = sheetsService.Spreadsheets.BatchUpdate(requestBody, spreadsheetId);
and execute the request:
Data.BatchUpdateSpreadsheetResponse response = request.Execute();
More Information:
You can read about spreadsheets.batchUpdate here with a C# example code at the bottom of the page here.
A JSON representation of the request resource can be found here which follows the same structure as the answer you linked here.
References:
Sheets API v4 - spreadsheets.batchUpdate
Example code for spreadsheets.batchUpdate
Sheets API v4 - JSON Representation of Batch Request
Stack Overflow - Is it possible to use the Google Spreadsheet API to add a comment in a cell?

Unable to verify Forge callback payload signature

I am currently using Forge Webhooks API to handle different events that might occur on a project. Everything works fine, except the payload signature check.
The reason why I want to check the payload is because the callback will end up on my API and I want to reject all requests that do not come from Forge's webhook service.
Steps I followed:
Add (register) secret key (token) on Forge. API Reference
Trigger an event that will eventually call my API for handling it.
Validating signature header. Followed this tutorial.
PROBLEM!!! My computedSignature is different from the signature received from Forge.
My C# code looks like this:
private const string SHA_HASH = "sha1hash";
var secretKeyBytes = Encoding.UTF8.GetBytes(ForgeAuthConfiguration.AntiForgeryToken);
using var hmac = new HMACSHA1(secretKeyBytes);
var computedHash = hmac.ComputeHash(request.Body.ReadAsBytes());
var computedSignature = $"{SHA_HASH}={computedHash.Aggregate("", (s, e) => s + $"{e:x2}", s => s)}";
For one example, Forge's request has this signature header: sha1hash=303c4e7d2a94ccfa559560dc2421cee8496d2d83
My C# code computes this signature: sha1hash=3bb8d41c3c1cb6c9652745f5996b4e7f832ca8d5
The same AntiForgeryToken was sent to Forge at step 1
Ok, I thought my C# code is broken, then I tried this online HMAC generator and for the given input, result is: 3bb8d41c3c1cb6c9652745f5996b4e7f832ca8d5 (same as C#)
Ok, maybe the online generator is broken, I tried their own code in node js and this is the result:
I have 3 ways of encrypting the SAME body using the SAME key and I get the SAME result every time. BUT those results are DIFFERENT from the signature provided by Forge, resulting in failing the check and rejecting a valid request...
Does anyone know what is happening with that signature?
Why is it different from my result if I follow their tutorial?
How are you validating your requests?
The code below is working at my side. Could you give it a try if it helps?
[HttpPost]
[Route("api/forge/callback/webhookbysig")]
public async Task<IActionResult> WebhookCallbackBySig()
{
try
{
var encoding = Encoding.UTF8;
byte[] rawBody = null;
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
rawBody = encoding.GetBytes(reader.ReadToEnd());
}
var requestSignature = Request.Headers["x-adsk-signature"];
string myPrivateToken = Credentials.GetAppSetting("FORGE_WEBHOOK_PRIVATE_TOKEN");
var tokenBytes = encoding.GetBytes(myPrivateToken);
var hmacSha1 = new HMACSHA1(tokenBytes);
byte[] hashmessage = hmacSha1.ComputeHash(rawBody);
var calculatedSignature = "sha1hash=" + BitConverter.ToString(hashmessage).ToLower().Replace("-", "");
if (requestSignature.Equals(calculatedSignature))
{
System.Diagnostics.Debug.Write("Same!");
}
else
{
System.Diagnostics.Debug.Write("diff!");
}
}
catch(Exception ex)
{
}
// ALWAYS return ok (200)
return Ok();
}
If this does not help, please share with your webhook ID (better send email at forge.help#autodesk.com). We will ask engineer team to check it.

Need help interfacing with the National Rail Enquiries (UK) API (LDBWS)

I've registered for a token to access the National Rail (UK), Live Departure Boards API, but I can't seem to get it to work. Can anybody point out what I'm doing wrong?
I used WSDL.EXE to build a C# SOAP Proxy class, as specified here: https://realtime.nationalrail.co.uk/ldbws/
The generated .cs proxy file is 1318 lines long, but it looks correct.
My code is as follows: (LDBServiceSoap is the generated proxy class)
static void Main(string[] args)
{
LDBServiceSoap ldb = new LDBServiceSoap();
ldb.AccessTokenValue = new AccessToken() {
TokenValue = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
};
StationBoard sb = ldb.GetDepartureBoard(4, "WAT", "VIC", FilterType.from, 0, 120);
}
The Url is set inside the proxy class, so I can't think of anything else I need to do.
But when the debugger gets up to the GetDepartureBoard method, it throws a WebException "The request failed with HTTP status 401: Unauthorized."
Does anybody know what I'm missing / doing wrong here?
You're awesome!
If you obtained your access token through the OpenLDWS signup then your token will only work on the https://realtime.nationalrail.co.uk/OpenLDBWS/ endpoint that could be your problem
Not sure how you've generated your sources but I've managed to get a working version using this Web service client given WSDL to generate the sources from the WSDL:
wsimport -extension -keep -XadditionalHeaders https://lite.realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2016-02-16
Then I call the method once the sources are on the classpath with the following:
AccessToken token = new AccessToken(); // This class is generated from the WSDL
token.setTokenValue("yourTokenHere");
Ldb ldb = new Ldb();
LDBServiceSoap api = ldb.getLDBServiceSoap();
GetBoardRequestParams reqParams = new GetBoardRequestParams();
reqParams.setCrs("STA"); // Station Code
reqParams.setNumRows(10);
reqParams.setTimeOffset(-120);
StationBoardResponseType departures = api.getDepartureBoard(reqParams, token);
Though the answer from Rob Evans did not completely provide the solution, it did show me the right direction. I had to implement this in C# and below code worked for me.
AccessToken token = new AccessToken();
token.TokenValue = "xxx-xxx-xxx";
ldb client = new ldb();
client.AccessTokenValue = token;
StationBoard sb = client.GetDepartureBoard(10, "ABW", "", FilterType.to, 0, 120);

Categories

Resources