I cannot successfully generate a signature for making AWS Requests using PAW.
Here is a link to the signature I am attempting to generate: http://docs.aws.amazon.com/AWSECommerceService/latest/DG/HMACSignatures.html#HMACAuth_ItemsRequired
I have already searched other StackOverflow posts such as: Paw rest client : how to compute HMAC-SHA256 using absolute url as input
To answer your precise question about HMAC-SHA256 signatures, here's a code snippet that will work to compute this specific type of signature, returning the result Base 64 encoded in Paw (it uses the HMAC Dynamic Value programmatically):
function signHmac256(input, key) {
var dv = DynamicValue("com.luckymarmot.HMACDynamicValue", {
input: input,
key: key,
algorithm: 3 /* = SHA256 */,
uppercase: false /* keep hashes lowercase */,
encoding: 'Base64' /* encode hash data in base 64 */,
});
return dv.getEvaluatedString();
}
Otherwise, about the AWS Product Advertising API, we've made a dynamic value for it just today (which is a good opportunity for use to showcase the extension API), see AWS Product Advertising API Auth for Paw and the GitHub Repository here.
To use this dynamic value, first install it through the link shared above, then you can set up all other parameters and then enter a Signature parameter, and set this dynamic value as its value:
Open the token to enter your AWS Secret Key (used in the HMAC signature):
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 creating symmetrically signed Tokens with HMAC + SHA-256. As expected the header looks like this:
{
"alg": "HS256",
"typ": "JWT"
}
But when I encrypt the token with the AES_128_CBC_HMAC_SHA_256, the header changed to this:
{
"alg": "A128KW",
"enc": "A128CBC-HS256",
"typ": "JWT"
}
The "enc" parameter looks like expected, but why does the "alg" parameter change when encrypted?
From what I understand about encrypting JWTs:
The payload is signed (or symmetrically encrypted) and appended to the token;
payload + signature are encrypted with the algorithm specified in "enc" if applicable.
This does not appear to apply though. How would a potential recipient know that the decrypted token was signed with HMAC + SHA-256 now?
Isn't signing and encrypting done in this manner? I also noted that the distinct "." separating the signature and the payload is still present in the encrypted token, which seems odd considering the whole content should be encrypted as one (excluding the header).
I am using Microsoft.IdentityModel to generate the tokens if that matters.
The "enc" parameter looks like expected, but why does the "alg" parameter change when encrypted?
The header claim alg has different meanings when used in a JWS (signed token) and JWE (encrypted token).
With JWS (extract from the RFC7515 section 4.1.1)
The "alg" (algorithm) Header Parameter identifies the cryptographic
algorithm used to secure the JWS.
With JWE (extract from the RFC7516 section 4.1.1)
This parameter has the same meaning, syntax, and processing rules as
the "alg" Header Parameter defined in Section 4.1.1 of [JWS], except
that the Header Parameter identifies the cryptographic algorithm used
to encrypt or determine the value of the CEK.
About you assumption
From what I understand about encrypting JWTs:
* The payload is signed (or symmetrically encrypted) and appended to the token;
* payload + signature are encrypted with the algorithm specified in "enc" if applicable.
This is not correct. With JWE, the payload is not digitally signed by the issuer.
If you need both encryption and signature, you will have to issue a JWS (e.g. with {"alg":"HS256","typ":"JWT"}).
This JWS will be encrypted (e.g. with {"alg": "A128KW","enc": "A128CBC-HS256","typ": "JWT"}
I also noted that the distinct "." separating the signature and the payload is still present in the encrypted token
THe difference between JWS and JWE is that the number of . is not the same:
2 . for JWS
4 . for JWE
Disctinction between the 2 token types is detailed in the RFC7516 section 9
What I'm doing now:
Using the JavaScript API to render the button on my web page.
When the Sign in with Google flow is complete, my client-side JavaScript callback is called.
That callback sends the given .credentials string to my server.
The backend server (Node.js) calls the google-auth-library library's OAuth2Client.verifyIdtoken method on the .credentials string, which returns the user's email address (among other things), which my server uses to verify the user and create a session.
Everything works, but I'm wondering if there are any security concerns I'm missing. In particular there's a nonce field. The docs (link) don't explain how to use it.
Note: I'm using "Sign in with Google" and not the deprecated "Google Sign-In".
Edit: I'm familiar with the concept of nonces and have used them when doing the OAuth 2 server-side flow myself. What I can't figure out is how the Sign in with Google SDK expects me to use its nonce parameter with the flow above, where I'm using both their client-side and server-side SDKs.
Nonces are used as a CSRF-prevention method. When you make a request to Google, you include a nonce, and when authentication is complete, Google will send the same nonce back. The magic in this method is that if the nonce does not match what you sent then you can ignore the response, because it was probably spoofed.
Read more about CSRF here: https://owasp.org/www-community/attacks/csrf
Nonces are usually crytographically secure random strings/bytes.
I use crypto-random-string as a base to generate nonces, but any package with this functionality should suffice.
Sometimes I store nonces with a TTL in Redis, but other times I store nonces with an ID attached to the request so I can later verify it.
I'm telling you this since it took a bit long for me to figure out this nonce stuff :P
Using the example from Google's website (https://developers.google.com/identity/one-tap/android/idtoken-auth), I added the code for the nonce:
const nonce = '...'; // Supplied by client in addition to token
const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client(CLIENT_ID);
async function verify() {
const ticket = await client.verifyIdToken({
idToken: token,
audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
});
const payload = ticket.getPayload();
const serverNonce = payload['nonce'];
if (nonce != serverNonce) {
// Return an error
}
const userid = payload['sub'];
// If request specified a G Suite domain:
// const domain = payload['hd'];
}
verify().catch(console.error);
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.
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.