Trying to generate a OAuth1 Authorization header value for Magento GET http request

I am using the n8n cloud version and I am trying to generate a OAuth1 Authorization header value with the help of a Javascript Code node. Here is my code:

const crypto = require('crypto');
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = ((length) => {
  let text = ""
  const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  for (let i = 0; i < length; i ++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
})(11)
  
// Your OAuth1 credentials
const consumerKey = 'XXX';
const accessToken = 'XXX';
const consumerSecret = 'XXX';
const accessTokenSecret = 'XXX';

// OAuth1 parameters
const oauthParams = {
  oauth_consumer_key: consumerKey,
  oauth_token: accessToken,
  oauth_signature_method: 'HMAC-SHA256',
  oauth_timestamp: timestamp,
  oauth_nonce: nonce,
  oauth_version: '1.0',
};

// Construct the URL and HTTP method
const baseUrl = 'https://our_url.net/rest/V1/customers/search';
const httpMethod = 'GET';

// Construct the parameter string
const parameterString = Object.keys(oauthParams)
  .sort()
  .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(oauthParams[key])}`)
  .join('&');

// Construct the signature base string
const signatureBaseString = `${httpMethod}&${encodeURIComponent(baseUrl)}&${encodeURIComponent(parameterString)}`;

// Calculate the signing key
const signingKey = `${encodeURIComponent(consumerSecret)}&${encodeURIComponent(accessTokenSecret)}`;

// Calculate the HMAC-SHA256 signature
const hmac = crypto.createHmac('sha256', signingKey);
hmac.update(signatureBaseString);
const signature = hmac.digest('base64');

// Add the signature to the OAuth parameters
oauthParams.oauth_signature = encodeURIComponent(signature);

// Construct the OAuth header manually
const headerParts = [];
for (const key in oauthParams) {
  headerParts.push(
    `${key}="${oauthParams[key].replace(/"/g, '\\"')}"`
  );
}

const header = `OAuth ${headerParts.join(',')}`;

return {
  authenticationHeader: header,
  oauth_timestamp: timestamp,
  oauth_nonce: nonce,
};

The JSON output looks like this:

{
"authenticationHeader": "OAuth oauth_consumer_key="XXX",oauth_token="XXX",oauth_signature_method="HMAC-SHA256",oauth_timestamp="1696608981",oauth_nonce="W4qBTg4FbmW",oauth_version="1.0",oauth_signature="PTRh6rY2r1gCUiusmOFdeB2DLsHHtwfYCAEXzQqGPyM%3D"",
"oauth_timestamp": "1696608981",
"oauth_nonce": "W4qBTg4FbmW"
}

What is the error message (if any)?

I get the following error message from the GET request:

{"status":"rejected","reason":{"message":"401 - \"{\\\"message\\\":\\\"The signature is invalid. Verify and try again.\\\"}\"","name":"Error","stack":"Error: 401 - \"{\\\"message\\\":\\\"The signature is invalid. Verify and try again.\\\"}\"\n    at createError (/usr/local/lib/node_modules/n8n/node_modules/axios/lib/core/createError.js:16:15)\n    at settle (/usr/local/lib/node_modules/n8n/node_modules/axios/lib/core/settle.js:17:12)\n    at RedirectableRequest.handleResponse (/usr/local/lib/node_modules/n8n/node_modules/axios/lib/adapters/http.js:238:9)\n    at RedirectableRequest.emit (node:events:526:35)\n    at RedirectableRequest.emit (node:domain:489:12)\n    at RedirectableRequest._processResponse (/usr/local/lib/node_modules/n8n/node_modules/follow-redirects/index.js:356:10)\n    at ClientRequest.RedirectableRequest._onNativeResponse (/usr/local/lib/node_modules/n8n/node_modules/follow-redirects/index.js:62:10)\n    at Object.onceWrapper (node:events:629:26)\n    at ClientRequest.emit (node:events:526:35)\n    at ClientRequest.emit (node:domain:489:12)\n    at HTTPParser.parserOnIncomingClient (node:_http_client:700:27)\n    at HTTPParser.parserOnHeadersComplete (node:_http_common:119:17)\n    at TLSSocket.socketOnData (node:_http_client:541:22)\n    at TLSSocket.emit (node:events:514:28)\n    at TLSSocket.emit (node:domain:489:12)\n    at addChunk (node:internal/streams/readable:324:12)\n    at readableAddChunk (node:internal/streams/readable:297:9)\n    at TLSSocket.Readable.push (node:internal/streams/readable:234:10)\n    at TLSWrap.onStreamRead (node:internal/stream_base_commons:190:23)\n    at TLSWrap.callbackTrampoline (node:internal/async_hooks:130:17)"}}

Please share your workflow

Information on your n8n setup

  • n8n version: cloud

What am I doing wrong?

Hi @dkarpov, welcome to the community!

This error is being thrown by the receiving server, so I am not quite sure what exactly is causing the problem here. You might need to check with the recipient how exactly your request (or the signature) should look like.

Are you also having trouble when using n8n’s built-in OAuth1 credentials instead?

Hello @MutedJam,

thanks for the reply. I was finally able to generate the correct OAuth1 Authorization header value by using a code node, but it’s very complicated for what it achieves. I would like to be able to use the OAuth1 node like you suggested. I have access to my consumer key, consumer secret, access token and access token secret, where can I use this to create OAuth1 credentials instead?

Thanks,
Daniil

1 Like

Hi @dkarpov, you can find these options through the HTTP Request node by selecting Generic Credential Type in the Authentication field, then OAuth1 API in the Generic Auth Type field:

You can then configure your OAuth1 details as needed:

3 Likes

Thank you for your help @MutedJam . Yes, we tried this already, but we didn’t have all the necessary URLs from our client to get it to connect. This is definitely the simpler way to do it but in the meantime, we will continue using our custom code node to generate the Authorization header.

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.