Skip to content

Authentication

Authentication is required to use T-API. Due to possible access restrictions for classic users, the concept of a technical user has been implemented. In order to create one, go to the API tab in the Pergamin. If you do not see the API tab in the system, please contact our support team.

API tab

API tab

Each technical user has three authentication methods available:

  • Advanced: Custom certificate

    Recommended for higher than basic use cases, when it is not possible to use Pergamin certificate.

Bearer token

The default and easiest to implement authentication method that is created automatically for each technical user is the Bearer token. This is the token that must be passed in the Authorization header every time the T-API is queried. The token is automatically generated when a technical user is created and is visible in the user's details. The token has an unlimited validity period, but can be reset at any time by the organization's administrator.

'Authorization': Bearer <token>

Warning

Once reset, the previous bearer token is no longer valid and a new one must be used.

Warning

The token is a secret and should be treated as such. It is recommended to store it in a secure place, e.g. in a password manager. You won't be able to see it again after closing the window.

Curl command example for 'Authorization' header
curl https://ext-api.pergam.in/ext-api/v2/documents \
   -H "Accept: application/json"
   -H "Authorization: Bearer {token}"

Pergamin certificate

A Pergam certificate is an X.509 certificate signed by Pergamin CA. To generate one, follow these steps:

  1. Generate private key using openssl command:
    openssl genrsa -out pkey.pem 4096
    
  2. Generate CSR (Certificate Signing Request):

    openssl req -new -key pkey.pem -out csr.csr -subj "/CN=[technical_user_id]/O=[organisation_id]"
    

    Note

    In place of [technical_user_id] you should put the ID of the technical user, and in place of [organisation_id] the ID of the organization to which the technical user belongs.

  3. Click Pergamin certificate in the API tab near the technical user for which you want to generate the certificate and upload the CSR file generated in previous step.

    Upload CSR
    CSR uploading window

  4. Download the certificate (the certificate will be available for download only immediately after it is generated, it will not be possible to download it again).

    Download certificate
    Certificate download window

Now you can use the certificate to sign requests to the API using the procedure described in the Signing requests using certificate section.

Custom certificate

In case there is no possibility to use Pergamin certificate (e.g. for technical reasons), it is possible to upload your own certificate and sign requests to the T-API using it.

Warning

In this case, only the signature and certificate validity date will be validated.

To enable this authentication method, you must upload the certificate in PEM format by clicking Custom certificate next to the selected technical user.

Upload custom certificate

Custom certificate uploading window

Warning

Using your own certificate excludes the possibility of using the Pergamin certificate. At the same time, you can use only one of these authentication methods.

As in the case of the Pergamin certificate, you can now start using your private key and certificate to sign requests to the API using the procedure described in the Signing requests using certificate section.

Signing requests using certificate

Prerequisites

To authenticate using Certificate you must provide following headers:

Certificate
certificate encoded in base64 format. Certificate must be in PEM format. Certificate must be signed by Pergamin CA. Certificate must be valid at the time of request. Certificate must be valid for the technical user for which the request is made.
ClientId
certificate subject but represented as RFC4514 string.
Example of certificate subject
/CN=26/O=237
in RFC4514 is:
O=237,CN=26
Signature
HMAC signature generated for each request individually (If request signature is invalid, request will be rejected) is required as well. This header is not required only when requesting endpoints from section Certificates and Health. Generating signature will require adding more headers wich allow our API to resolve correctness of sent signature, which is described in next section.
Timestamp:
epoch timestamp. Requests which are delivered after 15 seconds are considered to be invalid. Allowed values is e.g. 1660060402.879557 (from Python) and 1660060402 (for PHP). Both of them are correct, only first part is taken into account.

