From b89c5c150b5f618d13b65b8f7c88eb2820637dfa Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 16:44:00 +0100 Subject: [PATCH 1/8] fix: add invalid_tx_code and security considerations on tx code guessing --- ...enid-4-verifiable-credential-issuance-1_0.md | 17 +++++++++++++++-- ...enid-4-verifiable-credential-issuance-1_1.md | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index fb375b9f..480ae736 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -760,13 +760,16 @@ The following additional clarifications are provided for some of the error codes `invalid_grant`: -- The Authorization Server expects a Transaction Code in the Pre-Authorized Code Flow but the Client provides the wrong Transaction Code. -- The End-User provides the wrong Pre-Authorized Code or the Pre-Authorized Code has expired. +- The End-User provides the wrong Pre-Authorized Code or the Pre-Authorized Code has expired or is no longer valid. `invalid_client`: - The Client tried to send a Token Request with a Pre-Authorized Code without a Client ID but the Authorization Server does not support anonymous access. +`invalid_tx_code`: + +- The Authorization Server expects a Transaction Code in the Pre-Authorized Code Flow but the Client provides the wrong Transaction Code. + Below is a non-normative example of a Token Error Response: ``` @@ -1503,6 +1506,16 @@ An attacker might leverage the Credential issuance process and the End-User's tr In order to cope with that issue, the Wallet is RECOMMENDED to interact with trusted Credential Issuers only. In that case, the Wallet would not process a Credential Offer with an untrusted issuer URL. The Wallet MAY also show the End-User the endpoint of the Credential Issuer it will be sending the Transaction Code to and ask the End-User for confirmation. +### Transaction Code Guessing + +When the Pre-Authorized Code Flow is used together with a Transaction Code (`tx_code`), the Transaction Code is typically short, low-entropy, and intended for one-time use. As a result, it may be susceptible to online guessing or brute-force attacks if an attacker can repeatedly submit Token Requests using the same Pre-Authorized Code. + +To mitigate this risk, the Authorization Server SHOULD limit the number of failed Transaction Code verification attempts associated with a Pre-Authorized Code or issuance transaction. Once a configurable maximum number of failed attempts is exceeded, the Authorization Server SHOULD invalidate the Pre-Authorized Code and reject further Token Requests for that transaction. + +Transaction Codes SHOULD be short-lived and SHOULD be treated as single-use. Upon successful verification, a Transaction Code SHOULD NOT be accepted again. + +When a valid Pre-Authorized Code is presented with an incorrect Transaction Code, the Authorization Server SHOULD return the `invalid_tx_code` error. If the Pre-Authorized Code has expired, has been invalidated (including due to too many failed attempts), or is otherwise no longer valid, the Authorization Server SHOULD return the `invalid_grant` error. + ## Credential Lifecycle Management The Credential Issuer is supposed to be responsible for the lifecycle of its Credentials. This means the Credential Issuer will invalidate Credentials when it deems appropriate, e.g., if it detects fraudulent behavior. diff --git a/1.1/openid-4-verifiable-credential-issuance-1_1.md b/1.1/openid-4-verifiable-credential-issuance-1_1.md index 7df12370..dba9f502 100644 --- a/1.1/openid-4-verifiable-credential-issuance-1_1.md +++ b/1.1/openid-4-verifiable-credential-issuance-1_1.md @@ -1162,13 +1162,16 @@ The following additional clarifications are provided for some of the error codes `invalid_grant`: -- The Authorization Server expects a Transaction Code in the Pre-Authorized Code Flow but the Client provides the wrong Transaction Code. -- The End-User provides the wrong Pre-Authorized Code or the Pre-Authorized Code has expired. +- The End-User provides the wrong Pre-Authorized Code or the Pre-Authorized Code has expired or is no longer valid. `invalid_client`: - The Client tried to send a Token Request with a Pre-Authorized Code without a Client ID but the Authorization Server does not support anonymous access. +`invalid_tx_code`: + +- The Authorization Server expects a Transaction Code in the Pre-Authorized Code Flow but the Client provides the wrong Transaction Code. + Below is a non-normative example of a Token Error Response: ``` @@ -1908,6 +1911,16 @@ An attacker might leverage the Credential issuance process and the End-User's tr In order to cope with that issue, the Wallet is RECOMMENDED to interact with trusted Credential Issuers only. In that case, the Wallet would not process a Credential Offer with an untrusted issuer URL. The Wallet MAY also show the End-User the endpoint of the Credential Issuer it will be sending the Transaction Code to and ask the End-User for confirmation. +### Transaction Code Guessing + +When the Pre-Authorized Code Flow is used together with a Transaction Code (`tx_code`), the Transaction Code is typically short, low-entropy, and intended for one-time use. As a result, it may be susceptible to online guessing or brute-force attacks if an attacker can repeatedly submit Token Requests using the same Pre-Authorized Code. + +To mitigate this risk, the Authorization Server SHOULD limit the number of failed Transaction Code verification attempts associated with a Pre-Authorized Code or issuance transaction. Once a configurable maximum number of failed attempts is exceeded, the Authorization Server SHOULD invalidate the Pre-Authorized Code and reject further Token Requests for that transaction. + +Transaction Codes SHOULD be short-lived and SHOULD be treated as single-use. Upon successful verification, a Transaction Code SHOULD NOT be accepted again. + +When a valid Pre-Authorized Code is presented with an incorrect Transaction Code, the Authorization Server SHOULD return the `invalid_tx_code` error. If the Pre-Authorized Code has expired, has been invalidated (including due to too many failed attempts), or is otherwise no longer valid, the Authorization Server SHOULD return the `invalid_grant` error. + ## Credential Lifecycle Management The Credential Issuer is supposed to be responsible for the lifecycle of its Credentials. This means the Credential Issuer will invalidate Credentials when it deems appropriate, e.g., if it detects fraudulent behavior. From 40d6ce747389e4d3b00f861fdff2b738504a2048 Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 16:44:47 +0100 Subject: [PATCH 2/8] fix: add doc history --- 1.0/openid-4-verifiable-credential-issuance-1_0.md | 2 +- 1.1/openid-4-verifiable-credential-issuance-1_1.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index 480ae736..b2b29246 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -3039,7 +3039,7 @@ The technology described in this specification was made available from contribut -19 - * TBD + * add invalid_tx_code to Pre-Authz Code Flow -final diff --git a/1.1/openid-4-verifiable-credential-issuance-1_1.md b/1.1/openid-4-verifiable-credential-issuance-1_1.md index dba9f502..d5d6f222 100644 --- a/1.1/openid-4-verifiable-credential-issuance-1_1.md +++ b/1.1/openid-4-verifiable-credential-issuance-1_1.md @@ -3474,3 +3474,4 @@ The technology described in this specification was made available from contribut * Add back Interactive Authorization Endpoint text that was removed from the 1.0 draft * add require_interactive_authorization_request to AS metadata * add interactive_authorization_endpoint to AS metadata section + * add invalid_tx_code to Pre-Authz Code Flow From 6e8ec2e2a04b393f1a8cbf6f8de10b72aaa0428c Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 17:08:29 +0100 Subject: [PATCH 3/8] fix: removed 1.0 changes --- ...enid-4-verifiable-credential-issuance-1_0.md | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index b2b29246..94073458 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -760,16 +760,13 @@ The following additional clarifications are provided for some of the error codes `invalid_grant`: -- The End-User provides the wrong Pre-Authorized Code or the Pre-Authorized Code has expired or is no longer valid. +- The Authorization Server expects a Transaction Code in the Pre-Authorized Code Flow but the Client provides the wrong Transaction Code. +- The End-User provides the wrong Pre-Authorized Code or the Pre-Authorized Code has expired. `invalid_client`: - The Client tried to send a Token Request with a Pre-Authorized Code without a Client ID but the Authorization Server does not support anonymous access. -`invalid_tx_code`: - -- The Authorization Server expects a Transaction Code in the Pre-Authorized Code Flow but the Client provides the wrong Transaction Code. - Below is a non-normative example of a Token Error Response: ``` @@ -1506,16 +1503,6 @@ An attacker might leverage the Credential issuance process and the End-User's tr In order to cope with that issue, the Wallet is RECOMMENDED to interact with trusted Credential Issuers only. In that case, the Wallet would not process a Credential Offer with an untrusted issuer URL. The Wallet MAY also show the End-User the endpoint of the Credential Issuer it will be sending the Transaction Code to and ask the End-User for confirmation. -### Transaction Code Guessing - -When the Pre-Authorized Code Flow is used together with a Transaction Code (`tx_code`), the Transaction Code is typically short, low-entropy, and intended for one-time use. As a result, it may be susceptible to online guessing or brute-force attacks if an attacker can repeatedly submit Token Requests using the same Pre-Authorized Code. - -To mitigate this risk, the Authorization Server SHOULD limit the number of failed Transaction Code verification attempts associated with a Pre-Authorized Code or issuance transaction. Once a configurable maximum number of failed attempts is exceeded, the Authorization Server SHOULD invalidate the Pre-Authorized Code and reject further Token Requests for that transaction. - -Transaction Codes SHOULD be short-lived and SHOULD be treated as single-use. Upon successful verification, a Transaction Code SHOULD NOT be accepted again. - -When a valid Pre-Authorized Code is presented with an incorrect Transaction Code, the Authorization Server SHOULD return the `invalid_tx_code` error. If the Pre-Authorized Code has expired, has been invalidated (including due to too many failed attempts), or is otherwise no longer valid, the Authorization Server SHOULD return the `invalid_grant` error. - ## Credential Lifecycle Management The Credential Issuer is supposed to be responsible for the lifecycle of its Credentials. This means the Credential Issuer will invalidate Credentials when it deems appropriate, e.g., if it detects fraudulent behavior. From 7cec13dcb7fafb17d35e2f62a6f9ddcd65f77a99 Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 17:08:58 +0100 Subject: [PATCH 4/8] fix: removed doc history for 1.0 --- 1.0/openid-4-verifiable-credential-issuance-1_0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index 94073458..8f3be8a8 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -3026,7 +3026,7 @@ The technology described in this specification was made available from contribut -19 - * add invalid_tx_code to Pre-Authz Code Flow + * TBD -final From e9cab1fce87ee9563c28d0ff43f01e08f9622006 Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 17:09:33 +0100 Subject: [PATCH 5/8] fix: fixed doc history --- 1.0/openid-4-verifiable-credential-issuance-1_0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index 8f3be8a8..fb375b9f 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -3026,7 +3026,7 @@ The technology described in this specification was made available from contribut -19 - * TBD + * TBD -final From 08a348e2d8c96c51a2f323c72fdf9aab1cee1726 Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 17:10:28 +0100 Subject: [PATCH 6/8] fix: fixed change log --- 1.0/openid-4-verifiable-credential-issuance-1_0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index fb375b9f..e6ab5f2d 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -3026,8 +3026,8 @@ The technology described in this specification was made available from contribut -19 - * TBD - + * TBD + -final * https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-final.html From 00c225ee5efa736f2dfd6dd0468f44aace60e454 Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Thu, 15 Jan 2026 17:11:59 +0100 Subject: [PATCH 7/8] fix: updated doc history 1.0 --- 1.0/openid-4-verifiable-credential-issuance-1_0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index e6ab5f2d..fb375b9f 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -3026,8 +3026,8 @@ The technology described in this specification was made available from contribut -19 - * TBD - + * TBD + -final * https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-final.html From 8e1b82f380704dec4c7edfc5c9ce62d3cfdb27c0 Mon Sep 17 00:00:00 2001 From: Oliver Terbu Date: Wed, 18 Feb 2026 20:38:23 +0100 Subject: [PATCH 8/8] fix: add security consideration to errata --- 1.0/openid-4-verifiable-credential-issuance-1_0.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/1.0/openid-4-verifiable-credential-issuance-1_0.md b/1.0/openid-4-verifiable-credential-issuance-1_0.md index fb375b9f..db7b0439 100644 --- a/1.0/openid-4-verifiable-credential-issuance-1_0.md +++ b/1.0/openid-4-verifiable-credential-issuance-1_0.md @@ -1503,6 +1503,17 @@ An attacker might leverage the Credential issuance process and the End-User's tr In order to cope with that issue, the Wallet is RECOMMENDED to interact with trusted Credential Issuers only. In that case, the Wallet would not process a Credential Offer with an untrusted issuer URL. The Wallet MAY also show the End-User the endpoint of the Credential Issuer it will be sending the Transaction Code to and ask the End-User for confirmation. +### Transaction Code Guessing + +When the Pre-Authorized Code Flow is used together with a Transaction Code (`tx_code`), the Transaction Code is typically short, low-entropy, and intended for one-time use. As a result, it may be susceptible to online guessing or brute-force attacks if an attacker can repeatedly submit Token Requests using the same Pre-Authorized Code. + +To mitigate this risk, the Authorization Server SHOULD limit the number of failed Transaction Code verification attempts associated with a Pre-Authorized Code or issuance transaction. Once a configurable maximum number of failed attempts is exceeded, the Authorization Server SHOULD invalidate the Pre-Authorized Code and reject further Token Requests for that transaction. + +Transaction Codes SHOULD be short-lived and SHOULD be treated as single-use. Upon successful verification, a Transaction Code SHOULD NOT be accepted again. + +When a valid Pre-Authorized Code is presented with an incorrect Transaction Code, the Authorization Server SHOULD return an error indicating that the provided Transaction Code is invalid. +If the Pre-Authorized Code has expired, has been invalidated (including due to too many failed attempts), or is otherwise no longer valid, the Authorization Server SHOULD return the `invalid_grant` error. + ## Credential Lifecycle Management The Credential Issuer is supposed to be responsible for the lifecycle of its Credentials. This means the Credential Issuer will invalidate Credentials when it deems appropriate, e.g., if it detects fraudulent behavior. @@ -3026,7 +3037,7 @@ The technology described in this specification was made available from contribut -19 - * TBD + * Add security consideration on transaction code guessing -final