CVE-2026-114617
Authlib: ID token can disable its own nonce validation via the nonce_supported claim
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
4.2
Authlib: ID token can disable its own nonce validation via the nonce_supported claim
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
CVE-2026-114617- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Weakness
- CWE-294, CWE-807
- Updated
- 2026-11-02
EUVDEUVD-2026-108519
4.2
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
EUVD-2026-108519- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-c5mf-xmp2-59rc
4.2
Authlib: ID token can disable its own nonce validation via the nonce_supported claim
Summary
OpenIDMixin.parse_id_token() reads the nonce_supported claim from the ID token it is validating. When that claim is boolean false, the expected nonce is set to None and nonce validation is skipped for that token.
An ID token that carries this claim is therefore accepted in a session whose nonce does not match. A captured, validly signed ID token belonging to a victim can be replayed into an attacker-controlled session, authenticating the attacker as the victim at the relying party.
The code is identical in authlib/integrations/base_client/sync_openid.py:82-83 and authlib/integrations/base_client/async_openid.py:84-85, so all framework integrations are affected. Fixed versions: none; reproduced on 1.8.0 (commit c529a61a).
Preconditions: the ID token must carry a valid signature and pass iss and aud validation, and the attacker must be able to supply it to parse_id_token(). Authorization code flow is not affected. Implicit and hybrid relying parties, and applications calling parse_id_token() directly, are affected.
Details
Affected code
authlib/integrations/base_client/sync_openid.py:80-85, in parse_id_token():
claims = claims_cls(token.claims, token.header, claims_options, claims_params)
# https://github.com/authlib/authlib/issues/259
if claims.get("nonce_supported") is False:
claims.params["nonce"] = None
claims.validate(leeway=leeway)
authlib/integrations/base_client/async_openid.py:82-86 contains the same code.
Source of the claim
claims is constructed from token.claims, which is the decoded payload of the ID token passed to parse_id_token():
token = jwt.decode(
token["id_token"],
key=key_set,
registry=JWSRegistry(algorithms=alg_values, strict_check_header=False),
)
...
claims = claims_cls(token.claims, token.header, claims_options, claims_params)
claims.get("nonce_supported") therefore resolves against the ID token payload. It is not read from load_server_metadata(), from client configuration, or from any other source under the relying party's control.
Effect on validation
IDToken.validate_nonce() at authlib/oidc/core/claims.py:69-83 performs the comparison only when the expected value is truthy:
nonce_value = self.params.get("nonce")
if nonce_value:
if "nonce" not in self:
raise MissingClaimError("nonce")
if nonce_value != self["nonce"]:
raise InvalidClaimError("nonce")
Assigning claims.params["nonce"] = None makes nonce_value falsy, so both the presence check and the equality check are skipped. No error is raised and claims.validate() completes normally.
The docstring of that same method states the requirement:
If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request.
Trigger condition
The comparison is is False, so only a JSON boolean false activates the branch. A string value "false" does not, and nonce validation proceeds normally in that case.
Origin
The branch was added in commit 3ca7333c ("Skip verifying nonce for Apple case") to accommodate a provider that emits a nonce_supported claim, as referenced by the inline comment pointing to issue #259.
Remediation
Read the flag from server metadata or client configuration rather than from the token:
metadata = self.load_server_metadata()
if metadata.get("nonce_supported") is False:
claims.params["nonce"] = None
This preserves the behavior for relying parties configured against a provider that does not support nonces, while preventing the token from determining whether it is subject to nonce validation.
Proof of concept
Environment
- authlib 1.8.0, commit
c529a61a(tagv1.8.0) - Python 3.14
- joserfc 1.7.5
- No network access required
git clone https://github.com/authlib/authlib.git && cd authlib
git checkout c529a61a
python3 -m venv .venv…
- Record
GHSA-c5mf-xmp2-59rc- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Weakness
- CWE-294, CWE-807
- Updated
- 2026-11-02
NVD
4.2
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
CVE-2026-114617- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Weakness
- CWE-294, CWE-807
- Updated
- 2026-11-02
OSV
4.2
Authlib: ID token can disable its own nonce validation via the nonce_supported claim
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
CVE-2026-114617- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Weakness
- CWE-294, CWE-807
- Updated
- 2026-11-03
OSVDEBIAN-CVE-2026-114617
4.2
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
DEBIAN-CVE-2026-114617- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Updated
- 2026-11-02
Show 4 moreShow less
OSVGHSA-c5mf-xmp2-59rc
4.2
Authlib: ID token can disable its own nonce validation via the nonce_supported claim
Summary
OpenIDMixin.parse_id_token() reads the nonce_supported claim from the ID token it is validating. When that claim is boolean false, the expected nonce is set to None and nonce validation is skipped for that token.
An ID token that carries this claim is therefore accepted in a session whose nonce does not match. A captured, validly signed ID token belonging to a victim can be replayed into an attacker-controlled session, authenticating the attacker as the victim at the relying party.
The code is identical in authlib/integrations/base_client/sync_openid.py:82-83 and authlib/integrations/base_client/async_openid.py:84-85, so all framework integrations are affected. Fixed versions: none; reproduced on 1.8.0 (commit c529a61a).
Preconditions: the ID token must carry a valid signature and pass iss and aud validation, and the attacker must be able to supply it to parse_id_token(). Authorization code flow is not affected. Implicit and hybrid relying parties, and applications calling parse_id_token() directly, are affected.
Details
Affected code
authlib/integrations/base_client/sync_openid.py:80-85, in parse_id_token():
claims = claims_cls(token.claims, token.header, claims_options, claims_params)
# https://github.com/authlib/authlib/issues/259
if claims.get("nonce_supported") is False:
claims.params["nonce"] = None
claims.validate(leeway=leeway)
authlib/integrations/base_client/async_openid.py:82-86 contains the same code.
Source of the claim
claims is constructed from token.claims, which is the decoded payload of the ID token passed to parse_id_token():
token = jwt.decode(
token["id_token"],
key=key_set,
registry=JWSRegistry(algorithms=alg_values, strict_check_header=False),
)
...
claims = claims_cls(token.claims, token.header, claims_options, claims_params)
claims.get("nonce_supported") therefore resolves against the ID token payload. It is not read from load_server_metadata(), from client configuration, or from any other source under the relying party's control.
Effect on validation
IDToken.validate_nonce() at authlib/oidc/core/claims.py:69-83 performs the comparison only when the expected value is truthy:
nonce_value = self.params.get("nonce")
if nonce_value:
if "nonce" not in self:
raise MissingClaimError("nonce")
if nonce_value != self["nonce"]:
raise InvalidClaimError("nonce")
Assigning claims.params["nonce"] = None makes nonce_value falsy, so both the presence check and the equality check are skipped. No error is raised and claims.validate() completes normally.
The docstring of that same method states the requirement:
If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request.
Trigger condition
The comparison is is False, so only a JSON boolean false activates the branch. A string value "false" does not, and nonce validation proceeds normally in that case.
Origin
The branch was added in commit 3ca7333c ("Skip verifying nonce for Apple case") to accommodate a provider that emits a nonce_supported claim, as referenced by the inline comment pointing to issue #259.
Remediation
Read the flag from server metadata or client configuration rather than from the token:
metadata = self.load_server_metadata()
if metadata.get("nonce_supported") is False:
claims.params["nonce"] = None
This preserves the behavior for relying parties configured against a provider that does not support nonces, while preventing the token from determining whether it is subject to nonce validation.
Proof of concept
Environment
- authlib 1.8.0, commit
c529a61a(tagv1.8.0) - Python 3.14
- joserfc 1.7.5
- No network access required
git clone https://github.com/authlib/authlib.git && cd authlib
git checkout c529a61a
python3 -m venv .venv…
- Record
GHSA-c5mf-xmp2-59rc- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Weakness
- CWE-294, CWE-807
- Updated
- 2026-11-02
OSVPYSEC-2026-4357
4.2
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
PYSEC-2026-4357- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-114617
4.2
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
- Record
UBUNTU-CVE-2026-114617- CVSS 3.1
- 4.2 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N - Updated
- 2026-11-02
OSVopenSUSE-SU-2026:12390-1 No score
python313-Authlib-1.9.1-1.1 on GA media
These are all security issues fixed in the python313-Authlib-1.9.1-1.1 package on the GA media of openSUSE Tumbleweed.
- Record
openSUSE-SU-2026:12390-1- Updated
- 2026-11-03
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
authlibPyPI |
through 1.8.0 | 1.9.0 |
python-authlibDebian:12 |
All versions, plus listed versions 1.2.0-11.2.0-1+deb12u11.2.0-1+deb12u21.2.1-11.3.0-1 Show 23 moreShow less1.3.0-21.3.0-31.3.1-11.3.2-11.3.2-21.4.0-11.4.1-11.5.0-11.5.1-11.5.2-11.6.0-11.6.1-11.6.3-11.6.4-11.6.5-11.6.6-11.6.7-11.6.8-11.6.9-11.7.0-11.7.2-11.7.2-21.9.1-1 |
None known |
python-authlibDebian:13 |
All versions, plus listed versions 1.6.0-11.6.0-1+deb13u11.6.1-11.6.3-11.6.4-1 Show 9 moreShow less1.6.5-11.6.6-11.6.7-11.6.8-11.6.9-11.7.0-11.7.2-11.7.2-21.9.1-1 |
None known |
python-authlibDebian:14 |
before 1.9.1-1, plus listed versions 1.6.0-11.6.1-11.6.3-11.6.4-11.6.5-1 Show 7 moreShow less1.6.6-11.6.7-11.6.8-11.6.9-11.7.0-11.7.2-11.7.2-2 |
1.9.1-1 |
authlibPyPI |
before 1.9.0, plus listed versions 0.10.100.110.120.12.1 Show 45 moreShow less0.130.140.14.10.14.20.14.30.150.15.10.15.20.15.30.15.40.15.50.15.60.1rc00.20.2.10.30.40.4.10.50.5.10.60.70.80.91.0.01.0.0a11.0.0a21.0.0b11.0.0b21.0.0rc11.0.11.1.01.2.01.2.11.3.01.3.11.3.21.4.01.4.11.5.01.5.11.5.21.6.01.6.11.6.10 |
1.9.0 |
python-authlibUbuntu:Pro:22.04:LTS |
All versions, plus listed versions 0.15.4-10.15.5-10.15.5-1ubuntu0.1~esm10.15.5-1ubuntu0.1~esm2 |
None known |
python-authlibUbuntu:Pro:24.04:LTS |
All versions, plus listed versions 1.2.1-11.3.0-11.3.0-1ubuntu0.1~esm11.3.0-1ubuntu0.1~esm2 |
None known |
python-authlibUbuntu:26.10 |
All versions, plus listed versions 1.6.7-11.7.2-11.7.2-2 |
None known |
python-authlibUbuntu:Pro:26.04:LTS |
All versions, plus listed versions 1.6.0-11.6.5-11.6.6-11.6.7-11.6.7-1ubuntu0.1~esm1 |
None known |
python-AuthlibopenSUSE:Tumbleweed From an advisory covering 10 CVEs |
before 1.9.1-1.1 | 1.9.1-1.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | ||
| affected, aliases, facts, references | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-114617 is a medium vulnerability (CVSS 4.2) in Authlib, published October 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.27%, the 18th percentile. Fixed in authlib 1.9.0.
References
github.com/authlib/authlib/security/advisories/GHSA-c5mf-xmp2-59rc
github.com/authlib/authlib/pull/949
github.com/authlib/authlib/commit/6563f6f7a8c2f71d2f85ee7511d72a4fbae3acc0
github.com/authlib/authlib/releases/tag/v1.9.0
nvd.nist.gov/vuln/detail/CVE-2026-114617
github.com/advisories/GHSA-c5mf-xmp2-59rc
Show 15 moreShow less
github.com/CVEProject/cvelistV5/tree/main/cves/2026/114xxx/CVE-2026-114617.json
security-tracker.debian.org/tracker/CVE-2026-114617
github.com/authlib/authlib
ubuntu.com/security/CVE-2026-114617
cve.org/CVERecord?id=CVE-2026-114617
suse.com/security/cve/CVE-2025-62706
suse.com/security/cve/CVE-2026-114614
suse.com/security/cve/CVE-2026-114615
suse.com/security/cve/CVE-2026-114616
suse.com/security/cve/CVE-2026-114617
suse.com/security/cve/CVE-2026-114618
suse.com/security/cve/CVE-2026-114619
suse.com/security/cve/CVE-2026-116672
suse.com/security/cve/CVE-2026-41425
suse.com/security/cve/CVE-2026-96760
Left out here: 14 versions and the rest of 2 source descriptions. The JSON record has them.