Follow

Webhooks for SSL events

Webhook terminology

An event is a certificate change, such as a certificate being requested, issued, or failing validation. Each change has a corresponding Delivery object.

Webhook endpoints are URLs defined by users to which Openprovider sends deliveries. A single event may be sent to many webhook endpoints.

Webhooks refers to the overall concept of sending notifications to webhook endpoints.

 

Use webhooks to be notified about events that happen with certificates in Openprovider. Some events, like pre-validation result or issuance of the certificate are not the result of a direct API request, so it could be a problem to keep track of the current state of certificates.

Webhooks solve these problems by letting you register a URL to which we will send notifications anytime an event happens with a certificate under your account. When an event occurs - for example, when a certificate is issued, Openprovider generates a Delivery object. This object contains all the relevant information about what just happened, including the type of event and the data associated with it. Openprovider then sends the Delivery object to any URLs in your account's webhooks settings via an HTTP POST request. You can find a full list of all event types below.

Configuring your webhook settings

Webhooks are configured in the Webhook settings section in SSL Panel. Clicking Add endpoint reveals a form to add setting for new subscription. To configure it you should specify:

  • URL where to deliver events
  • Event type to be sent
  • Secret key that will be sent with delivery

You can configure as many subscriptions as you want.

webhookSettings.png

Common webhook mistakes

The two most common mistakes with webhooks are providing the wrong URL in the dashboard or the webhook endpoint not returning a 2xx status code. To test against these cases there is an option to send a test ping to each endpoint. Pings can be sent manually to verify functionality.

Events

  • ssl_panel.created - Occurs whenever a new certificate is created
  • ssl_panel.pre_validation.failed - Occurs whenever a validation fails.
  • ssl_panel.pre_validation.successful- Occurs when all validations have succeeded.
  • ssl_panel.requested - Occurs whenever a certificate is requested at the CA
  • ssl_panel.ca_chat.new_message_from_ca - Occurs whenever the CA has sent new message to the chat
  • ssl_panel.issued - Occurs whenever the CA has issued the certificate.
  • ssl_panel.will_expire_in_30_days - Occurs 30 days before the certificate expires
  • all events - *

Data format

A webhook will POST to the URL with all data available in the body. 

POST /payload HTTP/1.1
 
Host: localhost:4567
User-Agent: Tribuo/1.0
Content-Type: application/json
Content-Length: 6615
Version: "0.0.1" // Version of delivery structure
Signature: signature // HMAC hex digest of the payload, using the hook's secret as the key (if configured).
Delivery: b32f3ff1-d7a4-479e-b6ae-1857533caa39 // UUID of this delivery (for ability to check it later or store it).
Entity-Id: 192356 // Entity id in application (if specified, for example order id)
Event: ssl.created
  
{
  // Available metadata
  "metadata": {
    "version": "0.0.1",
    "signature": "signature",
    "delivery": "b32f3ff1-d7a4-479e-b6ae-1857533caa39",
    "event": "ssl.created",
    "entityId": 192356
  },
  "data": {
    // JSON payload from application.
    // Payloads can be completely different from application to application. That logic must be aligned before usage of this service.
  }
}

Structure of delivery details and status mapping:

Rules for status mapping

Openprovider API status status certificate.status certificate.operation
PAI open open none
ACT open active none
  open replaced none
FAI closed rejected none
  closed revoked none
  closed open none
EXP closed expired none
REJ open requested

delete

cancel

  open active, replaced

delete

cancel

REQ

open

requested

request
  open requested reissue
  open requested renew

Event ssl_panel.pre_validation.failed, ssl_panel.pre_validation.successful

