Trusted Identity
Trusted Identity is a signed JWS token (in JWT format) that the Partner/Tenant backend passes to the Verestro backend to authenticate the request and initiate an end-user session. The token is verified cryptographically (signature + certificate chain in x5c) and organizationally (verification of CN according to the onboarding configuration).
1) Purpose and Use
What it is
- Trusted Identity is a token that must be generated on the Partner/Tenant backend side, in an isolated and secure environment. It is passed to Verestro as proof that the Partner/Tenant confirms the identity of the end user identified by
userId(see the Payload (claims) section).
Why it is used
- To start an end-user session in a component (e.g., SDK) communicating with the Verestro backend.
- To simplify integration: the token is self-contained because it includes
x5c(certificate chain), so Verestro can verify the signature and trust without querying an external JWKS endpoint at runtime. - To protect against replay attacks: short TTL based on
iat.
Token Issuance and Verification – sample usage
@startuml skinparam ParticipantPadding 30 skinparam BoxPadding 30 skinparam noteFontColor #FFFFFF skinparam noteBackgroundColor #1C1E3F skinparam noteBorderColor #1C1E3F skinparam noteBorderThickness 1 skinparam sequence { ArrowColor #1C1E3F ArrowFontColor #1C1E3F ActorBorderColor #1C1E3F ActorBackgroundColor #FFFFFF ActorFontStyle bold ParticipantBorderColor #1C1E3F ParticipantBackgroundColor #1C1E3F ParticipantFontColor #FFFFFF ParticipantFontStyle bold LifeLineBackgroundColor #1C1E3F LifeLineBorderColor #1C1E3F } actor User participant "Partner/Tenant (Backend)" as A participant "Verestro (API)" as B User -> A: Session start request A -> A: Build payload (userId, iat, jti) A -> A: Add x5c (leaf + intermediates) A -> A: Sign JWS (RS256, private key) A -> B: Send Trusted Identity (JWS) B -> B: Read Root CA + expected CN B -> B: Validate x5c chain to Root CA B -> B: Validate CN/DN === expected B -> B: Verify JWS signature B -> B: Check iat TTL (10 min) B -> B: Start user session for userId B --> User: Session active @enduml
2) Integration / Onboarding
Variant A (recommended): Partner/Tenant provides CSR
The Partner/Tenant:
- generates an RSA key pair (RSA 2048),
- generates a CSR with
CN=V-TenantName-ApplicationName(instructions for correctly generating a CSR are available in the documentation), - submits the CSR to Verestro.
Verestro:
- signs the CSR with its internal CA and delivers the signed certificate to the Partner/Tenant.
The Partner/Tenant:
- uses the private key from the generated key pair to sign Trusted Identity tokens,
- includes the leaf + intermediate certificates in
x5c(if applicable).
Variant B: Partner/Tenant provides Root CA
The Partner/Tenant provides:
- The Root CA to be added as trusted in Verestro's systems.
- The expected
CN/DNof the certificate used for signing. - The above must be provided by the Partner/Tenant during the onboarding process.
Verestro:
- configures the Root CA in its systems,
- stores the expected
CN/DNfor the Partner/Tenant, - accepts tokens whose
x5cbuilds a chain to this Root CA and satisfies the CN/DN requirement.
Onboarding variants
@startuml skinparam ParticipantPadding 30 skinparam BoxPadding 30 skinparam noteFontColor #FFFFFF skinparam noteBackgroundColor #1C1E3F skinparam noteBorderColor #1C1E3F skinparam noteBorderThickness 1 skinparam sequence { ArrowColor #1C1E3F ArrowFontColor #1C1E3F ActorBorderColor #1C1E3F ActorBackgroundColor #FFFFFF ActorFontStyle bold ParticipantBorderColor #1C1E3F ParticipantBackgroundColor #1C1E3F ParticipantFontColor #FFFFFF ParticipantFontStyle bold LifeLineBackgroundColor #1C1E3F LifeLineBorderColor #1C1E3F } participant "Partner/Tenant" as C participant "Verestro" as P alt Variant A (recommended): CSR signed by our CA C -> C: Generate RSA keypair C -> P: Send CSR (CN=uniquePartner/TenantName) P -> P: Sign CSR with our CA P -> C: Return certificate (+ intermediates if any) P -> P: Configure our Root CA + expected CN/DN else Variant B: Partner/Tenant provides Root CA C -> P: Provide Root CA + expected CN/DN P -> P: Configure Root CA + expected CN/DN end @enduml
3) Structure
The token has the following format:
{base64url(header)}.{base64url(payload)}.{base64url(signature)}
3.1 Header
Required fields:
alg: signature algorithm (recommended:RS256, RSA 2048).x5c: X.509 certificate chain in Base64(DER) format, where:- the first element is the
leafcertificate (containing the public key used to verify the signature), - subsequent elements are intermediate certificates,
- the root CA is typically not included (Verestro holds it in its trust store).
- the first element is the
Example:
{
"alg": "RS256",
"typ": "JWT",
"x5c": [
"MIIC... (leaf)",
"MIID... (intermediate)"
]
}
3.2 Payload (claims)
Required fields:
userId: user identifier:- accepted values: internal ID (identifier from Verestro) or external ID (end-user identifier in the Partner/Tenant system),
- preferred: external ID — must be unique within the Partner/Tenant system,
iat: token issuance time (UNIX epoch in seconds).jti: unique token identifier (UUID).
Example:
{
"userId": "external-987654",
"iat": 1739191200,
"jti": "a3f1c3d6-0d3b-4f2e-9c24-8d6b9b2a9f0d"
}
3.3 Signature
- The token must be signed with the Partner/Tenant's private key corresponding to the certificate provided in
x5c. - Minimum requirements:
- RSA 2048
RS256
4) Security Requirements (TTL)
TTL (token validity)
- TTL: default: 10 minutes from
iat(this value can be changed). Once the token expires, a new one must be generated.
5) Trust Based on x5c and CN/DN Validation
What Verestro verifies
- Construction and validation of the certificate chain from
x5cup to the configured Root CA. - Validation of the certificate's
CNagainst the value established during the onboarding process. - JWS signature verification using the public key from the leaf certificate.
- Validation of
iat(TTL) andjti(replay protection), and presence ofuserId.
CN rule (integration requirement)
- The
CN(or agreedDN) of the certificate is the permanent identifier of the Partner/Tenant. - The
CN/DNmust not change during certificate renewal without prior notification; key/certificate rotations within the same DN are permitted.
7. Examples and Test Methods – those should be used for development and testing purposes only.
7.1 Trusted Identity example:
Token generated with the following payload will look like this:
{
"iat": "1770981506093",
"jti": "1b290b62-8e1e-4168-bb24-5c29d22ee699",
"userId": "some-external-user-id-1234"
}
"eyJhbGciOiJSUzI1NiIsIng1YyI6WyJNSUlGeFRDQ0E2MmdBd0lCQWdJVWNMWmtmN0EyZFdvNHdKT1NlVEdpbnMvdlVQTXdEUVlKS29aSWh2Y05BUUVMQlFBd2NqRUxNQWtHQTFVRUJoTUNVRXd4RkRBU0JnTlZCQWdNQzAxaGVtOTNhV1ZqYTJsbE1ROHdEUVlEVlFRSERBWlhZWEp6WVhjeEZEQVNCZ05WQkFvTUMxWmxjbVZ6ZEhKdklGTkJNUXd3Q2dZRFZRUUxEQU5FUlZZeEdEQVdCZ05WQkFNTUQxWmxjbVZ6ZEhKdlgwTkJYMFJsZGpBZUZ3MHlNVEF5TURnd056TTVOVEZhRncweU5qQXlNRGN3TnpNNU5URmFNSEl4Q3pBSkJnTlZCQVlUQWxCTU1SUXdFZ1lEVlFRSURBdE5ZWHB2ZDJsbFkydHBaVEVQTUEwR0ExVUVCd3dHVjJGeWMyRjNNUlF3RWdZRFZRUUtEQXRXWlhKbGMzUnlieUJUUVRFTU1Bb0dBMVVFQ3d3RFJFVldNUmd3RmdZRFZRUUREQTlXWlhKbGMzUnliMTlEUVY5RVpYWXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDRHdBd2dnSUtBb0lDQVFEbkZIZzB4Q0prckYwNFVSc0p0em5aVndxOWxrVUd2Z3J3K2RVVzh5aS9MV0VoMC9QU2hLVmUxNEFqWktXSXJaU3FRNDR6d0Mwbk04c0NyRjgvWnJxVFYvc0Q3dTQ5WnMzeko2TkVOQk83VTI0blZpeUxiaDNQQkZReEcyYWd6Q0ZTUXpEMTdpR0ZxckxYa29vQWVOMVllczRUc0FSdzlzK21aMlhydzlEaGdVa3pFZUZwcXo1c3J2N3huMFpLdjh4czMrZjd1SUlGdWdSWFhYVWltUmdCWXQ3dzk0SmgxblRpQis0SU1RSXBFR2Vmd29HTmlKL0IvWThsVXJVLzd1TnhKTHc2UU54dG52ZkFNaVJReGV4ektPc21RMWVxd1MrWWlQTVc3MG8vOVJHMmRRaWZyYWRpOU9JRjlqZmUxbzhxSVRQUG1nRG9aVWI1dWYrSGFybXdrSEs1SjBUcWpkZWZaNjlwYTVwWUppQzNsOUNOYlh1YzI3VVhuZmQxK2dwckdZMjdhMjgyemMwQnZad1FjL085blZIclVBeVh4OGR3MjIwK3RkUDZzSkFKMUV6YUpaVWltcDBka0hENkhLbmp3WjJ1L2RtMi83RzFYSnpiY0IzSStDMWlmbXdEYXhoWlVUbGpweGRBbklpbFU5WUpmOU14UVUwRGJ6bGVxMS9Sc01DWU9rSUpoZjVwZXdPMXFmSVlLK0V2a05iRzI5VzRqdGtNOFNISTdVRUFNN3hrWk1qVkNaamNMZnBzUk5LMWNjTnpFTEF3V2lHWG8yaVhEVmdBUStVUVU2cHBQdFQyb0ZVWWU3aWpFSit0RnEzQWd3UzIvMldnL1RvOVlhbitWM2luN2IxUURmTlJVc1BxeDgrTFlLcHhCRGVhMjBlR3FBZ1VTYzNEVFFJREFRQUJvMU13VVRBZEJnTlZIUTRFRmdRVWlteVhrSDE4bGhzRXc1ai9UaldCZ0d2NDNhSXdId1lEVlIwakJCZ3dGb0FVaW15WGtIMThsaHNFdzVqL1RqV0JnR3Y0M2FJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVhlM0ZGMm1zRC9qdllyYW03SnBpQlUvbFB0dEx0bmdpL3pCTGM4Y0dKbGlhcTM2S1h1ZWdpRWp3cjJtT1ExeXNaUXRQSnUrZjg4TXBPWU9QdDFBZm1QN1RRZ0ZZTjRyOFJVU2RxOEMwVTlUOFZvNUJxaXh4WFl6Z0xBSi8wTkZpZmx3YVJLN2FKOUdza1MrNkFoRUppRTdyNkl1cTZScWVyS3VvYkZvaEtQdHZLZkM5ZjBvcEwxVDBlV296L3BVNTBOTDM5QXpETkk5Tkh5MWdPQnNGNElYSHRUeHN1eTJCNjVyTkpjSjdKbmNkc0xhdWVhL3doa1hoUWRkUTVrN25MbUJ4eFl2M0RWZmNkZ2dYUXF0S3ZKQnh4SE9Gak1yUzdDYXVud2h6WDlJQW05Ny82MU8zNXVkd1dKVHZ0eFJnNEFWTGNOWXhjRHZTNlN3WVhud0dQak5BS0QvNXdpcStTMlZib1Z4UkJqSm12cEVhRU5WQ3djQnlvZ3ZidnlXcEd6WkhOUGdDRmVUVFRIYU51ZWJxL05XYmJ4QWM2bWhxM3d5bC9mYnBwakRhTno1U2hlbVFCdVVhbVZ1WlBZNVJDS2FUc2twSElTT0UyT1RrMkEzVkpuajA1cm0wQUY1QWlRbjJjWThJM3dYODlseFZRc3YrRjQyR2VMalVRMnVqMDR5dEliSjNnYUlBVFE3ODMvRjVuRkFVY0o0VWNGcXRFRXZEYVVkMEkrbFRtZkQzTEc0Y3E2STRheUd2Z04zS2NURW1PUU43ZlZPNWlvRjJFSk5oK1dRTHNuQ1RaTkgxc2dOSk53ajRRSlduSzVaYThPcTNzZk9jRDVraVE0ZmoxbW9HNmhRWkxQM3J6OVZZR2lCWTF2aWlGVG5RcWhJYjlOdzlrQ1NDaWEwPSJdfQ.eyJpYXQiOiIxNzcwOTgxNTA2MDkzIiwianRpIjoiMWIyOTBiNjItOGUxZS00MTY4LWJiMjQtNWMyOWQyMmVlNjk5IiwidXNlcklkIjoic29tZS1leHRlcm5hbC11c2VyLWlkLTEyMzQifQ.m75hzT1Wn4RW4wxVLdNm5wukVMtT-5J6h8PldaHfQ19WGqlx2x4wa5Ut2xKORaoMZOOkGMP1VKbOa-_MgFWeSR6nwyiUXoa7zDh7MNnUD7C1yCk-eVQDdSoFIQIg7UBjVj0uJZYkUOmScz0MjCpeZ-hhFVQInnHK-8YNdR1A5L-S5-d57pubz0C2GarIJu7z1d-qytfQFGdqvMAMuu9cPwc4oIfB4VajYqsz_NWWqSrsBNGnZIhuVKsWs1KXki3B2Z1v55tbET61bvZzuc7lEK27HzYaELC_za4zK0OP0GlqEl0gYzbj60E2sEE23jlUbiGj1Craq4KRrGpBAMDsgX0_kOicfQDjeYJ2wIouU2svDxLtI_BBiz7yT-opRTu0A-uDworfyWyt5IaZi9ZGOc_4--gwTWvrv1Bp9BPLZ8t6huSeJ4pjQTWMAZ_T2s2m69HWIIkIp0xDgkWBWlByEh-3ptzY_X3tZGtt7wjRH8AJrSeOXKPCDn9nZKu_sfaNFaDJGb28FajHR7u5xXUgif4DK9yFisaZf_SaXCkcO1KYO0oZD5Vy0gX-ZNJSVGX0yKm7wxHXBG1JPmHrvL-ieztM0PLBSR38I5CUJCHNLBlL2Cbw8YBuo-ubU0JxpgZ0i1g25Rxv1wVgYuw8x5ckxNpTjgsm08m-m-WcDxEAk_s"
7.2 Test methods
- Generating Trusted Identity:
curl --location 'https://datacore.verestro.dev/test/generate-jws-x5c-token' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Issuer-Code: YOUR_TENANT_ID' \
--header 'Application-Id: YOUR_TENANT_APP_ID' \
--header 'Authorization: Basic dGVzdDE6dGVzdDEyMw==' \
--header 'Collection: internal' \
--data '{
"iat": "1770981506093",
"jti": "1b290b62-8e1e-4168-bb24-5c29d22ee699",
"userId": "some-external-user-id-1234"
}'
- Validating Trusted Identity:
curl --location 'https://datacore.verestro.dev/test/read-jws-x5c-token' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Issuer-Code: YOUR_TENANT_ID' \
--header 'Application-Id: YOUR_TENANT_APP_ID' \
--header 'Authorization: Basic dGVzdDE6dGVzdDEyMw==' \
--header 'Collection: internal' \
--data '{
"token": "eyJhbGciOiJSUzI1NiIsIng1YyI6WyJNSUlGeF..................0qYz-H_0LEK0M"
}'
Output:
{
"verified": true,
"token": {
"iat": "1770981506093",
"jti": "1b290b62-8e1e-4168-bb24-5c29d22ee699",
"userId": "some-external-user-id-1234"
}
}