templates/Doc/Webhook/signatures.html.twig line 1

Open in your IDE?
  1. {% extends 'Layouts/Doc/default.html.twig' %}
  2. {% block title %}{{ 'app.documentation.menu.webhook.signatures'|trans }}{% endblock %}
  3. {% block headerPageTitle %}WEBHOOK {{ 'app.documentation.menu.webhook.signatures'|trans|upper }}{% endblock %}
  4. {% block body %}
  5.     <div class="card">
  6.         <div class="card-body flex-column p-5">
  7.             <div class="d-flex align-items-center h-lg-200px p-5 p-lg-15">
  8.                 <div class="row">
  9.                     <div class="col-md-12 pt-5 scroll-y">
  10.                         <h1 class="fw-bold fs-4 fs-lg-1 text-gray-800 mb-3">Check the webhook signatures</h1>
  11.                         <div class="position-relative w-100 text-gray-800">
  12.                             <p><strong>Verify the events that Popina Order sends to your webhook endpoints.</strong></p>
  13.                             <p><strong>Popina Order</strong> can optionally <strong>sign the webhook events</strong> it sends to your endpoints by including a <strong>signature</strong> in each event’s <strong>Popina Order-Signature</strong> header. This allows you to verify that the events were sent by <strong>Popina Order</strong>, not by a <strong>third party</strong>. You can <strong>verify signatures manually</strong> using your own solution.</p>
  14.                             <p>Before you can verify <strong>signatures</strong>, you need to retrieve your <strong>endpoint’s secret</strong> from <strong>Popina Order support team</strong>.</p>
  15.                             <p><strong>Popina Order</strong> generates a <strong>unique secret key</strong> for each endpoint. If you use the same endpoint for both <strong>staging</strong> and </strong>production</strong>, note that the secret is different for each one. After this setup, <strong>Popina Order</strong> starts to <strong>sign each webhook</strong> it sends to the endpoint.</p>
  16.                         </div>
  17.                     </div>
  18.                 </div>
  19.             </div>
  20.             <div class="d-flex align-items-center p-lg-15">
  21.                 <div class="row">
  22.                     <div class="col-md-12 scroll-y">
  23.                         <h1 class="fw-bold fs-4 fs-lg-1 text-gray-800 mb-3">Preventing replay attacks</h1>
  24.                         <p>A <strong>replay attack</strong> is when an <strong>attacker intercepts a valid payload and its signature</strong>, then re-transmits them. To <strong>mitigate such attacks</strong>, <strong>Popina Order</strong> includes a <strong>timestamp</strong> in the <strong>Popina-Order-Signature</strong> header. Because this timestamp is part of the signed payload, it is also verified by the <strong>signature</strong>, so an attacker can’t <strong>change the timestamp without invalidating the signature</strong>. If the signature is valid but the timestamp is too old, you can have your application reject the payload.</p>
  25.                         <p><strong>Popina Order</strong> generates the timestamp and signature each time we send an event to your endpoint. If <strong>Popina Order</strong> retries an event (for example, your endpoint previously replied with a non-2xx status code), then we generate a <strong>new signature and timestamp for the new delivery attempt</strong>.</p>
  26.                         <h1 class="fw-bold fs-4 fs-lg-1 text-gray-800 mb-3 mt-10">Verifying signatures</h1>
  27.                         <p>The <strong>Popina-Order-Signature</strong> header included in each signed event contains a timestamp and one signature. The <strong>timestamp</strong> is prefixed by <code>t=</code>, and the <strong>signature</strong> is prefixed by <code>s=</code>.</p>
  28.                         <div class="highlight text-gray-700">
  29.                             <div class="highlight-code">
  30.                                 <pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token attr-value"><span></span><span class="token punctuation">Popina-Order-Signature:</span></span><br><span class="token attr-value"><span class="token punctuation">t=</span></span>1492774577,<br><span class="token attr-value"><span class="token punctuation">s=</span></span>5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd</span></code></pre>
  31.                             </div>
  32.                         </div>
  33.                         <div class="p-5 mt-4 bg-light mt-10 mb-5">
  34.                             <p>Note<br> Note that newlines have been added for clarity, but a real <strong>Popina-Order-Signature</strong> header is on a single line.</p>
  35.                         </div>
  36.                         <p><strong>Popina Order</strong> generates signatures using a <strong>hash-based</strong> message authentication code (<strong>HMAC</strong>) with </strong>SHA-256</strong>.<p/>
  37.                         <h2 class="fs-3 mt-10">Step 1: Extract the timestamp and signatures from the header</h2>
  38.                         <p>Split the header, using the <code>,</code> character as the separator, to get a list of elements. Then split each element, using the <code>=</code> character as the separator, to get a <strong>prefix</strong> and <strong>value</strong> pair.</p>
  39.                         <p>The value for the prefix <code>t</code> corresponds to the <strong>timestamp</strong>, and <code>s</code> corresponds to the <strong>signature</strong>. You can discard all other elements.</p>
  40.                         <h2 class="fs-3 mt-10">Step 2: Prepare the <code>signed_payload</code> string</h2>
  41.                         <p>The signed_payload string is created by concatenating:</p>
  42.                         <ul>
  43.                             <li>The timestamp (as a string)</li>
  44.                             <li>The character <code>.</code></li>
  45.                             <li>The actual JSON payload (that is, the request body)</li>
  46.                         </ul>
  47.                         <h2 class="fs-3 mt-10">Step 3: Determine the expected signature</h2>
  48.                         <p>Compute an <strong>HMAC</strong> with the <strong>SHA256</strong> hash function. Use the endpoint’s <strong>signing secret</strong> as the key, and use the <code>signed_payload</code> string as the message.</p>
  49.                         <h2 class="fs-3 mt-10">Step 4: Compare the signatures</h2>
  50.                         <p>Compare the signature in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.</p>
  51.                     </div>
  52.                 </div>
  53.             </div>
  54.         </div>
  55.     </div>
  56. {% endblock %}
  57. {% block stylesheets %}
  58.     <link href="{{ asset('metronic/v8.1.5/plugins/custom/prismjs/prismjs.bundle.css') }}" rel="stylesheet" type="text/css" />
  59. {% endblock %}