Guide d’intégration du proxy TSP

Prev Next

Un fournisseur de services de confiance (TSP) est un composant ou un service qui fournit des fonctionnalités liées à la confiance pour une utilisation dans la signature électronique. Les responsabilités d’un FST comprennent généralement la gestion et la validation des certificats numériques, l’authentification et l’autorisation des utilisateurs finaux (signataires) pour l’utilisation de leurs clés privées, et la production de signatures basées sur ces ressources. Ensemble, ces capacités contribuent à garantir l’intégrité et l’authenticité des données.

TSP Proxy est un composant côté serveur de la plateforme OneSpan Sign (OSS) qui distribue les demandes de signature aux services de connecteur externe (EC) distants. Chaque EC agit en tant qu’intermédiaire entre l’OSS et un TSP arbitraire. Les intégrateurs sont responsables de la mise en œuvre et de l’hébergement de leur propre EC, qui doit se conformer à une API décrite dans le présent document et encapsuler toutes les préoccupations associées au TSP concerné. TSP Proxy fournit également une API qui peut être utilisée par l’EC invoqué pour récupérer un hachage de document et finaliser la signature produite par le TSP. Une fois qu’un service de production robuste répondant à ces exigences a été produit, il passe par un processus de test et d’approbation, après quoi sa configuration est déployée sur OneSpan Sign pour être utilisée par TSP Proxy. De cette façon, OneSpan Sign peut être intégré à un TSP de conception arbitraire.

Pour réussir l’intégration de votre connecteur externe à la plateforme OneSpan Sign, vous devrez vous concentrer sur deux domaines principaux. La première consiste à déchiffrer, vérifier et traiter le jeton de demande, et la seconde à récupérer un jeton d’accès à partir du service OAuth2 du proxy TSP . La première représente la demande de signature transmise au CE par le proxy TSP, et la seconde est nécessaire pour interagir avec l’API du proxy TSP.

Flux de travail du proxy TSP

Flowchart illustrating document hash verification and signature injection process with access tokens.

Demande de décryptage et de vérification du jeton

Le jeton de demande a une structure imbriquée. La couche externe est un jeton JSON Web Encryption (JWE) standard chiffré avec AES256. L’intégrateur reçoit un secret de 256 bits utilisé pour déchiffrer le JWE. Une fois que la CE a déchiffré la demande, elle doit évaluer soigneusement l’exactitude d’un certain nombre de revendications dans le jeton JSON Web Signature (JWS) inclus et vérifier sa signature à l’aide d’une clé publique RSA en ligne. Ces étapes de vérification sont essentielles et sont abordées plus en détail ci-dessous.

Voici un exemple simplifié de la façon dont un jeton de demande peut être déchiffré et validé en Java. Vous pouvez utiliser ce code comme référence pour implémenter des solutions dans d’autres langages de programmation.

Pour vous assurer que votre code fonctionne correctement, assurez-vous d’avoir ajouté les dépendances suivantes à votre projet :

<dependencies>
    <dependency>
        <groupId>com.nimbusds</groupId>
        <artifactId>nimbus-jose-jwt</artifactId>
        <version>8.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

L’exemple de code :

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.AESDecrypter;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
import com.onespan.external_connector.ec_mockca.model.MiniToken;
import net.minidev.json.JSONObject;
import org.springframework.web.reactive.function.client.WebClient;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.interfaces.RSAPublicKey;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;

