Sample code for 30+ languages & platforms
React Native Requires Chilkat v11.0.0+

ebay: Add Digital Signature to HTTP Request

See more eBay Examples

Demonstrates how to add a digital signature to an ebay HTTP request.

Chilkat React Native Downloads

React Native
import { BinData, CkDateTime, EdDSA, Http, HttpResponse, PrivateKey, StringBuilder } from '@chilkat/react-native'

async function chilkatExample() {
  // This example requires the Chilkat API to have been previously unlocked.
  // See Global Unlock Sample for sample code.

  // Note: Ebay provides a Key Management API
  // See https://developer.ebay.com/api-docs/developer/key-management/overview.html

  // The following test keys can be used: 
  // 
  // Ed25519 
  // 
  // Private Key:
  // 
  // -----BEGIN PRIVATE KEY-----
  // MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikTmiCqirVv9mWG9qfSnF
  // -----END PRIVATE KEY-----

  const strPrivateKey = 'MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikTmiCqirVv9mWG9qfSnF';

  // Public Key:
  // 
  // -----BEGIN PUBLIC KEY-----
  // MCowBQYDK2VwAyEAJrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs=
  // -----END PUBLIC KEY-----

  const strPublicKey = 'MCowBQYDK2VwAyEAJrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs=';

  // This example assumes you got a JWE for your given private key from the Ebay Key Management REST API.
  // This JWE is just for example:
  const strJwe = 'eyJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIiwidGFnIjoiSXh2dVRMb0FLS0hlS0Zoa3BxQ05CUSIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiaFd3YjNoczk2QzEyOTNucCJ9.2o02pR9SoTF4g_5qRXZm6tF4H52TarilIAKxoVUqjd8.3qaF0KJN-rFHHm_P.AMUAe9PPduew09mANIZ-O_68CCuv6EIx096rm9WyLZnYz5N1WFDQ3jP0RBkbaOtQZHImMSPXIHVaB96RWshLuJsUgCKmTAwkPVCZv3zhLxZVxMXtPUuJ-ppVmPIv0NzznWCOU5Kvb9Xux7ZtnlvLXgwOFEix-BaWNomUAazbsrUCbrp514GIea3butbyxXLNi6R9TJUNh8V2uan-optT1MMyS7eMQnVGL5rYBULk.9K5ucUqAu0DqkkhgubsHHw';

  const sbBody = new StringBuilder();
  sbBody.append('{"hello": "world"}');

  console.log('Body of request:');
  console.log(sbBody.getAsString());

  // -------------------------------------------------
  // Build the signature base string...

  const sbSigBase = new StringBuilder();

  sbSigBase.append('"content-digest": sha-256=:');
  sbSigBase.append(sbBody.getHash('sha256', 'base64', 'utf-8'));
  sbSigBase.append(':\n');

  sbSigBase.append('"x-ebay-signature-key": ');
  sbSigBase.append(strJwe);
  sbSigBase.append('\n');

  sbSigBase.append('"@method": POST\n');

  // This is the path part of the URL without query params...
  sbSigBase.append('"@path": ');
  sbSigBase.append('/verifysignature');
  sbSigBase.append('\n');

  // The is the domain, such as "api.ebay.com" w/ port if the port is something unusual.
  // In this example, we're testing against a local docker test server (see the info at https://developer.ebay.com/develop/guides/digital-signatures-for-apis)
  // Normally, I think it would just be "api.ebay.com" instead of "localhost:8080".
  sbSigBase.append('"@authority": ');
  sbSigBase.append('localhost:8080');
  sbSigBase.append('\n');

  sbSigBase.append('"@signature-params": ');

  const sbSigInput = new StringBuilder();
  sbSigInput.append('("content-digest" "x-ebay-signature-key" "@method" "@path" "@authority")');
  sbSigInput.append(';created=');

  const dt = new CkDateTime();
  dt.setFromCurrentSystemTime();
  const unixTimeNow = dt.getAsUnixTimeStr(false);
  sbSigInput.append(unixTimeNow);

  sbSigBase.appendSb(sbSigInput);

  // -------------------------------------------------
  // Sign the signature base string using the Ed25519 private key

  const bdPrivKey = new BinData();
  bdPrivKey.appendEncoded(strPrivateKey, 'base64');

  const privKey = new PrivateKey();
  try {
    privKey.loadAnyFormat(bdPrivKey, '');
  } catch {
    console.log(privKey.lastErrorText);
    return;
  }

  const bdToBeSigned = new BinData();
  bdToBeSigned.appendSb(sbSigBase, 'utf-8');

  const eddsa = new EdDSA();
  let sigBase64: string;
  try {
    sigBase64 = eddsa.signBdENC(bdToBeSigned, 'base64', privKey);
  } catch {
    console.log(eddsa.lastErrorText);
    return;
  }

  console.log('sigBase64:');
  console.log(sigBase64);

  // ----------------------------------------------------------
  // Send the JSON POST

  const http = new Http();

  http.setRequestHeader('x-ebay-signature-key', strJwe);

  const sbContentDigestHdr = new StringBuilder();
  sbContentDigestHdr.append('sha-256=:');
  sbContentDigestHdr.append(sbBody.getHash('sha256', 'base64', 'utf-8'));
  sbContentDigestHdr.append(':');
  http.setRequestHeader('Content-Digest', sbContentDigestHdr.getAsString());

  const sbSigHdr = new StringBuilder();
  sbSigHdr.append('sig1=:');
  sbSigHdr.append(sigBase64);
  sbSigHdr.append(':');
  http.setRequestHeader('Signature', sbSigHdr.getAsString());

  sbSigInput.prepend('sig1=');
  http.setRequestHeader('Signature-Input', sbSigInput.getAsString());

  // Add this header to make eBay actually check the signature.
  http.setRequestHeader('x-ebay-enforce-signature', 'true');

  // Set the OAuth2 access token to add the "Authorization: Bearer <access_token>" to the header.
  http.authToken = 'your_oauth2_access_token';

  // The signature base string constructed above is valid if we send this POST to "http://localhost:8080/verifysignature"
  // Normally, you'll send your POST to some api.ebay.com endpoint.
  const url = 'http://localhost:8080/verifysignature';

  const jsonStr = sbBody.getAsString();
  const resp = new HttpResponse();
  try {
    await http.httpStrAsync('POST', 'http://localhost:8080/verifysignature', jsonStr, 'utf-8', 'application/json', resp);
  } catch {
    console.log(http.lastErrorText);
    return;
  }

  console.log(`Response status code: ${resp.statusCode}`);
  console.log('Response body:');
  console.log(resp.bodyStr);
}