DPoP
DPoP (Demonstration of Proof-of-Possession)
**DPoP (Demostración de prueba de posesión) **es una extensión de OAuth 2.0 que garantiza que los tokens (acceso) estén vinculados al par de claves TPP (proveedor externo). Esto significa que incluso si se filtra un token, no se puede utilizar sin el correspondiente TPP privado generado aleatoriamente, evitando así ataques de repetición y uso indebido.
Paso 1: Genere un nuevo par de claves de firma usando OpenSSL
De acuerdo con el estándar DPoP, se recomienda utilizar llaves aleatorias en este paso.
- Elija un algoritmo (RSA PS256).
- Generar un nuevo par de claves aleatorias (clave privada y clave pública).
Paso 2: Convertir la clave pública al formato JWK
- DPoP requiere que la clave pública se incluya en el encabezado JWT como JWK (clave web JSON)
- Convierta su clave pública en formato PEM al formato JWK
Paso 3: Construir el DPoP JWT para la solicitud de token
- El DPoP JWT consta de un header y una payload:
- Header: Indica el tipo "dpop+jwt", el algoritmo "PS256" e incorpora su clave pública como JWK.
- Payload: Contiene el método HTTP (htm), el URI HTTP (htu), la hora de emisión (iat) y un identificador único (jti).
- Firmará este JWT con su clave privada generada en el Paso 1.
Headers
| Parámetro | Valor de muestra | Descripción |
|---|---|---|
| typ | dpop+jwt | Tipo de ficha |
| alg | PS256 | Algoritmo utilizado para firmar el JWT |
| jwk | {##public key##} | Clave pública en formato jwk. |
Payload:
| Parámetro | Valor de muestra | Descripción |
|---|---|---|
| htm | POST | El método HTTP que se utilizará para la API |
| htu | https://api.stage.redebanopenfinance.com/51/token.oauth2/v1 | El endpoint de URL para la API |
| iat | 1758265669 | "Emitida en" marca de tiempo |
| jti | lWkuS2iKLOebdS2n | Un identificador único para el token. |
Paso 4: Solicite un token de acceso
Solicitar endpoint de token con DPoP JWT creado con el valor del encabezado HTTP DPoP.
Ejemplo Curl para el Token
curl --location 'https://api.stage.redebanopenfinance.com/51/token.oauth2/v1' \
--key ./{network.key} \
--cert ./{network.pem} \
--header 'DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlBTMjU2IiwiandrIjp7Imt0eSI6IlJTQSIsIng1dCNTMjU2IjoiQkNiamg3clZpTHZHczhqODZYbDRtWHNpQlJKT1U2UGZUM21xZ3FyeXRBRSIsIm5iZiI6MTczMTQxOTQ3NywiZSI6IkFRQUIiLCJ1c2UiOiJzaWciLCJraWQiOiJyc2Ffa2V5IiwieDVjIjpbIk1JSURnRENDQW1pZ0F3SUJBZ0lHQVpNZ3BKZWFNQTBHQ1NxR1NJYjNEUUVCQlFVQU1Id3hEakFNQmdOVkJBTU1CVVpzZFdabU1SSXdFQVlEVlFRTERBbERZWFFnU0c5MWMyVXhIREFhQmdOVkJBb01FME5oYldKeWFXUm5aU0JWYm1sMlpYSnpkSGt4RWpBUUJnTlZCQWNNQ1VOaGJXSnlhV1JuWlRFWE1CVUdBMVVFQ0F3T1EyRnRZbkpwWkdkbGMyaHBjbVV4Q3pBSkJnTlZCQVlUQWtkQ01CNFhEVEkwTVRFeE1qRXpOVEV4TjFvWERUTTBNVEV4TURFek5URXhOMW93ZFRFT01Bd0dBMVVFQXd3RlIybHVaMlV4RXpBUkJnTlZCQXNNQ2tSdlp5QkxaVzV1Wld3eEdqQVlCZ05WQkFvTUVVOTRabTl5WkNCVmJtbDJaWEp6YVhSNU1ROHdEUVlEVlFRSERBWlBlR1p2Y21ReEZEQVNCZ05WQkFnTUMwOTRabTl5WkhOb2FYSmxNUXN3Q1FZRFZRUUdFd0pIUWpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTHh0NFlNYWxLRnFxQ3ZobGRtK0FuWWJrMlRjOHZyVzdUazg2bHpJaHN3YXk4WGpwRWN5NTJpWHcvVWpYN01wZ2Nsc2RQKytjY3VTR2VhelpqZFBtblIxQXdhY0NWNm5JbklmeDJTTkhWMXhGV1d5cWZYR0JGN2ZibHZCMTJMWnVLeXRCK28yWFJ4UkI1elRkWE16c2NrSHp0Q0hoUm9ENzRoSmgwUjdMQTRXZ1VjU3FETjQ1d1d0NGZEdTdQR1hGbDN3b0lYT0pZYkpHVGN0RU0yaHorUElFNmRONlR3Y3FqczhXL0lBVmN6dmxVblpXbVNnejh5S05YWWN4TCtnRGlvdk5EY3ZsdVpiMjBoYzVSeHhDNmMzVUlCMTJDUGQxb1ErK1VWVjRsWGowSWdsUWs1Mzd3bE1WQTYyNUJuby9FeC9ZaVh1aW9zaVVyTHVJMk4rSmhNQ0F3RUFBYU1QTUEwd0N3WURWUjBQQkFRREFnZUFNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUJONHc1dmJoZmpTZUFiZHNNbjY1UkVGRHFwQmV1WEFidXRCUWJSeFpzSkZEekhSZkxkUUNUcGpRT0FSWWxQZkNwWnVCRVpuS2lsWldoQmVPd1pLcXlwQTB3aXpjTE5oVEgvUXBPdCt2ZzFoQnJ5M0RSWGlibnRDSDY4TnlLZmVNNS9uTVBRdWpKeS9QUzFwb2crR25zNnFpbU5GN1pKeHRvY0pLaWJiNHkyaG5uK1NDZHpTSkJRYnE4UTB2alZZQkhlU2lDMGZ2TDRxYkJNZmQ3QWhzbm5wQ3lyMUNHM1ZTTy8vTXFUQjUvMTJ3NlBnTnlIWjZScjNpZjEwNFpPWnA3UzVFcGgyRGVzRERtVENnL3E5NWJLcnpNSHJrSURtQkVKZ25jQ05WSTdxUXVueTJpZDI2VERCTFNsWEw4WTd2NHZ3Y3hqcmdjTEthV0ZFVW9wekRwTyJdLCJleHAiOjIwNDY3Nzk0NzcsIm4iOiJ2RzNoZ3hxVW9XcW9LLUdWMmI0Q2RodVRaTnp5LXRidE9UenFYTWlHekJyTHhlT2tSekxuYUpmRDlTTmZzeW1CeVd4MF83NXh5NUlaNXJObU4wLWFkSFVEQnB3SlhxY2ljaF9IWkkwZFhYRVZaYktwOWNZRVh0OXVXOEhYWXRtNHJLMEg2alpkSEZFSG5OTjFjek94eVFmTzBJZUZHZ1B2aUVtSFJIc3NEaGFCUnhLb00zam5CYTNoOE83czhaY1dYZkNnaGM0bGhza1pOeTBRemFIUDQ4Z1RwMDNwUEJ5cU96eGI4Z0JWek8tVlNkbGFaS0RQeklvMWRoekV2NkFPS2k4ME55LVc1bHZiU0Z6bEhIRUxwemRRZ0hYWUk5M1doRDc1UlZYaVZlUFFpQ1ZDVG5mdkNVeFVEcmJrR2VqOFRIOWlKZTZLaXlKU3N1NGpZMzRtRXcifX0.eyJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9hcGkuc3RhZ2UucmVkZWJhbm9wZW5maW5hbmNlLmNvbS81MS90b2tlbi5vYXV0aDIvdjEiLCJpYXQiOjE3NTgyNjU2NjksImp0aSI6ImxXa3VTMmlLTE9lYmRTMm4ifQ.LNmAI-Joc7qmkIcTy0uzCozinDdR_IYCiBxT59QFF_9sUKxg-IYOdCt0La6TV2DXN9jn17TiThBG0VvBxOLXEnrr_XeyBbOrDMVwETUTnG5Dvrkd_ESmRi_g-rIpSFhwkRK1CC5FUA9Zh7lxGc7yEsGqPnymmA8INyFoXM2tOdaw_MK_Mwwq8ZtlQtAQDPF617Wrm2t03uYxDSO6Fy8yjfwzon4hTHjbOKeDIbv5nbU-jGXp3zWgP60ETmVKRuKV-RGAPdPYlNHaARrjMVLegE5GpaO15mCnDpEAJAmQzAmg1lkOqjWLxpkwKzr7ePZel5ZU30Rt3Wjz1vxEi3lCHQ' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=SC-15e55bf8-be49-4e31-a12d-65acd396c337' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJhbGciOiJQUzI1NiIsImtpZCI6Ijc2OEtSRWJUanRjckh2ZDdxcng3VjZsWU5YST0ifQ.eyJqdGkiOiJteUpXVElkMDAxIiwic3ViIjoiU0MtMTVlNTViZjgtYmU0OS00ZTMxLWExMmQtNjVhY2QzOTZjMzM3IiwiaXNzIjoiU0MtMTVlNTViZjgtYmU0OS00ZTMxLWExMmQtNjVhY2QzOTZjMzM3IiwiYXVkIjoiaHR0cHM6Ly9hdXRoLnN0YWdlLnJlZGViYW5vcGVuZmluYW5jZS5jb20iLCJpYXQiOjE3MzQ2OTQxMzksImV4cCI6MTc2NzE4NTgyNn0.NjwSF-_8nuc-BRp29ZPqYPcrtvAZdCF8GJkJNDPhJMbeDz3Va0O3GJvFj1LOQwRqcz8IYQUeRcKuPlzaLNwjz4hwhau-x6evArlQ4pkx_nvUmiKEmh4hPzRkgaJMRWyI56KgDL9cOk-0RS2ucAEUBuwWKSbSASuMo1hQnEjd-sL0VZEk7Ulier0TLBOE20KEW17Z-Ira5HrkHBZNgBEaBbKth6sntZD34BOiVB6SpDM-Tg2KjQBLLGCwXq44EfT9FtHhostmGQ3ovzZvxsgYwsW6U_mLBi9xJLDBELAtTCSR7s1S5Ae-X3OLfunB4-iBmcNtvmIrB0Cz7Sz_51bptA' \
--data-urlencode 'scope=payments'
Paso 5: Prepárese para el acceso a los recursos
- Para acceder a los recursos, necesita crear otro DPoP JWT que consta de un header y una payload:
- Header: Indica el tipo "dpop+jwt", el algoritmo "PS256" e incorpora su clave pública como JWK. (igual que el paso 3)
- Payload: Contiene el método HTTP (htm), el URI HTTP (htu), el momento de emisión (iat) y un identificador único (jti), y el claim ath (ath), que es un hash (SHA-256, codificado en base64url) de su token de acceso.
- Firme este JWT con la misma clave privada de firma generada en el paso 1.
Headers
| Parámetro | Valor de muestra | Descripción |
|---|---|---|
| typ | dpop+jwt | Tipo de ficha |
| alg | PS256 | Algoritmo utilizado para firmar el JWT |
| jwk | public key value | Clave pública en formato jwk |
Payload:
| Parámetro | Valor de muestra | Descripción |
|---|---|---|
| htm | POST | El método HTTP que se utilizará para la API |
| htu | https://api.stage.redebanopenfinance.com/51/back-channel-auth/v1/5061316a-3f1e-413e-ad43-3db94d773f93 | El endpoint de URL para la API |
| ath | CXGXnOFRmKh9Tnvf6tHrSHiUMHrJwAR4h0eRyIe-poM | un hash (SHA-256, codificado en base64url) del token de acceso |
| iat | 1758266744, | "Emitida en" marca de tiempo |
| jti | i-UVxK6hqsjrscpi | Un identificador único para el token. |
Paso 6: acceda a la API protegida
- Enviar una solicitud HTTP POST al endpoint del recurso protegido API de Consentimiento de pago, Pago nacional y Confirmación de fondos.
- Incluir el token de acceso en el encabezado de Autorización, utilizando el esquema "DPoP".
- Incluya su nuevo DPoP JWT en el encabezado DPoP.
- El servidor validará su prueba de posesión y, si todo es correcto, le dará acceso al recurso.
Ejemplo Curl para Consentimiento (Payment Consent)
curl --location 'https://api.stage.redebanopenfinance.com/51/domestic-payment-consents/v1' \
--key ./{network.key} \
--cert ./{network.pem} \
--header 'Content-Type: application/json' \
--header 'Authorization: DPoP v72Z3xciL8ZTInNTqZiJ43PI1QwMFeFka3NRfbnam5A' \
--header 'x-idempotency-key: 2' \
--header 'x-jws-signature: eyJhbGciOiJQUzI1NiIsInR5cCI6IkpPU0UiLCJjcml0IjpbImh0dHA6Ly9vcGVuYmFua2luZy5vcmcudWsvaWF0IiwiaHR0cDovL29wZW5iYW5raW5nLm9yZy51ay9pc3MiLCJodHRwOi8vb3BlbmJhbmtpbmcub3JnLnVrL3RhbiJdLCJodHRwOi8vb3BlbmJhbmtpbmcub3JnLnVrL2lzcyI6Ik9CLWU1ZjU4YWNlLTA5NjEtNGU0NC1hZjNjLTM1MjY1ZWQ4YjdjOS9TQy0xNWU1NWJmOC1iZTQ5LTRlMzEtYTEyZC02NWFjZDM5NmMzMzciLCJodHRwOi8vb3BlbmJhbmtpbmcub3JnLnVrL2lhdCI6MTc1MDA1ODc1NiwiaHR0cDovL29wZW5iYW5raW5nLm9yZy51ay90YW4iOiJvcGVuYmFua2luZy5vcmcudWsiLCJraWQiOiI3NjhLUkViVGp0Y3JIdmQ3cXJ4N1Y2bFlOWEk9IiwiY3R5IjoiYXBwbGljYXRpb24vanNvbiJ9..Bp_YLjqGUTtQNCcHDpNMsw8YJ2Q4F5TAifC78U8Nvd1LuDzHtOsH6DEIbyvkt_6dcV-sTu9_IYh7-mOA2v4CLY_fzz7PSLCgcys3yMjPEJSITz6V63iUh-Ujpo6-Ry9RTrptV5JdZ7SaW8u-rNClMROi4Inii6VLA8XFxJihkI7pzQfSPyt_jJGkaOyZd0MzgpGKW30HmWCQ2VNdieuMwydPeWdKKTMFTqDSMCs1QdFSOaKKVs9OK5oEBtGTrCwb5X-OgZ2O42lfK6hveXnbEB4YaDbxgVc_Y2Zzut7QrpkwpdouJnH8A9Fag2hh_vIxHv1SUuxVrd2MPZwWwziJlw' \
--header 'DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IlBTMjU2IiwiandrIjp7Imt0eSI6IlJTQSIsIng1dCNTMjU2IjoiQkNiamg3clZpTHZHczhqODZYbDRtWHNpQlJKT1U2UGZUM21xZ3FyeXRBRSIsIm5iZiI6MTczMTQxOTQ3NywiZSI6IkFRQUIiLCJ1c2UiOiJzaWciLCJraWQiOiJyc2Ffa2V5IiwieDVjIjpbIk1JSURnRENDQW1pZ0F3SUJBZ0lHQVpNZ3BKZWFNQTBHQ1NxR1NJYjNEUUVCQlFVQU1Id3hEakFNQmdOVkJBTU1CVVpzZFdabU1SSXdFQVlEVlFRTERBbERZWFFnU0c5MWMyVXhIREFhQmdOVkJBb01FME5oYldKeWFXUm5aU0JWYm1sMlpYSnpkSGt4RWpBUUJnTlZCQWNNQ1VOaGJXSnlhV1JuWlRFWE1CVUdBMVVFQ0F3T1EyRnRZbkpwWkdkbGMyaHBjbVV4Q3pBSkJnTlZCQVlUQWtkQ01CNFhEVEkwTVRFeE1qRXpOVEV4TjFvWERUTTBNVEV4TURFek5URXhOMW93ZFRFT01Bd0dBMVVFQXd3RlIybHVaMlV4RXpBUkJnTlZCQXNNQ2tSdlp5QkxaVzV1Wld3eEdqQVlCZ05WQkFvTUVVOTRabTl5WkNCVmJtbDJaWEp6YVhSNU1ROHdEUVlEVlFRSERBWlBlR1p2Y21ReEZEQVNCZ05WQkFnTUMwOTRabTl5WkhOb2FYSmxNUXN3Q1FZRFZRUUdFd0pIUWpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTHh0NFlNYWxLRnFxQ3ZobGRtK0FuWWJrMlRjOHZyVzdUazg2bHpJaHN3YXk4WGpwRWN5NTJpWHcvVWpYN01wZ2Nsc2RQKytjY3VTR2VhelpqZFBtblIxQXdhY0NWNm5JbklmeDJTTkhWMXhGV1d5cWZYR0JGN2ZibHZCMTJMWnVLeXRCK28yWFJ4UkI1elRkWE16c2NrSHp0Q0hoUm9ENzRoSmgwUjdMQTRXZ1VjU3FETjQ1d1d0NGZEdTdQR1hGbDN3b0lYT0pZYkpHVGN0RU0yaHorUElFNmRONlR3Y3FqczhXL0lBVmN6dmxVblpXbVNnejh5S05YWWN4TCtnRGlvdk5EY3ZsdVpiMjBoYzVSeHhDNmMzVUlCMTJDUGQxb1ErK1VWVjRsWGowSWdsUWs1Mzd3bE1WQTYyNUJuby9FeC9ZaVh1aW9zaVVyTHVJMk4rSmhNQ0F3RUFBYU1QTUEwd0N3WURWUjBQQkFRREFnZUFNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUJONHc1dmJoZmpTZUFiZHNNbjY1UkVGRHFwQmV1WEFidXRCUWJSeFpzSkZEekhSZkxkUUNUcGpRT0FSWWxQZkNwWnVCRVpuS2lsWldoQmVPd1pLcXlwQTB3aXpjTE5oVEgvUXBPdCt2ZzFoQnJ5M0RSWGlibnRDSDY4TnlLZmVNNS9uTVBRdWpKeS9QUzFwb2crR25zNnFpbU5GN1pKeHRvY0pLaWJiNHkyaG5uK1NDZHpTSkJRYnE4UTB2alZZQkhlU2lDMGZ2TDRxYkJNZmQ3QWhzbm5wQ3lyMUNHM1ZTTy8vTXFUQjUvMTJ3NlBnTnlIWjZScjNpZjEwNFpPWnA3UzVFcGgyRGVzRERtVENnL3E5NWJLcnpNSHJrSURtQkVKZ25jQ05WSTdxUXVueTJpZDI2VERCTFNsWEw4WTd2NHZ3Y3hqcmdjTEthV0ZFVW9wekRwTyJdLCJleHAiOjIwNDY3Nzk0NzcsIm4iOiJ2RzNoZ3hxVW9XcW9LLUdWMmI0Q2RodVRaTnp5LXRidE9UenFYTWlHekJyTHhlT2tSekxuYUpmRDlTTmZzeW1CeVd4MF83NXh5NUlaNXJObU4wLWFkSFVEQnB3SlhxY2ljaF9IWkkwZFhYRVZaYktwOWNZRVh0OXVXOEhYWXRtNHJLMEg2alpkSEZFSG5OTjFjek94eVFmTzBJZUZHZ1B2aUVtSFJIc3NEaGFCUnhLb00zam5CYTNoOE83czhaY1dYZkNnaGM0bGhza1pOeTBRemFIUDQ4Z1RwMDNwUEJ5cU96eGI4Z0JWek8tVlNkbGFaS0RQeklvMWRoekV2NkFPS2k4ME55LVc1bHZiU0Z6bEhIRUxwemRRZ0hYWUk5M1doRDc1UlZYaVZlUFFpQ1ZDVG5mdkNVeFVEcmJrR2VqOFRIOWlKZTZLaXlKU3N1NGpZMzRtRXcifX0.eyJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9hcGkuc3RhZ2UucmVkZWJhbm9wZW5maW5hbmNlLmNvbS81MS9iYWNrLWNoYW5uZWwtYXV0aC92MS81MDYxMzE2YS0zZjFlLTQxM2UtYWQ0My0zZGI5NGQ3NzNmOTMiLCJhdGgiOiJDWEdYbk9GUm1LaDlUbnZmNnRIclNIaVVNSHJKd0FSNGgwZVJ5SWUtcG9NIiwiaWF0IjoxNzU4MjY2NzQ0LCJqdGkiOiJpLVVWeEs2aHFzanJzY3BpIn0.ffRRH1urJob1o0AaXNH3S1Cr23LrpCAena0LsKRtIjw6lBZWA5mmL5laqWq1I7sPNtS2kXljHEqcHQP0rJCqYf0vznw7Ygh0BZucvqoZyIfdSdkPvLsGAe7mio5yoj4Jcl-OfnRX8Ek11vsBq22peK0x3PK5zfRDOLukAyxa1aRY6_SjCEB1yTSCwQXCRbyxztfuyu3WUofoKXcTNQbFW1Iq-k1_8T6c_aDvOd-8YfeTMEwNST9mmeJgZa_P1_X_eKsE64p0Kyv1L-BJUQukn-yFWbOty9PL0wOaJA6OpjzK2pINw4b9w1kIIgWIrWKvl5FpFCoxyEVBWx1bxJUB3A' \
--data '{"Data":{"ReadRefundAccount":"Yes","Authorisation":{"AuthorisationType":"Any","CompletionDateTime":"2025-11-12T00:00:00+00:00"},"Initiation":{"InstructionIdentification":"0555ca8f-bca6-470e-a192-2e897578a30","EndToEndIdentification":"DEMO USER","InstructedAmount":{"Amount":"115.00","Currency":"COP"},"CreditorAccount":{"SchemeName":"CAHO","Identification":"0036024594","Name":"Test user","SecondaryIdentification":"MERCHANTID"},"DebtorAccount":{"SchemeName":"CAHO","Identification":"3559898989","Name":"JESSICA","SecondaryIdentification":"1001017"},"CreditorPostalAddress":{"AddressLine":["test"],"AddressType":"Business","BuildingNumber":"27","Country":"GB","CountrySubDivision":"Wessex","Department":"test","PostCode":"7U31 2ZZ","StreetName":"AcaciaAvenue","SubDepartment":"test sub","TownName":"Sparsholt"},"SupplementaryData":{"DebtorMobileNumber":"3138745276"},"RemittanceInformation":{"Unstructured":"Internal ops code 5120101","Reference":"FRESCO-101"}},"SCASupportData":{"RequestedSCAExemptionType":"BillPayment","AppliedAuthenticationApproach":"CA","ReferencePaymentOrderId":"test"}},"Risk":{"PaymentContextCode":"Other","MerchantCategoryCode":"5967","MerchantCustomerIdentification":"053598653254","DeliveryAddress":{"AddressLine":["Flat 7","Acacia Lodge"],"StreetName":"AcaciaAvenue","BuildingNumber":"27","PostCode":"7U31 2ZZ","TownName":"Sparsholt","CountrySubDivision":"Wessex","Country":"GB"}}}'
Consulte el estándar definido en https://datatracker.ietf.org/doc/html/rfc9449 .