Skip to content

Certificate-Based Authentication (mTLS)

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.


Use Case Description
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

  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

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)

Section titled “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"))

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}"
}
  • 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.
  • 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.

  • 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.


  • 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}
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
{
"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)

Section titled “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"
}

RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication

Section titled “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).

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 Description Action
Invalid CSR Malformed or missing fields Regenerate CSR with correct fields
Certificate Expired Certificate is no longer valid Rotate certificate and update app
Certificate Mismatch Certificate does not match app/private key Ensure correct pair is used
Revoked Certificate Certificate has been revoked Register new certificate
Invalid Client client_id is incorrect or not registered Verify client_id and registration
Invalid Certificate Certificate is invalid or untrusted Use valid, non-expired certificate
Unauthorized Client not authorized for token/resource Check permissions and scopes
Token Expired Access token expired Request new token

  • 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.