{
"metadata":
{
    "version":"1.0.0",
    "delivery":"18bb58bc-2731-4d12-adb7-ec1e4fcc0ac7",
    "event":"ssl_panel.created",
    "signature":"sha256=8aca68f56d115c765cf91c1f2d27a7ef7348b698f8eed80aa2a34056adfee690"
},
"data":
{
    "id": "3d8b6599-0794-4c92-b019-ee939395b42a",
     "status": "open",
     "certificate":
     {
        "id": "09a704cb-3598-4324-a56f-eaa792f72a23",
        "status": "open",
        "expireAt": null,
        "operation": "none",
        "commonName": "openprovider.nl",
        "activatedAt": null,
        "certificates":
        {
            "main": null,
            "root": null,
            "intermediate": null
        },
        "preValidationStatus": "failed",
        "preValidationResults":
        [
            {"name": "whois_validator", "status": "passed"},
            {"name": "kvk_validator", "status": "failed"},
            {"name": "phone_number_validator", "status": "passed"}
        ],
        "openproviderId": 123456
    }
}

Events ssl_panel.created, ssl_panel.requested, ssl_panel.issuedssl_panel.will_expire_in_30_days

{
"metadata":
    {
    "version":"1.0.0",
    "delivery":"18bb58bc-2731-4d12-adb7-ec1e4fcc0ac7",
    "event":"ssl_panel.created",
    "signature":"sha256=8aca68f56d115c765cf91c1f2d27a7ef7348b698f8eed80aa2a34056adfee690"
},
"data":
{
    "id": "38e792f4-90f4-4e37-93ac-0478d01f954c",
    "status": "open",
    "certificate":
    {
        "id": "2410c949-9600-46ac-9c53-62de72742859",
        "status": "open",
        "expireAt": null,
        "operation": "none",
        "commonName": "openprovider.nl",
        "activatedAt": null,
        "certificates":
        {
            "main": null,
            "root": null,
            "intermediate": null
        },
        "preValidationStatus": "passed"
    },
    "openproviderId": 123456
}
}

Event ssl_panel.ca_chat.new_message_from_ca

{
"metadata":
    {
    "version":"1.0.0",
    "delivery":"18bb58bc-2731-4d12-adb7-ec1e4fcc0ac7",
    "event":"ssl_panel.created",
    "signature":"sha256=8aca68f56d115c765cf91c1f2d27a7ef7348b698f8eed80aa2a34056adfee690"
},
"data":
{
    "date": "2017-12-08T10:51:40+0100",
    "message": "We try to get contact the organization via the public number +111111111 but we do not get anyone on the line. Can you indicate when we can reached the organization for the validation?",
    "orderId": "0111111-1640-41d4-9b69-71600031d266",
    "openproviderId": "111111"
}  
}

 

Receiving a webhook notification

Creating a webhoook endpoint on your server is no different from creating any page on your website. With PHP, you might create a new .php file on your server; with a framework like Laravel, you would add a new route with the desired URL.

Webhook data is sent as JSON in the POST request body. The full delivery details are included and can be used directly, after parsing the JSON into an Delivery object.

 

1
2
3
4
5
6
<?php
 
$body = file_get_contents('php://input'); // get request body
$delivery = json_decode($body, true) // decode delivery as array
 
// handle event

 

Responding to a webhook

To acknowledge receipt of a webhook, your endpoint should return a 2xx HTTP status code. Any other information returned in the request headers or request body is ignored. All response codes outside this range will indicate to Openprovider that you did not receive the webhook.

If a webhook is not successfully received for any reason, Openprovider will continue trying to send the webhook once an hour for up to 3 days.

Using and API call, you can get all deliveries that were not successfully delivered.

Verifying deliveries

As an extra security measure, you can verify a delivery before acting upon it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
 
// PHP 7.0+
 
$body = file_get_contents('php://input'); // get request body
[$algorithm, $senderHash] = explode('=', $_SERVER['HTTP_SIGNATURE']); // get signature that has been generated by sender
$knownHash = hash_hmac($algorithm, $body, 'secretPhrase');
 
// now we can check generated signature against our
if (hash_equals($knownHash, $senderHash)) {
    header('HTTP/1.0 403 Forbidden');
 
    echo 'You are forbidden!';
}
 
$delivery = json_decode($body, true) // decode delivery as array
 
// handle event

You can extract hash algorithm by splitting it with = (for example, we will send signature similar to this: sha256=8aca68f56d115c765cf91c1f2d27a7ef7348b698f8eed80aa2a34056adfee690, like GitHub does).

Right now we will support only sha256.

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.