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 |
| POST | Request a client authentication certificate for the authenticated user |
| GET | Get details about the authenticated user |
| 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 nameC(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:
csrCertificate signing request contentnameFriendly name for the client authentication certificateexp(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.comtoclientauth.demo.one.digicert.comUse
--certflag with certificate file and passwordDo not include the
x-api-keyheader
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):
Generate new certificate 30-60 days before expiration (follow Steps 1-4)
Test new certificate in non-production environment
Update application configuration to use new certificate
Deploy updated configuration
Verify new certificate working
Disable old certificate (Step 6)
Monitor for any failed authentications
Delete old certificate files after 7-day grace period