public class RequestTokenProcessingExample {

public static void main(String[] args) throws ParseException, JOSEException, JsonProcessingException {
	String requestTokenStr = "the request token";
	String sharedSecret = "a shared secret";
	String targetEnv = "https://sandbox.e-signlive.com";
	String jwksUrl = targetEnv + "/rs/oauth2/jwks";
	String jtspUrl = targetEnv + "/rs";
	String yourInitUrl = "https://your-domain.com/ec/init";

	// 1. generate a symmetric key from the shared secret
	SecretKey key = new SecretKeySpec(sharedSecret.getBytes(), "AES");

	// 2. parse and decrypt the outer JWE layer of the request
	JWEObject jweObject = JWEObject.parse(requestTokenStr);
	EncryptionMethod enc = jweObject.getHeader().getEncryptionMethod();
	assertEquals(EncryptionMethod.A256GCM, enc);
	jweObject.decrypt(new AESDecrypter(key));

	// 3. extract and process inner JWS layer of the request
	SignedJWT jwt = jweObject.getPayload().toSignedJWT();

	// 3.1. verify the signing algorithm
	JWSAlgorithm algo = jwt.getHeader().getAlgorithm();
	assertEquals(JWSAlgorithm.RS256, algo);

	// 3.2. verify that the JWS has not expired
	Date exp = jwt.getJWTClaimsSet().getExpirationTime();
	assertTrue(exp.after(new Date()));

	// 3.3. obtain the public key from the OneSpan-hosted JWKS
	WebClient httpClient = WebClient.builder().build();
	String response = httpClient.get()
		.uri(jwksUrl)
		.retrieve()
		.bodyToMono(String.class)
		.block();

	JWKSet jwks = JWKSet.parse(response);
	JWK jwk = jwks.getKeyByKeyId(jwt.getHeader().getKeyID());
	RSAPublicKey publicKey = ((RSAKey)jwk).toRSAPublicKey();

	// 3.4. verify the signature with the public key
	JWSVerifier verifier = new RSASSAVerifier(publicKey);
	assertTrue(jwt.verify(verifier));

	// 3.5. verify the issuer and audience
	String iss = jwt.getJWTClaimsSet().getIssuer();
	assertEquals(jtspUrl, iss);
	List<String> auds = jwt.getJWTClaimsSet().getAudience();
	assertTrue(auds.contains(yourInitUrl));

	// 4. extract the MiniToken claim from the request
	JSONObject mt = (JSONObject)jwt.getJWTClaimsSet().getClaim("MiniToken");
	ObjectMapper mapper = new ObjectMapper();
	MiniToken minitoken = mapper.readValue(mt.toJSONString(), MiniToken.class);
	Map<String, String> params = minitoken.getContents();
	assertFalse(params.isEmpty());
}

}

La classe MiniToken :

@Data
public class MiniToken {
	private String sid;
	private String lang;
	private String callbackUrl;
	private String otp;
	private Map<String, String> contents;
}

Vérification

La vérification du jeton de demande est obligatoire. Les éléments suivants doivent être vérifiés :

  • Méthode de cryptage JWE : Prévu pour être A256GCM.

  • Méthode de signature JWS : Prévu pour RS256.

  • Expiration du jeton : Vérifiez que le jeton de demande n’a pas expiré.

  • Signature du jeton : Vérifiez que la signature du jeton de demande est valide.

  • Émetteur du jeton : L’URL de base de l’environnement OneSpan Sign cible suivie de « /rs ».

  • Audience du jeton : L’URL du point d’entrée de l’EC fournie à OneSpan doit apparaître dans cette liste.

Si l’une de ces vérifications échoue, la demande doit être rejetée.

Jeton d’accès

Le service TSP OAuth2 prend uniquement en charge le type d’octroi d’informations d’identification du client . Une fois que l’EC a été authentifié avec succès, il reçoit un jeton d’accès.

Authentification

Un EC a besoin d’informations d’identification pour obtenir un jeton d’accès afin d’utiliser l’API TSP Proxy. Ces justificatifs d’identité se composent d’un code d’identification et d’un code secret client, et vous seront fournis une fois que vous aurez terminé votre inscription auprès de OneSpan.

Autorisation

Le CE recevra un champ d’application spécifique pour utiliser l’API de proxy TSP attribuée.

Pour obtenir le jeton d’accès, effectuez une requête HTTP similaire à celle ci-dessous :

curl --location --request POST 'https://{hostname}/oauth2/token' \
--header 'Authorization: Basic ${base64(clientId:clientSecret)}' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'otp=${OTP from MiniToken}' \
--data-urlencode 'scope=${assigned scope}'

Cet appel ne peut être effectué avec succès qu’une seule fois par jeton de demande, car l’OTP (One Time Passcode) fourni par le jeton de demande sera invalidé une fois que le jeton d’accès est accordé. Par conséquent, il est crucial pour l’EC de stocker le jeton d’accès jusqu’à ce que le flux de signature soit terminé.

