Skip to content

Authentication Setup

All API access to the Digital Post Platform is authenticated using certificate-based machine-to-machine authentication and OAuth 2.0.

Before sending messages or accessing platform APIs, a system integration must be created and configured, and a valid access token must be obtained.

This section explains how to configure authentication and obtain credentials for API access.


Overview

Authentication is based on:

  • Client certificate authentication
  • JSON Web Tokens (JWT)
  • OAuth 2.0 token exchange

Each integrating system authenticates using a registered system integration and a client certificate.

The general process is:

  1. Generate the private key
  2. Generate the public certificate
  3. Create a System Integration
  4. Generate JWTs using the private key
  5. Exchange JWTs for access tokens

Create the private key file (private-key.pem)

Authentication is based on X.509 client certificates. For each system integration, the integrator must hold a private key that matches the registered public certificate. This private key is used locally by the integrating system to sign JWTs and must never be shared.

Generate a 2048-bit RSA private key in PEM format using OpenSSL:

<code >openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private-key.pem</code>

Result

  • private-key.pem — your private RSA key in PEM format.

Important notes

  • Store private-key.pem securely (preferably in a secret manager or HSM where available).
  • Limit file access (e.g., strict permissions) and ensure it is not committed to source control.
  • The private key must remain with the integrating system and must never be uploaded or distributed.

Generate the public certificate file (publickey.cer)

Each system integration must have one registered public certificate with a corresponding private key held by the integrator. The public certificate is uploaded in the Administration Portal so the platform can verify the JWT signatures created using your private key.

Generate a self-signed X.509 certificate (public certificate) in PEM format from your private key. Keep the validity at 365 days:

openssl req -new -x509 -key private-key.pem -out publickey.cer -days 365

Result

  • publickey.cer — your public X.509 certificate in PEM format (contains the public key).

Important notes

  • Upload publickey.cer to the Administration Portal when creating/configuring the system integration.
  • The certificate is used to verify the JWT signatures (the JWTs are signed with the private key; verification happens using the uploaded public certificate).
  • Plan certificate rotation before expiry (365 days) to avoid authentication interruptions.

Create a System Integration

A system integration represents the technical client that authenticates against the platform.

System integrations are created in the Administration Portal.

To create a system integration:

  1. Select an organisation
  2. Navigate to Distribution → System integration
  3. Click Add System integration
  4. Enter a name
  5. Upload a certificate
  6. Enter contact information
  7. Select permissions:
    • Send message
    • Retrieve billing data (if required)
  8. Set status to Active
  9. Click Save

Only active system integrations can authenticate.

Each system integration is assigned a unique:

  • machineId

This identifier is required for authentication.


Collect Required Identifiers

Before implementing authentication, the following identifiers must be collected from the Administration Portal.

Machine Identifier

machineId
Identifies the system integration.

Certificate Thumbprint

Certificate thumbprint
Used as the issuer value in JWTs.

These identifiers are required when creating JWTs and submitting API requests.


Machine Authentication

Create a JSON Web Token

Authentication requires creating a signed JWT in accordance with RFC 7519.

The JWT must be signed using RS256 and the private key registered with the system integration.

Required Claims

ClaimFull nameDescription
jtiJWT idUnique id for token e.g. GUID.
issIssuerThumbprint of client certificate used for signing the JWT.
subSubjectId of the System integration to request a token for (Machine id).
audAudienceURL of the Security Token Service requesting the token from, e.g. admin-test.digitalpost.dk.
expExpiration timeNumericDate (Epoch) specifying the time from which the token is valid. It must not be more than 5 minutes before Issued At.
nbfNot beforeNumericDate (Epoch) specifying the time from which the token is valid. It must not be more than 5 minutes before Issued At.
iatIssued atNumericDate (Epoch) specifying the time the token was issued.

Example Payload

{
  "jti": "56aec5e8-5895-45eb-8a2b-6afb65d9bf4s",
  "iss": "38d00f87072131f1444d779ca6c75219b102de50",
  "sub": "38",
  "aud": "admin.digitalpostbox.xxx",
  "iat": 1572382814,
  "exp": 1572382899,
  "nbf": 1572382814
}

