Skip to main content

Set up service user multi-factor authentication

A client authentication certificate enables multi-factor authentication (mTLS) for DigiCert® ONE APIs. This certificate works alongside or replaces your API key to provide enhanced security for sensitive operations, such as code signing, certificate management, and audit log access.

In this tutorial, you will:

  • Create a CSR and request a signed client authentication certificate.

  • Generate a PKCS#12 file with your certificate and private key.

  • Verify mTLS authentication works with DigiCert® ONE APIs.

  • Manage certificate access and learn about rotation and expiration.

Notice

DigiCert​​®​​ provides different authentication methods depending on the sensitivity of the operation. Make sure you understand when to use each method when building integrations.

Use mTLS (client certificate) for:

  • All DigiCert​​®​​ Software Trust Manager signing operations (required)

  • Production certificate issuance in DigiCert® Device Trust Manager (required)

  • Document signing operations in DigiCert​​®​​ Document Trust Manager (required)

  • High-security operations in DigiCert® Account Manager (optional but recommended)

Use API key authentication for:

  • Read-only operations (listing resources, viewing details)

  • Development and testing workflows

  • Non-signing certificate management tasks

Why mTLS for sensitive operations:

  • Provides cryptographic proof of identity (something you have)

  • More difficult to compromise than API keys

  • Certificates can be quickly disabled without regenerating API keys

  • Meets compliance requirements for code signing

Before you begin

Before you begin, make sure you have:

Endpoint overview

Path

Method

Description

/account/api/v1/client-auth-certificate

POST

Request a client authentication certificate for the authenticated user

/account/api/v1/user/me

GET

Get details about the authenticated user

/account/api/v1/client-auth-certificate/CERT_ID/enable

PUT

Enable or disable a client authentication certificate

Step 1: Generate a certificate signing request (CSR)

First you need to generate a private key and CSR using OpenSSL.

# Create directory for secure storage
mkdir -p ~/.digicert/certs
cd ~/.digicert/certs

# Generate private key and CSR
openssl req -new -newkey rsa:2048 -nodes \
  -keyout client_auth_private.key \
  -out client_auth.csr \
  -subj "/CN=Demo API Service User/O=Your Organization/C=US"

Immediately secure your client_auth_private.key file.

# Restrict access to owner read-only
chmod 400 client_auth_private.key

Two certificate files are created:

  • client_auth_private.key: Your private key. Keep this secure! You will safely store this in a PKCS#12 file in step 4.

  • client_auth.csr: Certificate signing request to send to DigiCert​​®​​.

Subject fields explained:

  • CN (Common Name): Use a descriptive name identifying the service (for example, Production API Service, CI/CD Signing Service, IoT Provisioning Service)

  • O (Organization): Your organization’s legal name

  • C (Country): Two-letter country code (US, CA, GB, DE)

  • Additional fields (OU, L, ST) are optional for client authentication certificates

Tip

Verify your CSR using openssl req -text -noout -in client_auth.csr. You should see certificate request details, including subject information and a 2048-bit RSA public key.

Step 2: Request a client authentication certificate

Next you will submit your generated CSR to Account Manager /account/api/v1/client-auth-certificate endpoint and save the response for the next step.

Include these fields in your request body:

  • csr Certificate signing request content

  • name Friendly name for the client authentication certificate

  • exp (optional) Service user expiration date in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)

Note

These examples save the API response to response.json for instructional purposes. Typically you would extract the x509_cert field directly from the response object and use it programmatically without saving to a file.

Successful response (HTTP 201):

{
  "id": "e281fe3b-fb97-4183-a4fa-205913a7aee4",
  "user_id": "8b210e38-b8a9-41df-a96e-1ffe4512f6d1",
  "name": "API Client Auth Certificate",
  "common_name": "Service User Client Auth",
  "x509_cert": "-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWgAwIBAgIQZA...\n-----END CERTIFICATE-----\n",
  "ca_cert": "-----BEGIN CERTIFICATE-----\nMIIEFjCCAv6gAwIBAgIQDx...\n-----END CERTIFICATE-----\n",
  "end_date": "2026-10-20T23:59:59Z",
  "start_date": "2025-10-20T00:00:00Z",
  "enabled": true,
  "serial_number": "6403F2A8B1234567890ABCDEF",
  "public_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
}