Vérification

La vérification par rapport au jeton d’accès est facultative. Les éléments suivants peuvent être vérifiés.

  • Expiration du jeton : vérifiez si le jeton a expiré.

  • Vérification du jeton : assurez-vous que le jeton est valide et digne de confiance. Cela peut être fait de la même manière que JWT est validé ci-dessus.

  • Fournisseur de jetons : il doit s’agir de l’URL de base de l’environnement cible suivie de « /rs ».

OAuth2 API

  • GET/rs/oauth2/token pour obtenir un jeton d’accès.

  • POST/rs/oauth2/jwks pour obtenir un JWKS (JSON Web Key Set) à partir duquel la clé publique peut être obtenue.

Proxy API

  • GET/rs/proxy/api/hash pour obtenir un hachage de document

  • POST/rs/proxy/api/inject pour injecter le hachage du document signé (signature) dans le document (pdf)

Pour plus d’informations sur l’API Proxy, reportez-vous à la https://sandbox.esignlive.com/rs/proxy.

Processus de signature

Le processus de signature proprement dit se produit au cours des étapes 4 à 6 du diagramme ci-dessus.

Flowchart illustrating document hash verification and signature injection process with access tokens.

Pour terminer un processus de signature, vous devez procéder comme suit :

  1. Obtenir un hachage de document

  2. Signer le hachage du document

  3. Injecter le hachage du document signé dans le document

Obtention d’un hachage de document

Pour obtenir un hachage de document, les données suivantes doivent être fournies dans le corps de la demande :

  • SID : ID de session fourni par le MiniToken ;

  • Type de signature : PKCS1, PKCS7 ou CMS ;

  • Certificat du signataire : Doit être au format PEM. Le certificat du signataire peut avoir un en-tête et un pied de page ou aucun en-tête ni pied de page, mais il ne peut pas avoir simplement un en-tête ou un simple pied de page.

Par exemple:

{
  "sid": "string",
  "lang": "string",
  "content": {
    "signatureType": "PKCS1",
    "signerCert": "string"
  }
}

Ensuite, effectuez un appel POST avec le corps de la requête ci-dessus à /proxy/api/hash. La réponse suivante vous sera retournée :

{
  "sid": "string",
  "lang": "string",
  "result": {
    "hash": "string"
  }
}

Le hachage du document se trouve dans le champ de hachage . Le hachage utilise RSA SHA256.

Signature d’un hachage de document

Cette étape doit être effectuée par une autorité de certification, et chaque autorité de certification dispose de son propre flux de travail. Reportez-vous au processus de l’autorité de certification de votre organisation pour signer le hachage du document.

Le proxy TSP prend uniquement en charge les types de signature PKCS1, PKCS7 et CMS.

Injection d’une signature

Dès que le hachage du document est signé, il peut être envoyé au proxy TSP pour injection. Pour ce faire, les données suivantes doivent être préparées :

  • Type de signature : Doit être PKCS1 ou PKCS7 et doit avoir la même valeur que l’appel précédent.

  • Hachage signé : hachage du document signé.

Par exemple:

{
  "sid": "string",
  "lang": "string",
  "content": {
    "signatureType": "PKCS1",
    "signedHash": "string"
  }
}

Ensuite, effectuez un appel POST avec le corps de la requête ci-dessus à /proxy/api/inject. La réponse suivante vous sera retournée :

{
  "sid": "string",
  "lang": "string",
  "result": {
    "status": "string",
    "returnUrl": "string"
  }
}

Si le statuschamp " a une valeur autre que success, alors cet appel doit être réessayé.

Le returnUrl champ fournit une URL de redirection pour ramener le signataire au début du processus de signature.

Appendice

Exemple de jeton de demande

Voici un exemple de jeton de demande JWE, tel qu’il apparaîtrait lorsqu’il serait reçu par un EC.