The token lifetime must not exceed five minutes.


Example JWT Creation Flow

Pseudocode example:

now = getCurrentTime()
platformDomain = getPlatformDomain()

header = {
  alg: "RS256",
  typ: "JWT"
}

payload = {
  jti: generateUuid(),
  iss: getCertificateThumbprint(),
  sub: getMachineId(),
  aud: platformDomain,
  exp: now + 300,
  nbf: now,
  iat: now
}

encodedHeader = base64Url(header)
encodedPayload = base64Url(payload)

signingInput = encodedHeader + "." + encodedPayload

signature = sign(signingInput, privateKey)

token = signingInput + "." + signature

Exchange JWT for Access Token

Once a JWT has been created, it must be exchanged for an access token. To obtain an access token, the signed JWT must be sent to the platform Login Service token endpoint.

The JWT is submitted as a UTF-8 and Base64 encoded form parameter named token.
The OAuth grant type clientcertificate and client id clientcertificate must be used.
No client secret is required.

If authentication is successful, the Security Token Service issues an access token valid for approximately ten minutes.
This token must be included as a Bearer token in the Authorization header when calling platform APIs.

Token Endpoint

POST https://<platform-domain>/loginservice/connect/token

Request Format

Content Type: application x www form urlencoded

grant_type=clientcertificate
&client_id=clientcertificate
&token=<base64-encoded-jwt>

No client secret is required.

Example Request

POST /loginservice/connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=clientcertificate&client_id=clientcertificate&token=eyJhbGciOi...

Use Access Token in API Requests

The token endpoint returns an access token.

This token must be included in all API requests:

Authorization: Bearer <access-token>

All protected APIs require a valid bearer token.


Token Lifetime and Renewal

Access tokens are valid for approximately ten minutes.

After expiration:

  • A new JWT must be generated
  • A new token must be requested

Integrations should implement automatic token renewal.

Tokens must not be reused after expiration.


User Authentication

Some APIs may require user based authentication using OAuth 2.0 Authorization Code Grant with PKCE.

This flow is used for interactive user access and is separate from machine authentication.

Most system integrations only require machine authentication.


Practical Example: Manual Certificate and Token Setup

This section provides a practical example of generating certificates, signing JWTs, and obtaining access tokens using commonly available tools.

It supplements the general authentication flow described above and is intended for development and testing purposes.

Generate Certificate Using OpenSSL

openssl genpkey -algorithm RSA \
  -pkeyopt rsa_keygen_bits:2048 \
  -out private-key.pem

openssl req -new -x509 \
  -key private-key.pem \
  -out publickey.cer \
  -days 1825

Upload publickey.cer when creating the system integration.

Store private-key.pem securely.

Create and Validate JWT Using jwt.io (Optional)

Tools such as jwt.io can be used for testing and validation during development only; they must not be used to generate JWTs in production, and private key material (e.g., a PEM file) must never be uploaded to third-party online services.

Select: • Algorithm: RS256 • Header: Default

Example payload:

{
  "jti": "b639b8d9-d302-4cc5-8b83-aac451854492",
  "iss": "BF6FAFD79CDFA2FBC9CCB685E78C5D9DBCF713B9",
  "sub": "1733",
  "aud": "http://securitytokenservice",
  "exp": 1568991626,
  "nbf": 1568991086,
  "iat": 1568991326
}

Paste the public certificate and private key to validate the signature.

Obtain Access Token Using curl

Example request:

curl -X POST \
  https://<platform-domain>/loginservice/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=clientcertificate&client_id=clientcertificate&token=<jwt-token>"

The response contains the access token.


Troubleshooting Authentication

Common authentication issues include:

  • Invalid certificate
  • Incorrect thumbprint
  • Expired JWT
  • Invalid audience value
  • Incorrect machineId
  • Unsynchronized system clocks

If authentication fails:

  • Verify certificate registration
  • Verify JWT claims
  • Check token endpoint URL
  • Confirm system time accuracy

Next Steps

After authentication is configured, continue with: