A server I need to integrate with returns its answers encoded as a JWT. Worse, the response body actually is a json, of the form:
{d: token} with token = JWT.encode({id: 123, field: "John", etc.})
I'd like to use a pact verification on the content of the decoded token. I know I can easily have a pact verifying that I get back a {d: string}, I can't do an exact match on the string (as the JWT contains some varying IDs). What I want is the following, which presumes the addition of a new Pact.JWT functionality.
my_provider.
upon_receiving('my request')
.with(method: :post,
path: '/order',
headers: {'Content-Type' => 'application/json'}
).will_respond_with(
status: 200,
headers: {'Content-Type' => 'application/json; charset=utf-8'},
body: {
d: Pact::JWT( {
id: Pact.like(123),
field: Pact.term(generate: "John", matcher: /J.*/
},signing_key,algo
)
})
Short of adding this Pact::JWT, is there a way to achive this kind of result?
I am already using the pact proxy to run my verification. I know you can modify the request before sending it for verification (How do I verify pacts against an API that requires an auth token?). Can you modify the request once you receive it from the proxy server?
If that's the case, I can plan for the following work around:
a switch in my actual code to sometimes expect the answers decoded instead of in the JWT
run my tests once with the swich off (normal code behaviour, mocks returns JWT data encoded.
run my tests a second time with the swich off (code expect data already decoded, mocks return decoded data.)
use the contract json from this second run
hook into the proxy:verify task to decode the JWT on the fly, and use the existing pact mechanisms for verification. (Step that I do not know how to do).
My code is in ruby. I do not have access to the provider.
Any suggestions appreciated! Thanks
You can modify the request or response by using (another) proxy app.
class ProxyApp
def initialize real_provider_app
#real_provider_app = real_provider_app
end
def call env
response = #real_provider_app.call(env)
# modify response here
response
end
end
Pact.service_provider "My Service Provider" do
app { ProxyApp.new(RealApp) }
end
Pact as a tool, I don't expect it to give this behavior out of the box.
In my opinion, the best is,
Do not change source code only for tests
Make sure your tests verifies encoded json only (generate encoded expected json in test & verify that with actual)
Related
Can you tell me if the following flow is good practice for retrieving encryption key?
So I have an Angular app which has custom encryption service created by me and a npm library, which now uses simple string value for key.
I also store access token inside a cookie and the value is encrypted.
Is it good practice, while executing a standard CRUD operation method against my API, first in this method to execute a separate http get request to get the encryption key from the API (from a separate endpoint), then de-crypt the cookie and THEN send it in the http request?
For example, look at this pseudo-code:
getAllProductsAsAdmin(): Observable<any>{
let encryptionKey = callApiAndGetKeyMethod(this.encryptionKeyApiUrl);
let decryptedCookie = decryptCookie(this.existingCookie, encryptionKey);
this.headers = this.headers.set('Authorization', decryptedCookie);
return this.httpClient.get<IGetProductAdminModel[]>(this.getAllProductsAsAdminUrl, {headers: this.headers})
.pipe(
tap(data => console.log('All:',JSON.stringify(data))),
catchError(this.handleError)
);
I am using fulcrum to collect data. fulcrum has a webhook feature
I have created a firebase function and linked the firebase function to fulcrums webhook feature with the functions URL. https://us-central1-example.cloudfunctions.net/fulcrumHook
Here is my existing function.
exports.fulcrumHook = functions.https.onRequest((request, response) => {
console.log(response.data.form_id)
response.send(200)
})
Through hours of debugging, in the logs I can see that the data I want is coming through but I am struggling to access it in the function itself.
When I log the request I get IncomingMessage { _readableState: ReadableState { objectMode: false,.....
When I log the response I get ServerResponse { domain: null, _events: [Object: null prototype] { finish: [ [.... as well as the body much further down with the actual data i need in it.
I have search for all the keywords i can think of about how to handle this data but I am completely stumped.
Do I need to handle the response like a promise with response.then(data => ...stuff)
Do I need to establish a connection like a socket with response.on('data', (data) => ...stuff)
Everything you need is in the documentation for HTTP triggers.
The request and response are essentially Express Request and Response objects.
Used as arguments for onRequest(), the Request object gives you access to the properties of the HTTP request sent by the client, and the Response object gives you a way to send a response back to the client.
You can click through to those linked APIs to understand in detail how they work.
Data passed to the function can be found by reading values from the request. If it's a POST request, form values are read like this:
request.body.form_id
The response is sent using response.send(). Just pass it an object that will get automatically serialized as JSON. Or use the linked API for the response object from above to learn more about your options.
I'm sorry in advance if something bring you here and I talk about a platform that's not really well-known over the world despite featuring a well-known person dancing in their commercial.
It's Shopee Open Platform API I talk about. I was trying to follow very properly their instruction here.
https://open.shopee.com/documents?module=63&type=2&id=51
But stuck instantly at step 5 : Shop Authorization. First, I've been given a test partner id, a test key, and I need to set manually the test redirect URL. I have to generate authorization token from all given information. Firstly I need to create a token base string by concatenating the test key with URI component encoded string of the URL. It turns into something like this.
9b754aca01a5d719cb70c5778294dae6ff90fcc68c82908ee480a36ff901d181https%3A%2F%2Fwww.unwelldocumented.com
To generate the authorization token, it says I need to do hexencode(sha256(token_base_string)). It returned a very long integer.
32373935663639356636346266303137613465396239383361373334646133656530313333393762636138396364663037366566313366313436316534303761
So I just assumed everything is fine and that is the authorization token. But when I send this...
https://partner.uat.shopeemobile.com/api/v1/shop/auth_partner?id=(test_partner_id)&token=(authorization_token)&redirect=(test_redirect_URL)
... suddenly I get this
{
"error": "error_auth",
"msg": "Invalid token",
"request_id": "30a4b6b0074541bdd88260a33f155ca6"
}
In order to solve this, you have to understand that SHA256 is an Encryption hash function. Please research more on SHA256 on your specific language.
For this very specific case, your SHA256 token should be as below.
Before SHA256:
9b754aca01a5d719cb70c5778294dae6ff90fcc68c82908ee480a36ff901d181https%3A%2F%2Fwww.unwelldocumented.com
After SHA256:
2795f695f64bf017a4e9b983a734da3ee013397bca89cdf076ef13f1461e407a
The rest of your steps seems correct.
I have been trying to get push notifications working using firebase. So far I have got as far as successfully sending an empty message "tickle". The problem is adding the message payload seems to have no affect on what the client receives. That is the service worker just sees it as another empty message.
I started by going through googles guide here - https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications
After going through how to send an empty message it says the message payload must be encrypted and suggests using an existing library to do it. To quote - "As with anything related to encryption, it's usually easier to use an actively maintained library than to write your own code".
I tried to use web-push-php which is one of the libraries recommended by googles guide. After having trouble with that i discovered web-php-push doesn't actually support firebase.
Looking on here i find examples that look really simple and don't event encrypt the message payload. It is simply sent in plain json. Doing this has no affect and the receiving end still thinks it's an empty message. See my code below.
I am at a complete loss with this and i'm confused why googles guide says the message data must be encrypted but there are countless examples on SO where it is just send in plain json text.
This is what i am posting from my server to the end point.
POST https://fcm.googleapis.com/fcm/send Authorization: key=[my server
key] Content-Type: application/json {"priority":10,"to":"[subscriber
id]","notification":{"body":"test body","title":"test title"}}
Here is my event listener in my service-worker.js
self.addEventListener('push', function(e) {
var body;
if (e.data) {
body = e.data.text();
} else {
body = "No message "+JSON.stringify(e);
}
var options = {
body: body
};
e.waitUntil(
self.registration.showNotification('Launtel Residential', options)
);
});
When i run the post request above the push notification occurs and triggers the service worker 'push' event as expected but no message data is present. e.data returns null. The 'e' object always just contains a flag set to true. e.isTrusted==true
Can someone explain how do I compute a HMAC
===============
To verify that the request came from Shopify, compute the HMAC digest according to the following algorithm and compare it to the value in the X-Shopify-Hmac-SHA256 header. If they match, you can be sure that the Webhook was sent from Shopify and the data has not been compromised.
Each Webhook request includes a X-Shopify-Hmac-SHA256 header which is generated using the app's shared secret, along with the data sent in the request.
I have the secret key... how can I combine the secret key + the data in the request to generate a HMAC
The easiest way is to use the ShopifySharp Library. You can use the Nuget package and install it in your project.
This is an example taken from the ShopifySharp website for validating webhooks:
NameValueCollection requestHeaders = Request.Headers;
Stream inputStream = Request.InputStream;
if(AuthorizationService.IsAuthenticWebhook(requestHeaders, inputStream, shopifySecretKey))
{
//Webhook is authentic.
}
else
{
//Webhook is not authentic and should not be acted on.
}
If you don't want to use ShopifySharp, you can see how they implemented it in the source code.