eyJlbmMiOiJBMjU2R0NNIiwidGFnIjoiTHFRVHUwN2xocVpISHl6TF9qT0pBZyIsImFsZyI6IkEyNTZHQ01LVyIsIml2IjoiVHFHYjFvRFFtbkhOZXVBVyJ9.5POunw5dPvtem2MHxJsNodj_iHtqkFoL4c6cBIpy4iA.Q1d3XKUMB3WsAghA.rOE6xDKdMjYzEyQgQvcdqszGVeC-OFh74ue-MpfTlxYyZVsmUGjOo62eWOSJ_lfBDngaWycyziPeDTzUtMV63uVM-m5TanIcQC5Za3uYHGqDkgFHMyCRlZiVWDtgKCL9SDGpAkVzq6jtAKu6xeN5F-0DGZVKLMUHtKBpoJ8DaTXos275OpsD9fu_WykTJqoMAoTQy6KwjE2BurjW1eikOtoIS0CxobrpzsP_FkEeR7W0OQKC6U_VVk-5SO4Az5HWH96YtZIolYmw5TBhN0E45mkllMrgQD9ZHIWoMNOAjfS-G6SP2tmxT4Clpu0OQ3ycMtJHXqAGVIwJxJ-i_8L79H-u7j4YsVoH4_QuOK_trU7SI0M_HtrZB86qdseQUmehgrLjfa0kFGlQnIMuaRc-WLBJXT8VBdUaSJSS8xJSiesVBK6XjGR8bGNwfaMsUn86kACrQd26ftbH6d7SnYE2GLYQvSxIyUaPK5DczWTXztN1gVAuWZvDlEHZlkhbNXTrENRunnQn_Ekk4-bDC44bYerhIWk3BRNKNK7BMZL-SqppJu9pTL3ZaDMgDn4gRF6Xele1oMAPEw85XAQJIQzZwhJkpx-t6_fZiZcW1NAmcdN0jMl90FYsA9eVlJfmxIiGtYBLYxF67xUddwExUyawHYI-wDs7wfmZO2k8cVFycZFf-x68u-jIG-a_BYWBP5uGO0h8iwn8J-UUwDmTSUEE2n_2ZHF9mtakuhZV_-G9ld1ZMRPi-hVdcQUp_1lvsyVO1Efizy4mRuuoMvXsWDc-W7tM5IdPxLCT7GtgJXTeZOHdrF4zuZ4zZAOT4-zMfxDhlkXLpTCZQtI-FOFCaeGgxc4oxVrVwkt75rTY3WhRQiohyNP8LLBTcKpoiWamNo3Y6vaIFSIW9JWtUKRbU6fpWcDi-0TFB7x7x9DqXe9vHE1r73haa9Dwye_YQy_dmIfOQIK04GCbE96D8kH_LPHrNhiVlBBEkWJhe6TJ0H9K5En5oIYfhGs37uolPaW7cVxD32ZgvxEM6XVZNYs-qJSYRg3-_n5ImqYdCfzZDF7TETAfQJfE_jrTRmuNi22Fis9jPPxp9BAWUk2Hk0i5A_K4rZJEK-3N_is42dYtXc3l6A_o1lmKiX7sQ9eYB9G5VAPdD5nbo0FjHCMflWT_ymp98BPl044jiIeNKtbePQis_4vD5T6v1gbyIpURJ9YmqCm29k0G4S7HkpS9xeePsdahuv8cGRo4i9esFjr5CxXREB_nS-vyFgWAj1fD7aHbQ2ZbtpU9MAw0O0yCqUHQ8rcdUXmwktNmxa1aP5nExSTtRk6hNQP3JkgYpA5QGjGtzbqrEcJouw-K97oxz4ETOBENk25ZvI5Rv5Lqx5q5RC91xZEUnqhk1u4osXwDAYrex_YTz-o5ghtp4zBgT08iZftZ6ZEvvYPOmlHq8GNAxKcPZkGcJceIj-WExE8ugOTF9R-M3gVPmC2WmBBK5r-omlN7mCebl5CQnrvWsnOYT5VjIzh0wyhciP3zo5TUyyEKv3wL6r48NFWN3Czj0U7WZPtYJvaouci-gfnGoNhlRMxXUZvIWYqbawbsJ--FiyBDVb82xjWWqYeyfuUJ_c4yK1soY6PuJxuFagvBCdDnibvfZePcJVMWaWv8pLKna9uUNQ6hWI36-BreTQ-0t6sb0pa5TQkmbhP8ieVOciQ8e4tPV72OjU9ElTBclCY80JXaLuNr50dDIyw-7eI8l_jS.PHmauhRpPtD4-BLTmafCSw

