How to send queryStringParameters with invokeApi command - javascript

The full path to the endpoint with the query string parameters is:
https://api.mydomain.com/getData?param_01=value_01&param_02=value_01
After importing the 'aws-api-gateway-client'
var apigClientFactory = require('aws-api-gateway-client').default;
I go ahead and configure the variables:
let url = 'https://api.mydomain.com'
let pathTemplate = '/getData?param_01=value_01&param_02=value_01';
let method = 'GET';
let params = '';
let additionalParams = '';
let body = '';
var client = apigClientFactory.newClient({
invokeUrl: url,
accessKey: 'my-accessKeyId',
secretKey: 'my-secretAccessKey',
sessionToken: 'my-sessionToken',
region: 'MY_AWS_REGION'
});
Next invoke endpoint with:
client
.invokeApi(params, pathTemplate, method, additionalParams, body)
.then(function(res) {
console.log("...res:", res);
})
.catch(function(err) {
console.log("...err:", err);
});
But it fails with the 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
Is there a way to send the queryStringParameters with invokeApi command?

let params = {};
let pathTemplate = '/getData';
let additionalParams = {
queryParams: {
param0: 'value0',
param1: 'value1'
}
};
aws-api-gateway-client - npm

Related

Interacting with Oauth1 API in cloudflare worker (Flickr)

I'm needing to interact with the Flickr api from a cloudflare worker, but it's turning out to be exceedingly tricky.
My initial idea was to reach for the oauth1.0a library, but unfortunately it requires being passed a synchronous signature function. This is an issue because I need to use WebCrypto on the worker and it only exposes an asynchronous API.
Are there any other libraries I can use? I've currently spent hours trying to manually craft the request but keep getting errors saying the signature is bad.
This is my current attempt using someone's fork of oauth1.0a that adds support for an async signature function. This currently results in an "invalid_signature" response:
import OAuth from 'oauth-1.0a';
const CALLBACK_URL = "https://localhost:3000/oauth/callback";
const encoder = new TextEncoder();
async function signData(baseString: string, keyString: string) {
return await crypto.subtle.importKey(
'raw',
encoder.encode(keyString),
{ name: 'HMAC', hash: 'SHA-1' },
false,
['sign']
).then(key => {
return crypto.subtle.sign(
"HMAC",
key,
encoder.encode(baseString)
);
}).then(signature => {
let b = new Uint8Array(signature);
// base64 digest
return btoa(String.fromCharCode(...b));
});
}
export async function getRequestToken(consumerKey: string, consumerSecret: string) {
const url = "https://www.flickr.com/services/oauth/request_token";
const token = {
key: consumerKey,
secret: consumerSecret
}
const oauth = new OAuth({
consumer: token,
signature_method: 'HMAC-SHA1',
// #ts-ignore
hash_function: signData,
});
const requestData = {
url,
method: 'GET',
data: {
oauth_callback: CALLBACK_URL
}
};
// #ts-ignore
const authorisedRequest = await oauth.authorizeAsync(requestData, token);
let params = new URLSearchParams();
for (let [key, value] of Object.entries(authorisedRequest)) {
params.append(key, value as string);
}
const response = await fetch(requestData.url + `?${params}`, {
method: requestData.method,
});
const body = await response.text();
const parsedBody = oauth.deParam(body);
return parsedBody;
}

Getting Cognito User and Group inside Amplify AWS API function

I used Amplify Cli to create the templated api 'amplify add api' with new lambda function and cognito authentication. This is the code generated in the index.js file of the lambda function:
/************************************
index.js
*************************************/
const awsServerlessExpress = require('aws-serverless-express');
const app = require('./app');
const server = awsServerlessExpress.createServer(app);
exports.handler = (event, context) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
awsServerlessExpress.proxy(server, event, context);
};
/************************************
HTTP put method for insert object in app.js
*************************************/
app.put(path, function(req, res) {
if (userIdPresent) {
req.body['userId'] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH;
} else {
// Get the unique ID given by cognito for this user, it is passed to lambda as part of a large string in event.requestContext.identity.cognitoAuthenticationProvider
let userSub = req.apiGateway.event.requestContext.identity.cognitoAuthenticationProvider.split(':CognitoSignIn:')[1];
let requestIp = req.apiGateway.event.requestContext.identity.sourceIp;
let userPoolId = process.env.AUTH_TDOCWEBAPP001_USERPOOLID;
let request = {
UserPoolId: userPoolId, // Set your cognito user pool id
AttributesToGet: [
'email',
'given_name',
'family_name',
],
Filter: 'sub = "' + userSub + '"',
Limit: 1
}
//let users = await cognitoClient.listUsers(request).promise(); //Doesn't work because await not allowed
let users = cognitoClient.listUsers(request);
console.log("got user in put:", users[0]);
// TODO: Get the group that the user belongs to with "cognito:grouops"?
// Set userId and sortKey
req.body['userId'] = users[0].sub;
req.body['sortKey'] = sortKeyValue;
req.body['updatedByIp'] = requestIp;
req.body['createdAt'] = new Date().toISOString(); //ISO 8601 suppored by DynamoDB
req.body['updatedAt'] = new Date().toISOString();
req.body['isDeleted'] = false;
}
let putItemParams = {
TableName: tableName,
Item: req.body
}
dynamodb.put(putItemParams, (err, data) => {
if(err) {
res.statusCode = 500;
res.json({error: err, url: req.url, body: req.body});
} else{
res.json({success: 'put call succeed!', url: req.url, data: data})
}
});
});
So right now, when I call the lambda via the API, i get users is undefined. I'm trying to get the user object and then the groups that it belongs. Not sure how to do it if the function doesn't allow async... Please help
I found it myself the solution.
let users = await cognitoClient.listUsers(request);
or
let users = cognitoClient.listUsers(request, function(err, data) {...});
I needed wait to get users from the Cognito.