Algorithm

  1. RequestKeySignature: Generate request key (64 bytes long) and generate signature using client private key (e.g. pkey.pem from Pergamin Certificate section) using SHA256 algorithm with PSS padding using MGF1+SHA256 algorithms, then encode as base64.
  2. Payload: Prepare request payload if any. Serialize to JSON then compress/encode using gzip and then encode to base64.
  3. PayloadDigest: Calculate payload digest. Use SHA256 algorithm on payload and then encode binary result to base64 as string.

    Note

    Set empty string if payload is empty

  4. Prepare headers array:

    Header Value Description
    SignatureVersion 2 Version of signature algorithm (always set to 2)
    SignatureMethod HmacSHA256 Signature algorithm (always set to RSASSA-PSS)
    ClientId ie. O=237,CN=26 Certificate subject in RFC4514 notation
    RequestKeySignature random (64 bytes length) Random signature key
    Timestamp ie. 1660060402.879557 Current timestamp in seconds (microseconds are also allowed)
    PayloadDigest sha256 hash of payload Empty string if payload is empty, otherwise value from step 3.
    Content-Type text/plain Content type of request payload
    Accept application/json Content type of response payload
  5. RequestHeaders: Sort this array by header name ascendingly and serialize to JSON.

  6. Create string to be signed: HTTPVerb + "\n" + RequestHeaders + "\n" + HTTPRequestURI where:

    * HTTPVerb is name of request method e.g POST (always in uppercase RFC2616)

    * RequestHeaders is a JSON dump generated in previous step

    * HTTPRequestURI is an request URI encoded according to RFC3986

    Example of encoded URI
    https://ext.pergam.in/ext-api/v2/t?id=2
    // ... encode URI
    https%3A%2F%2Fext.pergam.in%2Fext-api%2Fv2%2Ft%3Fid%3D2
    
  7. Prepare HMAC compliant RFC2104 with prepared string from previous step using SHA256 algorithm. Then encode to base64. Use resulting value as the value of Signature header.

  8. RequestKeyEncrypted: Encrypt request key using Pergamin's External API certificate public key, which you can retrieve using this API. For encryption use OAEP padding with MGF1 and SHA256 algorithms. Encrypted value encode to base 64.
  9. Append RequestKeyEncrypted and Certificate to request headers.
  10. Headers send within request should be as follows:

    • SignatureVersion
    • SignatureMethod
    • ClientId
    • RequestKeySignature
    • TimeStamp
    • PayloadDigest
    • Content-Type
    • Accept
    • Signature
    • RequestKeyEncrypted
    • Certificate

Pseudocode example

Example of signing request using certificate
# 1. Generate random request key and sign it with private key
bytes request_key = random(64)
private_key pkey = load_private_key('pkey.pem')
bytes request_key_signature = pkey.sign(
  bytes: request_key,
  padding: PSS(padding: MGF1, salt: PSS.MAX_LENGTH),
  hash: SHA256
)

# 2. Compress and encode payload data
bytes payload = gzip.compress(payload)
string payload = base64.encode(payload)

# 3. Calculate payload digest
bytes hash = sha256(payload)
string payload_digest = base64.encode(hash)

# 4. Build headers array
array headers = []
headers['SignatureMethod'] = 'HmacSHA256'
headers['SignatureVersion'] = '2'
headers['PayloadDigest'] = payload_digest
headers['TimeStamp'] = current_utc_timestamp()
headers['Content-type'] = 'text/plain'
headers['Accept'] = 'application/json'
headers['RequestKeySignature'] = request_key_signature
headers['ClientId'] = ''; // Depends on certificate subject \

# 5. Sort headers array by keys
array headers = array_sort_by_keys_asc(headers)

# 6. Create teext to be signed
string text_to_sign = request_method + '\n'
    + json.encode(headers) + '\n'
    + urlencode(request_uri)

# 7. Calculate HMAC signature
bytes hmac = hmac(text_to_sign, request_key, 'sha256')
string signature = base64.encode(hmac)
headers[Signature] = signature

# 8. Encrypt request key using Pergamin External API certificate public key
public_key pubkey = load_public_key('pergamin-ext-api-cert.pem')
bytes request_key_encrypted = pubkey.encrypt(
  bytes: request_key,
  padding: OAEP(padding: MGF1, algorithm: SHA256),
)
string request_key_encrypted = base64.encode(request_key_encrypted)

# 9. Appends RequestKeyEncrypted and Certificate to request headers
headers['RequestKeyEncrypted'] = request_key_encrypted
bytes certificate = load_certificate()
string certificate = base64.encode(certificate)
headers['Certificate'] = certificate

# 10. Send request
send_request(
    url: request_uri,
    payload: payload,
    headers: headers
)