En-tête après décodage

{
  "enc": "A256GCM",
  "tag": "LqQTu07lhqZHHyzL_jOJAg",
  "alg": "A256GCMKW",
  "iv": "TqGb1oDQmnHNeuAW"
}

JWS extrait de la JWE déchiffrée

eyJraWQiOiJjNjQzNjk5MC05YjMzLTRiZjEtYTI0Ny1kMTNlYjMwNDMyZjMiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL29zc3EzLnJuZC5lc2lnbmxpdmUuY29tL3JzIiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6OTg5OS9lYy9pbml0IiwiTWluaVRva2VuIjp7InNpZCI6ImE0Y2E0Zjc3MGU4ZTZkMDg5ZjhmZjFiMmUxMmZlYTNiMTg3N2NjNzE0YzcyZGYzMmIyYWE0NmRjZTc0YmZkMzkiLCJsYW5nIjoiZW4iLCJjYWxsYmFja1VybCI6Imh0dHBzOi8vb3NzcTMucm5kLmVzaWdubGl2ZS5jb20vdHJhbnNhY3Rpb24vWDdhT1BQTldSQkQzb1l4ZGFyMjlaT1ZvRUtVPS9zaWduP2luaXRpYWxEb2N1bWVudElkPTI5Mzc0MWRiMzg4ZjQ1MGE1N2U4YTRjMWZmMzViZTg3ZjI3M2I1NDBhNDBmMGM5MCZzaWduZXJJZD1kOTNhdU1WUlNyOFImZG9jdW1lbnROYXZPcGVyYXRpb249bmV4dCIsIm90cCI6IjZiZWEzYmQzLWRmNTQtNDVlYy04ODZiLTYyMTM5ZTE2ZWZkOSIsImNvbnRlbnRzIjp7ImRvY05hbWUiOiJUZXN0X0RvY3VtZW50X0VtcHR5Iiwicm9sZUlkIjoibkt1dXgxNjNpQnNNIiwiZG9jSWQiOiIyOTM3NDFkYjM4OGY0NTBhNTdlOGE0YzFmZjM1YmU4N2YyNzNiNTQwYTQwZjBjOTAiLCJ0cmFuc0lkIjoiWDdhT1BQTldSQkQzb1l4ZGFyMjlaT1ZvRUtVPSIsInNpZ25hdHVyZVR5cGUiOiJQS0NTMSJ9fSwiZXhwIjoxNzQyMjQzODE3LCJpYXQiOjE3NDIyNDM1MTd9.aM54pCQ_RyEKIFxqzeY-KGvML7s-Z1Q7NXE-VqV1O1HuJU__KU_77bOEJuBw7bQbQPk_6sTSWrwPZ71V9QBxMT6KFu0zUGfTxMcN90x9gyYN1QMshQDhv8wUjvCk9KmIjLtMxaqGAPS0BD5xxpHt9a9B2D9aGhqAhqYMZx20GMlTjVLkyEi40IG5kU9s5UYSxbg9RgFGSV_55kK3B3vLQRiGV2qqAVSzmVCyB4lPKDQNViiOZyyweaaLx0Ri7d1AmYU5NTRV8DrtEcFbF4Uq-VxdWf6MZrFnlI9UFLdGcr89V4Q3zG2QPWtSftp5hyW0ldZvBD1Pt-JN_s-AItig6w

En-tête après décodage

{
  "kid": "c6436990-9b33-4bf1-a247-d13eb30432f3",
  "alg": "RS256"
}

Charge utile après décodage :

