Skip to content

Certificate-Based Authentication (mTLS)

Overview

Certificate-Based Authentication using Mutual TLS (mTLS) provides a secure way for applications to connect to TID without using client secrets. Your application uses a digital certificate to prove its identity, improving security and reliability for enterprise integrations, automated workflows, and secure system-to-system communication.


When to Use mTLS

Use CaseDescription
Applications without secrets (client_credentials)When storing a client secret is not feasible or secure
Use refresh tokens for on-behalf-of tokens (Class #2) (urn:ietf:params:oauth:grant-type:token-exchange, refresh_token)Long-running, non-repetitive workflows (> 1 hour) that need sender-constrained tokens with mTLS + DPoP
Use subject delegation for long-running repetitive workflows (Class #3)
(urn:ietf:params:oauth:grant-type:subject-delegation)
Repetitive workflows (> 1 hour) where applications act on behalf of users without the user being present
Device authentication (urn:trimble:params:oauth:x509-cert)IoT devices authenticate using mTLS with TID-provisioned certificates to obtain access tokens
F2C Token Exchange
(urn:ietf:params:oauth:grant-type:token-exchange)
Controller-to-sensor delegation where sensors without internet access delegate authority to a nearby controller

How it Works

  1. Obtain a certificate for your application from IAM.
  2. Application presents the certificate during the mTLS handshake to the /oauth/token endpoint.
  3. TID verifies the certificate and issues a certificate-bound access token.
  4. Application uses the access token to access protected APIs.

mTLS token endpoints:

  • Staging: https://mtls.stage.id.trimblecloud.com
  • Production: https://mtls.id.trimble.com

Certificate Management

1. Subscribe to IAM APIs in Cloud Console

mTLS certificates are provisioned by IAM. To obtain an mTLS certificate, the application requesting the certificate must subscribe to the IAM APIs in Cloud Console.

2. Generate the Certificate Signing Request (CSR)

Generate an RSA 2048-bit key pair and create a CSR. You can use either the openssl CLI or Python.

Using OpenSSL (CLI):

Terminal window
openssl req -new -newkey rsa:2048 -nodes -keyout myapp_private_key.pem -out myapp_csr.pem

Using Python:

import json
import datetime
from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
CERT_NAME = "EXAMPLE_CERTIFICATE"
# Origination timestamp of the client key pair
origination_timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
cert_cn = f"{CERT_NAME}-{origination_timestamp}"
# Generate RSA 2048-bit keys
keys = rsa.generate_private_key(public_exponent=65537, key_size=2048)
# Generate a CSR
builder = x509.CertificateSigningRequestBuilder(subject_name=x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, cert_cn)
]))
csr = builder.sign(keys, hashes.SHA256())
csr_pem = csr.public_bytes(serialization.Encoding.PEM)
# Write the private key and CSR to files
with open("client.private_key.pem", "wb") as f:
f.write(keys.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
with open("client.csr.pem", "wb") as f:
f.write(csr_pem)
# Build the IAM API request body
api_req_body = json.dumps({"csr": csr_pem.decode("ascii")})
with open("iam_api_req_body.json", "w") as f:
f.write(api_req_body)
print("CSR PEM:")
print(csr_pem.decode("ascii"))

3. Submit the CSR to IAM

Use the IAM API to add a new certificate by submitting the CSR created in the previous step.

Request

POST {IAM_baseurl}/applications/{applicationId}/certificates
Authorization: Bearer {<respective-application-token>}
Content-Type: application/json

Request body

{
"csr": "{PEM-encoded certificate signing request string}"
}

Response

{
"fingerprint": "{fingerprint string}",
"certificate": "{public certificate string}"
}

4. Certificate Issuance and Installation

  • TID will validate your CSR and issue a new certificate (e.g., a .crt or .pem file).
  • Download the issued certificate from the response.
  • Install the new certificate in your application, pairing it with the private key you generated in Step 2.

5. Rotate on Expiry

  • Create a new CSR and repeat the process to obtain a new certificate before the current one expires.
  • Update your application’s configuration to use the new certificate and private key.
  • Test authentication to ensure the new certificate is working.
  • Remove the old certificate (Work In Progress) from your application once the new one is active.

Note: Each application can have a maximum of 5 active certificates at any given time. Plan certificate rotation and management accordingly.

Certificate Lifecycle and Rotation

  • Certificates have a defined lifespan (validity period: 3 years*) as per security guidelines.
  • Rotate certificates before expiry or if compromise is suspected.
  • Each application can have up to 5 active certificates.

* Subject to change.


Client Credentials Grant with mTLS

Token Request

  • API CALL:

    • POST {mTLS endpoint}/oauth/token
  • HEADER:

    • Accept: application/json
  • REQUEST BODY:

    • grant_type = client_credentials
    • scope = {ApplicationNames} (Space separated values)
    • client_id = {Application ID registered in TID/IAM}

Example Token Request

POST /oauth/token HTTP/1.1
Host: mtls.stage.id.trimblecloud.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json
grant_type=client_credentials
&client_id=ada20a37-372a-42f3-ac25-1290fed75ad7
&scope=Automation-Test-App-421925030555583

Example Token Response

{
"token_type": "bearer",
"expires_in": 3600,
"access_token": "eyJhbG...<JWT truncated for brevity>"
}
  • To decode and verify the TID JWT Token, refer to Decode JWT

Certificate-Bound Access Tokens (Proof of Possession)

To provide strong sender-constrained security, access tokens are bound to the client certificate:

  • When a client authenticates with mTLS at the /token endpoint, the Authorization Server includes a confirmation claim (cnf) in the JWT access token.
  • The cnf claim contains the x5t#S256 field, which is the SHA-256 hash of the client certificate.

Example JWT claims:

{
"iss": "https://id.trimble.com",
"exp": 1769586829,
"nbf": 1769583229,
"iat": 1769583229,
"jti": "296200815e2549d8802cb41146344473",
"jwt_ver": 2,
"sub": "ada20a37-372a-42f3-ac25-1290fed75ad7",
"application_name": "Automation-Test-App-421925030555583",
"identity_type": "application",
"auth_time": 1769583229,
"amr": [
"client_credentials"
],
"cnf": {
"x5t#S256": "71692eb0806248bb8898c38a5356b8321b7548dbc81afd605c2f1313b834993c"
},
"aud": [
"ada20a37-372a-42f3-ac25-1290fed75ad7"
],
"scope": "Automation-Test-App-421925030555583"
}

Standards and Implementation Details

RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication

This implementation follows RFC 8705, which defines how OAuth 2.0 clients can authenticate using Mutual TLS (mTLS) and how access tokens can be bound to client certificates for Proof of Possession (PoP).

Client Authentication Methods

TID supports the following client authentication methods for mTLS and client secrets:

  • tls_client_auth: For certificates issued by a trusted Certificate Authority (CA).
  • client_secret_basic: Standard client secret authentication.
  • client_secret_post: Client secret sent in the POST body.

Clients must register their certificate details (subject DN or public key) with TID.

The OAuth 2.0 Authorization Server Metadata endpoint (https://id.trimble.com/.well-known/openid-configuration) advertises these supported methods in the token_endpoint_auth_methods_supported array.


Error Handling & Troubleshooting

ErrorDescriptionAction
Invalid CSRMalformed or missing fieldsRegenerate CSR with correct fields
Certificate ExpiredCertificate is no longer validRotate certificate and update app
Certificate MismatchCertificate does not match app/private keyEnsure correct pair is used
Revoked CertificateCertificate has been revokedRegister new certificate
Invalid Clientclient_id is incorrect or not registeredVerify client_id and registration
Invalid CertificateCertificate is invalid or untrustedUse valid, non-expired certificate
UnauthorizedClient not authorized for token/resourceCheck permissions and scopes
Token ExpiredAccess token expiredRequest new token

Best Practices

  • Store private keys securely and never share them.
  • Rotate certificates proactively.
  • Monitor certificate expiry and set up alerts.
  • Automate rotation if possible.
  • Do not reuse old certificates; generate a new CSR for each rotation.