Authentication of APIs and Webhooks

Overview

In this section, we will learn how to authenticate API calls that you'd make to Knit and how to check the authenticity of webhooks that Knit sends to your servers.

Authentication for APIs

When making calls to Knit, you'd need to pass certain headers so that we know that you have authorised the call . These headers are:

  • Authorization
    Pass your API_KEY in Authorization header with Bearer prefix, i.e., Authorization: Bearer API_KEY
  • X-Knit-Integration-Id
    Pass the integration id received in the UI Auth Component while doing an integration to uniquely identify the origin org at your end along with the application for which this integration was done, i.e., X-Knit-Integration-Id: integration-id

Authenticating Webhooks

When receiving POST requests from Knit, you'll want to ensure that the request is not from a malicious source and has not been altered in transit.

All incoming POST requests from Knit have anX-Knit-Signature key in the header, which is an encoded combination of your API_KEY and the payload of the request.

Using this key, calculate the HMAC-SHA256 of the payload and encode it to a Base 64 URL Safe encoding (without padding) to get the signature. Ensure that the signature matches the X-Knit-Signaturein the request headers to make sure that the request is authentic.

import org.apache.commons.codec.binary.Hex
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

val API_KEY = "Your API Key here"
val payload = request.body

val hMacSHA256 = Mac.getInstance("HmacSHA256")
val secretKey = SecretKeySpec(API_KEY..toByteArray(Charsets.UTF_8), "HmacSHA256")
hMacSHA256.init(secretKey)
val encoded = Base64
  .getUrlEncoder().withoutPadding()
  .encodeToString(hMacSHA256.doFinal(toSign.toByteArray(Charsets.UTF_8)))

val isRequestValid = encoded == request.headers["X-Knit-Signature"]

const base64url = require('base64url');
var crypto = require('crypto');

const key = "Your API Key here"

const encoded = base64url(crypto.createHmac("sha256", key).update(request.body).digest());

isRequestValid = encoded == request.headers["X-Knit-Signature"]

import base64
import hashlib
import hmac


def verify_webhook(data, hmac_header, apikey):
  digest = hmac.new(apikey.encode('utf-8'),
                    data.encode('utf-8'),
                    digestmod=hashlib.sha256).digest()

  computed_hmac = base64.urlsafe_b64encode(digest).rstrip(b"=")

  return hmac.compare_digest(computed_hmac, hmac_header.encode('utf-8'))