{
  "iss": "https://ossq3.rnd.esignlive.com/rs",
  "aud": "https://localhost:9899/ec/init",
  "MiniToken": {
    "sid": "a4ca4f770e8e6d089f8ff1b2e12fea3b1877cc714c72df32b2aa46dce74bfd39",
    "lang": "en",
    "callbackUrl": "https://ossq3.rnd.esignlive.com/transaction/X7aOPPNWRBD3oYxdar29ZOVoEKU=/sign?initialDocumentId=293741db388f450a57e8a4c1ff35be87f273b540a40f0c90&signerId=d93auMVRSr8R&documentNavOperation=next",
    "otp": "6bea3bd3-df54-45ec-886b-62139e16efd9",
    "contents": {
      "docName": "Test_Document_Empty",
      "roleId": "nKuux163iBsM",
      "docId": "293741db388f450a57e8a4c1ff35be87f273b540a40f0c90",
      "transId": "X7aOPPNWRBD3oYxdar29ZOVoEKU=","signatureType": "PKCS1"
    }
  },
  "exp": 1742243817,
  "iat": 1742243517
}

Un JWKS typique

{
    "keys": [
        {
            "kty": "RSA",
            "e": "AQAB",
            "kid": "c6436990-9b33-4bf1-a247-d13eb30432f3",
            "n": "1WzJWdMmvdkah4szAo6t0VA5jEGNG6KFSMwB7ZLNAyQR2zfZ-HTYCfZGbC-BOnyodzsVoBA6MCWHak1nN098ZTrp0rWFz3WeeYRPYaJGLzmoeKzhoFyEg2WVYXzHBJfn95vYfgT1POhuCDofZnuZl5CpdOUxN6E-MOU6asZ7JtPwluqlMxeJH1CXr5hKdvy3GC3aOXwWdQw5edloGEglPmHpMGuXH667-mDPFSfGISaBn5qIqsDLXPLujim_Cgfuvm7kxAqjmxOjQPInsw6lpdOHc-EZpHLHoIzxtafPzX7TYCUmjv3Bkpe3teBJMHGp0Y_YCn97DZdLbOeyskpWdQ"
        }
    ]
}

Un jeton d’accès typique

eyJraWQiOiJjNjQzNjk5MC05YjMzLTRiZjEtYTI0Ny1kMTNlYjMwNDMyZjMiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJwcm94eS1vbmVzcGFuIiwiYXVkIjoiaHR0cHM6Ly9vc3NxMy5ybmQuZXNpZ25saXZlLmNvbS9ycy9wcm94eSIsIm5iZiI6MTc0MjI0MzUyNiwic2NvcGUiOlsicHJveHkuYXBpIl0sImlzcyI6Imh0dHBzOi8vb3NzcTMucm5kLmVzaWdubGl2ZS5jb20vcnMiLCJleHAiOjE3NDIyNDUzMjYsImlhdCI6MTc0MjI0MzUyNiwianRpIjoiMDk2YTIwMTUtYTY1ZC00YTc3LWI5ZjEtOWNkYzg2NWU2MDhlIn0.0NidkTxNEdidO4jx50sD5tnwMSX6Jhy9ggIGG34fBhr33w6OHsqKFtRAfo7xAUOysCyk3Flw8ZgsUKFDmich1rYznu5Zwm6xA-3O4d_LlDm7-dDRzR_sECrBagyllwZQVXHmvuSOha63W-PBkjixxn3UwpK93pjSyXKCBSrhFCwzx63gKsd0jPaN_DP7mDJ8jBSGbfEfCCbEkCduU1-zNCSfAFWrEuKvKzdUgV8hoOn9Dzs48vTuTih2PCPQRIEyNnpn3A2mH10D3-TIHcBsAFFNg5QK7A8LTcWu5C9aCgCaF9zKjEYspUArzzxWSfMHAJJ5E5slSnmwwQIKSdFmbQ

En-tête après décodage

{
  "kid": "cb6ffa24-bcaf-4aae-904b-a0ce979b846d",
  "alg": "RS256"
}

Charge utile après décodage

{
  "sub": "proxy-onespan",
  "aud": "https://domain.com/rs/proxy",
  "nbf": 1742243526,
  "scope": [
    "proxy.api"
  ],
  "iss": "https://domain.com/rs",
  "exp": 1742245326,
  "iat": 1742243526,
  "jti": "096a2015-a65d-4a77-b9f1-9cdc865e608e"
}