Step 3: Extract the certificate from response.json

With the response saved to response.json, you can extract your signed certificate in the x509_cert field.

jq -r '.x509_cert' response.json > client_auth.crt

Make sure the certificate was extracted:

openssl x509 -in client_auth.crt -text -noout | head -n 10

You should see certificate details including the subject, issuer, and validity dates.

Note

You now have the certificate (client_auth.crt) and private key (client_auth_private.key) as separate files. These can be used directly for authentication, or you can package them into a PKCS#12 (.p12) file in the next steps for easier distribution and use.

Step 4: Create PKCS#12 file

Combine your private key and the signed certificate into a password-protected PKCS#12 file.

openssl pkcs12 -export \
  -out client_auth.p12 \
  -inkey client_auth_private.key \
  -in client_auth.crt \
  -name "DigiCert Client Auth Certificate"

At the password prompt, enter a strong password and remember it. You will need it for all mTLS API calls.

Tip

Verify the PKCS#12 file using openssl pkcs12 -in client_auth.p12 -noout -info. Enter your password when prompted and confirm certificate details.

Delete sensitive files

The plaintext private key should not remain on your filesystem. The PKCS#12 file contains both the certificate and private key in a password-protected format.

# Delete plaintext private key
rm client_auth_private.key

Step 5: Test mTLS authentication

Verify the certificate works by making an API call using mTLS. To do this add clientauth to the base URL and use --cert flag to provide the certificate file (client_auth.p12) and password (YOUR_PASSWORD).

Important

Important differences for mTLS:

  • Base URL changes from demo.one.digicert.com to clientauth.demo.one.digicert.com

  • Use --cert flag with certificate file and password

  • Do not include the x-api-key header

Expected response (HTTP 200):

{
  "id": "783a6a45-b74b-4635-bb4b-69855910ccd3",
  "email": "jane@example.com",
  "status": "ACTIVE",
  "access_scope": "account",
  "primary_account_id": "130deba5-3ebb-43b2-8183-1a9940d460f5",
  "created_at": "2021-06-23T08:55:19Z",
  "created_by": "8f7f8b1f-63c1-4580-af7d-ea4cd890e8f7",
  "user_type": "service",
  "friendly_name": "Example service user",
  "description": "",
  "locale": "en_US",
  "applications": [
    {
      "id": "2d3a72fd-ad44-4a9b-952a-2bcadb14a741",
      "name": "Trust Lifecycle",
      "permissions": [
        "VIEW_EM_SEAT",
        "VIEW_EM_AUDIT_LOG",
        "VIEW_EM_CERTIFICATE",
        "VIEW_EM_PROFILE"
      ]
    },
    {
      "id": "1a05282a-ec70-4da9-b921-933c070fcf80",
      "name": "IoT Trust",
      "permissions": [
        "VIEW_IOT_CERTIFICATE",
        "VIEW_IOT_ENROLLMENT_PROFILE"
      ]
    },
    {
      "id": "97b97f1b-8d1d-4203-a62c-0a209a1bea0a",
      "name": "Document Trust",
      "permissions": [
        "MANAGE_DSM_VIEW_CERTIFICATE_PROFILES",
        "MANAGE_DSM_ADD_VALIDATIONS",
        "MANAGE_DSM_VIEW_CERTIFICATE_TEMPLATES",
        "MANAGE_DSM_VIEW_VALIDATIONS"
      ]
    },
    {
      "id": "78c0355a-e1ca-4978-b60c-e9d66b9e1f30",
      "name": "Account Manager",
      "permissions": [
        "MANAGE_AM_ACCOUNT",
        "VIEW_AM_AUDIT_LOG"
      ]
    },
    {
      "id": "fd2b688d-43bd-4b4a-9fd6-f883ad9e813d",
      "name": "CA Manager",
      "permissions": [
        "VIEW_CM_LICENSE"
      ]
    },
    {
      "id": "7660bdb3-66e7-46e6-928f-dcae4d64ee91",
      "name": "Software Trust",
      "permissions": [
        "MANAGE_SM_CERTIFICATE_PROFILE",
        "VIEW_SM_CERTIFICATE",
        "SIGN_SM_HASH"
      ]
    }
  ],
  "accounts": [
    {
      "id": "4b13f12d-c8b2-4c49-a21f-9b399364f2ce",
      "name": "Example account",
      "active": true,
      "service_period": {
        "from": "2021-05-06",
        "to": "2030-05-06"
      },
      "friendly_identifier": "1234567",
      "locale": "en_US"
    }
  ]
}