Javascript: API call with Certs

I have to make API call using 'sync-request' node module using certs (.cert & .pem file) which are given to us. Whenever I am trying to make a call - it gives error message as - Unable to verify the first certificate.
I have tried using agentOptions or importing 'ssl-root-cas' node module. But it gives same above error. I am not sure if, I am passing values correctly or not.
let request = require('sync-request');
let crt_file = fs.readFileSync('someFilePath.cer', ascii);
let pem_file = fs.readFileSync('someFilePath.pem', ascii);
let apiUrl = 'http://localhost:8888/getDetails';
let agentOptions = {
maxCachedSessions: 0,
secureProtocol: 'TLSv1_2_method',
securityOptions: 'SSL_OP_NO_SSLv3',
ciphers: 'ALL',
key: crt_file,
cert: pem_file,
Passphrase: 'London1!'
}
let response = request('GET', apiUrl, agentOptions);
I want to get success response with use of certs. The above agentOptions is something which I googled and tried to include.
NOTE: I do not want to use NODE_TLS_REJECT_UNAUTHORIZED=0
With request node module being deprecated, got provides excellent approach. This works for me.
const got = require('got');
const crypto = require('crypto');
const OAuth = require('oauth-1.0a');
const oauth = OAuth({
consumer: {
key: process.env.CONSUMER_KEY,
secret: process.env.CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});
const token = {
key: process.env.ACCESS_TOKEN,
secret: process.env.ACCESS_TOKEN_SECRET
};
const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
got(url, {
headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
responseType: 'json'
});

Apple IAP Receipt Validation Node.js

I'm trying to use Node.js from here for my IAP Receipt Validation, but it always returns error on a server's log: "The data in the receipt-data property was malformed."
Can someone help me to properly send base64 string to Node.js and to decode it there as same base64 string for receipt validation? I have zero experience with javascript and been trying to make this simple code work for two days now, to no avail.
Here is my Swift code:
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
let receiptString = receiptData.base64EncodedString(options: [])
var request = URLRequest(url: URL(string: "https://us-central1-calendizer-6a849.cloudfunctions.net/receiptValidation")!)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
// attach receipt data to a request
request.httpBody = receiptString.data(using: .utf8)
print("httpBody: \(request.httpBody?.base64EncodedString())")
Logs.log("✉️ Receipt Validation -> sending request ...")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
...
}
Here is my Node.js code (Firebase Cloud Functions):
const functions = require('firebase-functions');
var iap = require('in-app-purchase');
exports.receiptValidation = functions.https.onRequest((request, response) => {
var receipt_try1 = request.body
var receipt_try2 = request.body.toString('base64');
var receipt_try3 = JSON.stringify(receipt);
var receipt_try4 = new Buffer(request.body.toString(), 'base64')
console.log("receipt: " + receipt_try1)
iap.config({
applePassword: 'my shared key',
test: true
});
iap.setup(function (error) {
if (error) {
console.log("Setup error:" + error) // Failed to validate
}
iap.validate(iap.APPLE, receipt_try1, function (error, appleResponse) {
if (error)
{
console.log("Validation error:" + error) // Failed to validate
}
if (iap.isValidated(appleResponse)) {
console.log("successful validation" + appleResponse)
response.send(appleResponse)
}
});
});
});
did it using json:
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
let receiptBase64String = receiptData.base64EncodedString(options: [])
//.replacingOccurrences(of: "+", with: "%2B")
// prepare json data
let json: [String: Any] = ["receipt_string": receiptBase64String]
let jsonData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
// create post request
var request = URLRequest(url: URL(string: "https://us-central1-calendizer-6a849.cloudfunctions.net/receiptValidation")!)
//request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = jsonData
and in Node.js simply:
var receipt = request.body.receipt_string

Retrieving photo from Azure using Graph API

I'm trying to retrieve a profile picture from the Microsoft Azure API. The code below shows how.
private getProfilePicture(bearerToken: string, tenantId: string): void {
let command = CommandHelper.createRestBlobCommand([
{ name: 'https://graph.microsoft.com/beta'},
{ name: 'me/photo/$value' }
]);
command.Headers.push({ name: 'Authorization', value: 'bearer ' + bearerToken });
// load the photo from graph api.
this._gateway.send(command).subscribe(result => {
let info = result.payload;
var Base64 = require('js-base64').Base64;
var temp = 'data:image/bmp;base64,' + Base64.encode('info');
console.log(temp);
let action = actions.AuthenticationActions.photoLoaded(info);
this._store.dispatch(action);
});
}
The problem however is, that when I look at the output it returns :
data:image/bmp;base64,W29iamVjdCBCbG9iXQ==
Which translates to [object Blob].
My question is how to get the image object here?
with PHP is much simple in nodejs you have to put this to the function who return req as param and do it like this :
app.get('/...', function(req, res){ ...
var base64Data = req.rawBody.replace(/^data:image\/bmp;base64,/, "");
require("fs").writeFile("out.bmp", base64Data, 'base64', function(err) {
console.log(err);
});

Categories