Step 6: Manage certificate access (enable/disable)

Client authentication certificates can be temporarily disabled to revoke API access without deleting the certificate. To do this you need the certificate ID, which you can get from the id field of the response.json file from step 2.

CERT_ID=$(jq -r '.id' response.json)
echo "Certificate ID: $CERT_ID"

Disable the certificate

Add the certificate ID to the endpoint path /account/api/v1/client-auth-certificate/CERT_ID/enable and provide the required body content. Make sure to use API token authentication (x-api-key header) and remove the clientauth. from the base URL.

curl -X PUT "https://demo.one.digicert.com/account/api/v1/client-auth-certificate/${CERT_ID}/enable" \
  -H "x-api-key: SERVICE_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

Response (HTTP 200):

{
  "id": "CERTIFICATE_ID",
  "user_id": "USER_ID",
  "name": "Certificate name",
  "common_name": "COMMON_NAME",
  "end_date": "2023-04-30T23:59:59Z",
  "start_date": "2021-06-10T00:00:00Z",
  "enabled": false,
  "serial_number": "AUTH_CERT_SERIAL",
  "public_key": "PUBLIC_KEY"
}

Verify access is revoked

Try making an mTLS API call with the disabled certificate.

curl -X GET \
  --cert client_auth.p12:YOUR_PASSWORD \
  --cert-type P12 \
  "https://clientauth.one.digicert.com/account/api/v1/user/me"

Response (HTTP 403):

{
    "errors": [
        {
            "code": "AUTHORIZATION_ERROR",
            "message": "No authentication data provided"
        }
    ]
}

Re-enable the certificate

curl -X PUT "https://demo.one.digicert.com/account/api/v1/client-auth-certificate/${CERT_ID}/enable" \
  -H "x-api-key: SERVICE_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'

The returned enable field shows true.

Client authentication certificates expire on the date specified during creation (maximum 397 days from creation date).

Check certificate expiration

Using OpenSSL:

openssl pkcs12 -in ~/.digicert/certs/client_auth.p12 -nokeys -passin pass:YOUR_PASSWORD | \
  openssl x509 -noout -enddate

Expected output:

notAfter=Oct 20 23:59:59 2026 GMT

Using the API:

curl -X GET \
  "https://demo.one.digicert.com/account/api/v1/client-auth-certificate" \
  -H "x-api-key: SERVICE_API_KEY" | jq '.[] | {name, end_date, enabled}'

What happens at expiration

When a certificate expires:

  • mTLS authentication immediately fails with HTTP 403

  • All integrations using the certificate stop working

  • The certificate cannot be renewed or extended

  • The certificate must be regenerated

Best practices for certificate rotation

Set up monitoring (90 days before expiration):

# Check expiration and alert if < 90 days remain
EXPIRY=$(openssl pkcs12 -in client_auth.p12 -nokeys -passin pass:YOUR_PASSWORD | \
  openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_REMAINING=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))

if [ $DAYS_REMAINING -lt 90 ]; then
  echo "WARNING: Certificate expires in $DAYS_REMAINING days. Rotate soon."
fi

Rotation workflow (zero-downtime):

  1. Generate new certificate 30-60 days before expiration (follow Steps 1-4)

  2. Test new certificate in non-production environment

  3. Update application configuration to use new certificate

  4. Deploy updated configuration

  5. Verify new certificate working

  6. Disable old certificate (Step 6)

  7. Monitor for any failed authentications

  8. Delete old certificate files after 7-day grace period