rfc9449.original.xml | rfc9449.xml | |||
---|---|---|---|---|
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="UTF-8"?> | |||
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Process | ||||
or - mmark.miek.nl" --> | <!DOCTYPE rfc [ | |||
<rfc version="3" ipr="trust200902" docName="draft-ietf-oauth-dpop-16" submission | <!ENTITY nbsp " "> | |||
Type="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclu | <!ENTITY zwsp "​"> | |||
de" indexInclude="true" consensus="true"> | <!ENTITY nbhy "‑"> | |||
<!ENTITY wj "⁠"> | ||||
]> | ||||
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft | ||||
-ietf-oauth-dpop-16" number="9449" submissionType="IETF" category="std" | ||||
consensus="true" xml:lang="en" tocInclude="true" sortRefs="true" symRefs="true" | ||||
updates="" obsoletes="" version="3"> | ||||
<front> | <front> | |||
<title abbrev="OAuth DPoP">OAuth 2.0 Demonstrating Proof-of-Possession at the Ap | <title abbrev="OAuth DPoP">OAuth 2.0 Demonstrating Proof of Possession (DPoP)</t | |||
plication Layer (DPoP)</title><seriesInfo value="draft-ietf-oauth-dpop-16" strea | itle> | |||
m="IETF" status="standard" name="Internet-Draft"></seriesInfo> | <seriesInfo name="RFC" value="9449"/> | |||
<author initials="D." surname="Fett" fullname="Daniel Fett"><organization>Authle te</organization><address><postal><street></street> | <author initials="D." surname="Fett" fullname="Daniel Fett"><organization>Authle te</organization><address><postal><street></street> | |||
</postal><email>mail@danielfett.de</email> | </postal><email>mail@danielfett.de</email> | |||
</address></author><author initials="B." surname="Campbell" fullname="Brian Camp | </address></author> | |||
bell"><organization>Ping Identity</organization><address><postal><street></stree | ||||
t> | <author initials="B." surname="Campbell" fullname="Brian Campbell"><organization | |||
</postal><email>bcampbell@pingidentity.com</email> | >Ping Identity</organization><address><postal><street></street> | |||
</address></author><author initials="J." surname="Bradley" fullname="John Bradle | </postal><email>bcampbell@pingidentity.com</email></address></author> | |||
y"><organization>Yubico</organization><address><postal><street></street> | ||||
<author initials="J." surname="Bradley" fullname="John Bradley"><organization>Yu | ||||
bico</organization><address><postal><street></street> | ||||
</postal><email>ve7jtb@ve7jtb.com</email> | </postal><email>ve7jtb@ve7jtb.com</email> | |||
</address></author><author initials="T." surname="Lodderstedt" fullname="Torsten | </address></author> | |||
Lodderstedt"><organization>yes.com</organization><address><postal><street></str | ||||
eet> | <author initials="T." surname="Lodderstedt" fullname="Torsten Lodderstedt"><orga | |||
</postal><email>torsten@lodderstedt.net</email> | nization>Tuconic</organization><address><postal><street></street> | |||
</address></author><author initials="M." surname="Jones" fullname="Michael Jones | </postal><email>torsten@lodderstedt.net</email></address></author> | |||
"><organization>independent</organization><address><postal><street></street> | ||||
<author initials="M." surname="Jones" fullname="Michael Jones"><organization>Sel | ||||
f-Issued Consulting</organization><address><postal><street></street> | ||||
</postal><email>michael_b_jones@hotmail.com</email> | </postal><email>michael_b_jones@hotmail.com</email> | |||
<uri>https://self-issued.info/</uri> | <uri>https://self-issued.info/</uri> | |||
</address></author><author initials="D." surname="Waite" fullname="David Waite"> | </address></author> | |||
<organization>Ping Identity</organization><address><postal><street></street> | ||||
<author initials="D." surname="Waite" fullname="David Waite"><organization>Ping | ||||
Identity</organization><address><postal><street></street> | ||||
</postal><email>david@alkaline-solutions.com</email> | </postal><email>david@alkaline-solutions.com</email> | |||
</address></author><date/> | </address></author> | |||
<area>Security</area> | ||||
<workgroup>Web Authorization Protocol</workgroup> | <date year="2023" month="September"/> | |||
<area>sec</area> | ||||
<workgroup>oauth</workgroup> | ||||
<keyword>security</keyword> | <keyword>security</keyword> | |||
<keyword>oauth2</keyword> | <keyword>oauth2</keyword> | |||
<abstract> | <abstract> | |||
<t>This document describes a mechanism for sender-constraining OAuth 2.0 | <t>This document describes a mechanism for sender-constraining OAuth 2.0 | |||
tokens via a proof-of-possession mechanism on the application level. | tokens via a proof-of-possession mechanism on the application level. | |||
This mechanism allows for the detection of replay attacks with access and refres h | This mechanism allows for the detection of replay attacks with access and refres h | |||
tokens.</t> | tokens.</t> | |||
</abstract> | </abstract> | |||
</front> | </front> | |||
<middle> | <middle> | |||
<section anchor="Introduction"><name>Introduction</name> | <section anchor="Introduction"><name>Introduction</name> | |||
<t>DPoP (for Demonstrating Proof-of-Possession at the Application Layer) | <t>Demonstrating Proof of Possession (DPoP) is an application-level mechanism fo | |||
is an application-level mechanism for | r | |||
sender-constraining OAuth <xref target="RFC6749"></xref> access and refresh toke ns. It enables a client to | sender-constraining OAuth <xref target="RFC6749"></xref> access and refresh toke ns. It enables a client to | |||
prove the possession of a public/private key pair by including | prove the possession of a public/private key pair by including | |||
a <tt>DPoP</tt> header in an HTTP request. The value of the header is a JSON Web Token | a <tt>DPoP</tt> header in an HTTP request. The value of the header is a JSON Web Token | |||
(JWT) <xref target="RFC7519"></xref> that enables the authorization | (JWT) <xref target="RFC7519"></xref> that enables the authorization | |||
server to bind issued tokens to the public part of a client's | server to bind issued tokens to the public part of a client's | |||
key pair. Recipients of such tokens are then able to verify the binding of the | key pair. Recipients of such tokens are then able to verify the binding of the | |||
token to the key pair that the client has demonstrated that it holds via | token to the key pair that the client has demonstrated that it holds via | |||
the <tt>DPoP</tt> header, thereby providing some assurance that the client prese nting | the <tt>DPoP</tt> header, thereby providing some assurance that the client prese nting | |||
the token also possesses the private key. | the token also possesses the private key. | |||
In other words, the legitimate presenter of the token is constrained to be | In other words, the legitimate presenter of the token is constrained to be | |||
the sender that holds and can prove possession of the private part of the | the sender that holds and proves possession of the private part of the | |||
key pair.</t> | key pair.</t> | |||
<t>The mechanism specified herein can be used in cases where other | <t>The mechanism specified herein can be used in cases where other | |||
methods of sender-constraining tokens that utilize elements of the underlying | methods of sender-constraining tokens that utilize elements of the underlying | |||
secure transport layer, such as <xref target="RFC8705"></xref> or <xref target=" I-D.ietf-oauth-token-binding"></xref>, | secure transport layer, such as <xref target="RFC8705"></xref> or <xref target=" I-D.ietf-oauth-token-binding"></xref>, | |||
are not available or desirable. For example, due to a sub-par user experience | are not available or desirable. For example, due to a sub-par user experience | |||
of TLS client authentication in user agents and a lack of support for HTTP token | of TLS client authentication in user agents and a lack of support for HTTP token | |||
binding, neither mechanism can be used if an OAuth client is an application that | binding, neither mechanism can be used if an OAuth client is an application that | |||
is dynamically downloaded and executed in a web browser (sometimes referred to a s a | is dynamically downloaded and executed in a web browser (sometimes referred to a s a | |||
"single-page application"). Applications installed | "single-page application"). | |||
and run directly on a user's device are another example well positioned to benef | Additionally, applications that are installed and run directly | |||
it | on a user's device are well positioned to benefit from | |||
from DPoP-bound tokens to guard against misuse of tokens by a compromised | DPoP-bound tokens that guard against the misuse of tokens by | |||
or malicious resource. Such applications often have dedicated protected storage | a compromised or malicious resource. | |||
Such applications often have dedicated protected storage | ||||
for cryptographic keys.</t> | for cryptographic keys.</t> | |||
<t>DPoP can be used to sender-constrain access tokens regardless of the | <t>DPoP can be used to sender-constrain access tokens regardless of the | |||
client authentication method employed, but DPoP itself is not used for client au thentication. | client authentication method employed, but DPoP itself is not used for client au thentication. | |||
DPoP can also be used to sender-constrain refresh tokens issued to public client s | DPoP can also be used to sender-constrain refresh tokens issued to public client s | |||
(those without authentication credentials associated with the <tt>client_id</tt> ).</t> | (those without authentication credentials associated with the <tt>client_id</tt> ).</t> | |||
<section anchor="conventions-and-terminology"><name>Conventions and Terminology< /name> | <section anchor="conventions-and-terminology"><name>Conventions and Terminology< /name> | |||
<t>The key words "MUST", "MUST NOT", "REQUIRED", & | <t> | |||
quot;SHALL", "SHALL | The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQU | |||
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", | IRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL | |||
"NOT RECOMMENDED", | NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14> | |||
"MAY", and "OPTIONAL" in this document are to be interpreted | RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", | |||
as | "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to | |||
described in BCP 14 <xref target="RFC2119"></xref> <xref target="RFC8174"></xref | be interpreted as | |||
> when, and only when, they | described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> | |||
appear in all capitals, as shown here.</t> | when, and only when, they appear in all capitals, as shown here. | |||
</t> | ||||
<t>This specification uses the Augmented Backus-Naur Form (ABNF) notation | <t>This specification uses the Augmented Backus-Naur Form (ABNF) notation | |||
of <xref target="RFC5234"></xref>.</t> | of <xref target="RFC5234"></xref>.</t> | |||
<t>This specification uses the terms "access token", "refresh tok | <t>This specification uses the terms "access token", "refresh token", | |||
en", | "authorization server", "resource server", "authorization endpoint", | |||
"authorization server", "resource server", "authorizati | "authorization request", "authorization response", "token endpoint", | |||
on endpoint", | "grant type", "access token request", "access token response", | |||
"authorization request", "authorization response", "tok | "client", "public client", and "confidential client" defined by "The OAuth 2.0 A | |||
en endpoint", | uthorization Framework" <xref target="RFC6749"></xref>.</t> | |||
"grant type", "access token request", "access token res | <t>The terms "request", "response", "header field", and "target URI" | |||
ponse", | ||||
"client", "public client", and "confidential client&quo | ||||
t; defined by The OAuth 2.0 Authorization Framework <xref target="RFC6749"></xre | ||||
f>.</t> | ||||
<t>The terms "request", "response", "header field" | ||||
, and "target URI" | ||||
are imported from <xref target="RFC9110"></xref>.</t> | are imported from <xref target="RFC9110"></xref>.</t> | |||
<t>The terms "JOSE" and "JOSE header" are imported from <xre f target="RFC7515"></xref>.</t> | <t>The terms "JOSE" and "JOSE Header" are imported from <xref target="RFC7515">< /xref>.</t> | |||
<t>This document contains non-normative examples of partial and complete HTTP me ssages. | <t>This document contains non-normative examples of partial and complete HTTP me ssages. | |||
Some examples use a single trailing backslash to indicate line wrapping for long values, as per <xref target="RFC8792"></xref>. | Some examples use a single trailing backslash to indicate line wrapping for long values, as per <xref target="RFC8792"></xref>. | |||
The character and leading spaces on wrapped lines are not part of the value.</t> | The character and leading spaces on wrapped lines are not part of the value.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="objective"><name>Objectives</name> | <section anchor="objective"><name>Objectives</name> | |||
<t>The primary aim of DPoP is to prevent unauthorized or illegitimate | <t>The primary aim of DPoP is to prevent unauthorized or illegitimate | |||
parties from using leaked or stolen access tokens, by binding a token | parties from using leaked or stolen access tokens, by binding a token | |||
to a public key upon issuance and requiring that the client proves | to a public key upon issuance and requiring that the client proves | |||
possession of the corresponding private key when using the token. | possession of the corresponding private key when using the token. | |||
This constrains the legitimate sender of the token to only the party with | This constrains the legitimate sender of the token to only the party with | |||
access to the private key and gives the server receiving the token added | access to the private key and gives the server receiving the token added | |||
assurances that the sender is legitimately authorized to use it.</t> | assurances that the sender is legitimately authorized to use it.</t> | |||
<t>Access tokens that are sender-constrained via DPoP thus stand in | <t>Access tokens that are sender-constrained via DPoP thus stand in | |||
contrast to the typical bearer token, which can be used by any party in | contrast to the typical bearer token, which can be used by any party in | |||
possession of such a token. Although protections generally exist to | possession of such a token. Although protections generally exist to prevent unin | |||
prevent unintended disclosure of bearer tokens, unforeseen vectors for | tended disclosure of bearer tokens, unforeseen vectors for leakage have occurred | |||
leakage have occurred due to vulnerabilities and implementation issues | due to vulnerabilities and implementation issues in other layers in the protoco | |||
in other layers in the protocol or software stack (CRIME <xref target="CRIME"></ | l or software stack (see, e.g., Compression Ratio Info-leak Made Easy (CRIME) <x | |||
xref>, BREACH <xref target="BREACH"></xref>, | ref target="CRIME"></xref>, Browser Reconnaissance and Exfiltration via Adaptive | |||
Heartbleed <xref target="Heartbleed"></xref>, and the Cloudflare parser bug <xre | Compression of Hypertext (BREACH) <xref target="BREACH"></xref>, | |||
f target="Cloudbleed"></xref> are some examples). | Heartbleed <xref target="Heartbleed"></xref>, and the Cloudflare parser bug <xre | |||
f target="Cloudbleed"></xref>). | ||||
There have also been numerous published token theft attacks on OAuth | There have also been numerous published token theft attacks on OAuth | |||
implementations themselves (<xref target="GitHub.Tokens"></xref> as just one hig h profile example). | implementations themselves (<xref target="GitHub.Tokens"></xref> is just one hig h-profile example). | |||
DPoP provides a general defense in depth | DPoP provides a general defense in depth | |||
against the impact of unanticipated token leakage. DPoP is not, however, | against the impact of unanticipated token leakage. DPoP is not, however, | |||
a substitute for a secure transport and MUST always be used in | a substitute for a secure transport and <bcp14>MUST</bcp14> always be used in | |||
conjunction with HTTPS.</t> | conjunction with HTTPS.</t> | |||
<t>The very nature of the typical OAuth protocol interaction | <t>The very nature of the typical OAuth protocol interaction | |||
necessitates that the client discloses the access token to the | necessitates that the client discloses the access token to the | |||
protected resources that it accesses. The attacker model | protected resources that it accesses. The attacker model | |||
in <xref target="I-D.ietf-oauth-security-topics"></xref> describes cases where a | in <xref target="I-D.ietf-oauth-security-topics"></xref> describes cases where a | |||
protected resource might be counterfeit, malicious or compromised | protected resource might be counterfeit, malicious, or compromised | |||
and plays received tokens against other protected resources to gain | and plays received tokens against other protected resources to gain | |||
unauthorized access. Audience restricted access tokens | unauthorized access. Audience-restricted access tokens | |||
(e.g., using the JWT <xref target="RFC7519"></xref> <tt>aud</tt> claim) can | (e.g., using the JWT <xref target="RFC7519"></xref> <tt>aud</tt> claim) can | |||
prevent such misuse, however, doing so in practice has proven to be | prevent such misuse. However, doing so in practice has proven to be | |||
prohibitively cumbersome for many deployments (even despite extensions such as < | prohibitively cumbersome for many deployments (despite extensions such as <xref | |||
xref target="RFC8707"></xref>). | target="RFC8707"></xref>). | |||
Sender-constraining access tokens is a more robust and straightforward | Sender-constraining access tokens is a more robust and straightforward | |||
mechanism to prevent such token replay at a different endpoint and DPoP | mechanism to prevent such token replay at a different endpoint, and DPoP | |||
is an accessible application layer means of doing so.</t> | is an accessible application-layer means of doing so.</t> | |||
<t>Due to the potential for cross-site scripting (XSS), browser-based | <t>Due to the potential for cross-site scripting (XSS), browser-based | |||
OAuth clients bring to bear added considerations with respect to protecting | OAuth clients bring to bear added considerations with respect to protecting | |||
tokens. The most straightforward XSS-based attack is for an attacker to | tokens. The most straightforward XSS-based attack is for an attacker to | |||
exfiltrate a token and use it themselves completely independent of the | exfiltrate a token and use it themselves completely independent of the | |||
legitimate client. A stolen access token is used for protected | legitimate client. A stolen access token is used for protected | |||
resource access and a stolen refresh token for obtaining new access tokens. | resource access, and a stolen refresh token is used for obtaining new access tok ens. | |||
If the private key is non-extractable (as is possible with <xref target="W3C.Web CryptoAPI"></xref>), | If the private key is non-extractable (as is possible with <xref target="W3C.Web CryptoAPI"></xref>), | |||
DPoP renders exfiltrated tokens alone unusable.</t> | DPoP renders exfiltrated tokens alone unusable.</t> | |||
<t>XSS vulnerabilities also allow an attacker to execute code in the context of | <t>XSS vulnerabilities also allow an attacker to execute code in the context of | |||
the browser-based client application and maliciously use a token indirectly | the browser-based client application and maliciously use a token indirectly | |||
through the client. That execution context has access to utilize the signing | through the client. That execution context has access to utilize the signing | |||
key and thus can produce DPoP proofs to use in conjunction with the token. | key; thus, it can produce DPoP proofs to use in conjunction with the token. | |||
At this application layer there is most likely no feasible defense against | At this application layer, there is most likely no feasible defense against | |||
this threat except generally preventing XSS, therefore it is considered | this threat except generally preventing XSS; therefore, it is considered | |||
out of scope for DPoP.</t> | out of scope for DPoP.</t> | |||
<t>Malicious XSS code executed in the context of the browser-based client | <t>Malicious XSS code executed in the context of the browser-based client | |||
application is also in a position to create DPoP proofs with timestamp values in | application is also in a position to create DPoP proofs with timestamp values in | |||
the future and exfiltrate them in conjunction with a token. These stolen | the future and exfiltrate them in conjunction with a token. These stolen | |||
artifacts can later be used independent of the client application to | artifacts can later be used independent of the client application to | |||
access protected resources. To prevent this, servers can optionally require | access protected resources. To prevent this, servers can optionally require | |||
clients to include a server-chosen value into the proof that cannot be predicted | clients to include a server-chosen value into the proof that cannot be predicted | |||
by an attacker (nonce). In the absence of the optional nonce, the impact of | by an attacker (nonce). In the absence of the optional nonce, the impact of | |||
pre-computed DPoP proofs is limited somewhat by the proof being bound to an | pre-computed DPoP proofs is limited somewhat by the proof being bound to an | |||
access token on protected resource access. Because a proof covering an access | access token on protected resource access. Because a proof covering an access | |||
token that does not yet exist cannot feasibly be created, access tokens obtained | token that does not yet exist cannot feasibly be created, access tokens obtained | |||
with an exfiltrated refresh token and pre-computed proofs will be unusable.</t> | with an exfiltrated refresh token and pre-computed proofs will be unusable.</t> | |||
<t>Additional security considerations are discussed in <xref target="Security">< /xref>.</t> | <t>Additional security considerations are discussed in <xref target="Security">< /xref>.</t> | |||
</section> | </section> | |||
<section anchor="concept"><name>Concept</name> | <section anchor="concept"><name>Concept</name> | |||
<t>The main data structure introduced by this specification is a DPoP | <t>The main data structure introduced by this specification is a DPoP | |||
proof JWT, described in detail below, which is sent as a header in an | proof JWT that is sent as a header in an | |||
HTTP request. A client uses a DPoP proof JWT to prove | HTTP request, as described in detail below. A client uses a DPoP proof JWT to pr | |||
ove | ||||
the possession of a private key corresponding to a certain public key.</t> | the possession of a private key corresponding to a certain public key.</t> | |||
<t>Roughly speaking, a DPoP proof is a signature over some | <t>Roughly speaking, a DPoP proof is a signature over:</t> | |||
data of the HTTP request to which it is attached, a timestamp, a unique identifi | <ul> | |||
er, an optional server-provided nonce, | <li>some data of the | |||
and a hash of the associated access token when an access token is present within | HTTP request to which it is attached,</li> | |||
the request.</t> | <li>a timestamp,</li> | |||
<li>a unique | ||||
identifier,</li> | ||||
<li>an optional server-provided nonce, and</li> | ||||
<li>a hash of the | ||||
associated access token when an access token is present within the | ||||
request.</li> | ||||
</ul> | ||||
<figure anchor="basic-flow"><name>Basic DPoP Flow </name> | <figure anchor="basic-flow"><name>Basic DPoP Flow </name> | |||
<sourcecode type="ascii-art">+--------+ | <artwork type="ascii-art"><![CDATA[ | |||
+---------------+ | +--------+ +---------------+ | |||
| |--(A)-- Token Request ------------------->| | | | |--(A)-- Token Request ------------------->| | | |||
| Client | (DPoP Proof) | Authorization | | | Client | (DPoP Proof) | Authorization | | |||
| | | Server | | | | | Server | | |||
| |<-(B)-- DPoP-bound Access Token ----------| | | | |<-(B)-- DPoP-Bound Access Token ----------| | | |||
| | (token_type=DPoP) +---------------+ | | | (token_type=DPoP) +---------------+ | |||
| | | | | | |||
| | | | | | |||
| | +---------------+ | | | +---------------+ | |||
| |--(C)-- DPoP-bound Access Token --------->| | | | |--(C)-- DPoP-Bound Access Token --------->| | | |||
| | (DPoP Proof) | Resource | | | | (DPoP Proof) | Resource | | |||
| | | Server | | | | | Server | | |||
| |<-(D)-- Protected Resource ---------------| | | | |<-(D)-- Protected Resource ---------------| | | |||
| | +---------------+ | | | +---------------+ | |||
+--------+ | +--------+ | |||
</sourcecode> | ]]></artwork> | |||
</figure> | </figure> | |||
<t>The basic steps of an OAuth flow with DPoP (without the optional nonce) are s hown in <xref target="basic-flow"></xref>:</t> | <t>The basic steps of an OAuth flow with DPoP (without the optional nonce) are s hown in <xref target="basic-flow"></xref>.</t> | |||
<ul spacing="compact"> | <ol type="A" spacing="normal"> | |||
<li>(A) In the Token Request, the client sends an authorization grant | <li>In the token request, the client sends an authorization grant | |||
(e.g., an authorization code, refresh token, etc.)<br /> | (e.g., an authorization code, refresh token, etc.) | |||
to the authorization server in order to obtain an access token | to the authorization server in order to obtain an access token | |||
(and potentially a refresh token). The client attaches a DPoP | (and potentially a refresh token). The client attaches a DPoP | |||
proof to the request in an HTTP header.</li> | proof to the request in an HTTP header.</li> | |||
<li>(B) The authorization server binds (sender-constrains) the access token to t he | <li>The authorization server binds (sender-constrains) the access token to the | |||
public key claimed by the client in the DPoP proof; that is, the access token ca nnot | public key claimed by the client in the DPoP proof; that is, the access token ca nnot | |||
be used without proving possession of the respective private key. | be used without proving possession of the respective private key. | |||
If a refresh token is issued to a public client, it too is | If a refresh token is issued to a public client, it is also bound to the public | |||
bound to the public key of the DPoP proof.</li> | key of the DPoP proof.</li> | |||
<li>(C) To use the access token, the client has to prove | <li>To use the access token, the client has to prove | |||
possession of the private key by, again, adding a header to the | possession of the private key by, again, adding a header to the | |||
request that carries a DPoP proof for that request. The resource server needs to | request that carries a DPoP proof for that request. The resource server needs to | |||
receive information about the public key to which the access token is bound. Thi s | receive information about the public key to which the access token is bound. Thi s | |||
information may be encoded directly into the access token (for | information may be encoded directly into the access token (for | |||
JWT structured access tokens) or provided via token | JWT-structured access tokens) or provided via token | |||
introspection endpoint (not shown). | introspection endpoint (not shown). | |||
The resource server verifies that the public key to which the | The resource server verifies that the public key to which the | |||
access token is bound matches the public key of the DPoP proof. | access token is bound matches the public key of the DPoP proof. | |||
It also verifies that the access token hash in the DPoP proof matches the | It also verifies that the access token hash in the DPoP proof matches the | |||
access token presented in the request.</li> | access token presented in the request.</li> | |||
<li>(D) The resource server refuses to serve the request if the | <li>The resource server refuses to serve the request if the | |||
signature check fails or the data in the DPoP proof is wrong, | signature check fails or if the data in the DPoP proof is wrong, | |||
e.g., the target URI does not match the URI claim in the DPoP | e.g., the target URI does not match the URI claim in the DPoP | |||
proof JWT. The access token itself, of course, must also be | proof JWT. The access token itself, of course, must also be | |||
valid in all other respects.</li> | valid in all other respects.</li> | |||
</ul> | </ol> | |||
<t>The DPoP mechanism presented herein is not a client authentication method. | <t>The DPoP mechanism presented herein is not a client authentication method. | |||
In fact, a primary use case of DPoP is for public clients (e.g., single page | In fact, a primary use case of DPoP is for public clients (e.g., single-page | |||
applications and applications on a user's device) that do not use client authent ication. Nonetheless, DPoP | applications and applications on a user's device) that do not use client authent ication. Nonetheless, DPoP | |||
is designed such that it is compatible with <tt>private_key_jwt</tt> and all | is designed to be compatible with <tt>private_key_jwt</tt> and all | |||
other client authentication methods.</t> | other client authentication methods.</t> | |||
<t>DPoP does not directly ensure message integrity but relies on the TLS | <t>DPoP does not directly ensure message integrity, but it relies on the TLS | |||
layer for that purpose. See <xref target="Security"></xref> for details.</t> | layer for that purpose. See <xref target="Security"></xref> for details.</t> | |||
</section> | </section> | |||
<section anchor="the-proof"><name>DPoP Proof JWTs</name> | <section anchor="the-proof"><name>DPoP Proof JWTs</name> | |||
<t>DPoP introduces the concept of a DPoP proof, which is a JWT created by | <t>DPoP introduces the concept of a DPoP proof, which is a JWT created by | |||
the client and sent with an HTTP request using the <tt>DPoP</tt> header field. | the client and sent with an HTTP request using the <tt>DPoP</tt> header field. | |||
Each HTTP request requires a unique DPoP proof.</t> | Each HTTP request requires a unique DPoP proof.</t> | |||
<t>A valid DPoP proof demonstrates to the server that the client holds the priva te | <t>A valid DPoP proof demonstrates to the server that the client holds the priva te | |||
key that was used to sign the DPoP proof JWT. This enables authorization servers to bind | key that was used to sign the DPoP proof JWT. This enables authorization servers to bind | |||
issued tokens to the corresponding public key (as described in <xref target="acc ess-token-request"></xref>) | issued tokens to the corresponding public key (as described in <xref target="acc ess-token-request"></xref>) | |||
and for resource servers to verify the key-binding of tokens that | and enables resource servers to verify the key-binding of tokens that | |||
it receives (see <xref target="http-auth-scheme"></xref>), which prevents said t okens from | it receives (see <xref target="http-auth-scheme"></xref>), which prevents said t okens from | |||
being used by any entity that does not have access to the private key.</t> | being used by any entity that does not have access to the private key.</t> | |||
<t>The DPoP proof demonstrates possession of a key and, by itself, is not | <t>The DPoP proof demonstrates possession of a key and, by itself, is not | |||
an authentication or access control mechanism. When presented | an authentication or access control mechanism. When presented | |||
in conjunction with a key-bound access token as described in <xref target="http- auth-scheme"></xref>, | in conjunction with a key-bound access token as described in <xref target="http- auth-scheme"></xref>, | |||
the DPoP proof provides additional assurance about the legitimacy of the client | the DPoP proof provides additional assurance about the legitimacy of the client | |||
to present the access token. However, a valid DPoP proof JWT is not sufficient a lone | to present the access token. However, a valid DPoP proof JWT is not sufficient a lone | |||
to make access control decisions.</t> | to make access control decisions.</t> | |||
<section anchor="the-dpop-http-header"><name>The DPoP HTTP Header</name> | <section anchor="the-dpop-http-header"><name>The DPoP HTTP Header</name> | |||
<t>A DPoP proof is included in an HTTP request using the following request heade r field.</t> | <t>A DPoP proof is included in an HTTP request using the following request heade r field.</t> | |||
<dl spacing="compact"> | <dl spacing="compact"> | |||
<dt><tt>DPoP</tt></dt> | <dt><tt>DPoP</tt>:</dt> | |||
<dd>A JWT that adheres to the structure and syntax of <xref target="DPoP-Proof-S yntax"></xref>.</dd> | <dd>A JWT that adheres to the structure and syntax of <xref target="DPoP-Proof-S yntax"></xref>.</dd> | |||
</dl> | </dl> | |||
<t><xref target="dpop-proof-jwt"></xref> shows an example DPoP HTTP header field | <t><xref target="dpop-proof-jwt"></xref> shows an example DPoP HTTP header field | |||
(with '\' line wrapping per RFC 8792).</t> | . The example uses "\" line wrapping per <xref target="RFC8792"/>.</t> | |||
<figure anchor="dpop-proof-jwt"><name>Example <tt>DPoP</tt> header </name> | <figure anchor="dpop-proof-jwt"><name>Example <tt>DPoP</tt> Header </name> | |||
<artwork>DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | <sourcecode type="http-message">DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2Ii | |||
wiandrIjp7Imt0eSI6Ik\ | ||||
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | |||
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | |||
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ | QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ | |||
oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ | oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ | |||
WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\ | WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\ | |||
4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg | 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>Note that per <xref target="RFC9110"></xref> header field names are case-inse | <t>Note that per <xref target="RFC9110"></xref>, header field names are case ins | |||
nsitive; | ensitive; thus, <tt>DPoP</tt>, <tt>DPOP</tt>, <tt>dpop</tt>, etc., are all valid | |||
so <tt>DPoP</tt>, <tt>DPOP</tt>, <tt>dpop</tt>, etc., are all valid and equivale | and equivalent header | |||
nt header | field names. However, case is significant in the header field value.</t> | |||
field names. Case is significant in the header field value, however.</t> | ||||
<t>The <tt>DPoP</tt> HTTP header field value | <t>The <tt>DPoP</tt> HTTP header field value | |||
uses the <tt>token68</tt> syntax defined in Section 11.2 of <xref target="RFC911 | uses the token68 syntax defined in <xref target="RFC9110" sectionFormat="of" sec | |||
0"></xref> | tion="11.2"></xref> and is repeated below in <xref target="dpop-header-abnf"></x | |||
(repeated below in <xref target="dpop-header-abnf"></xref> for ease of reference | ref> for ease of reference.</t> | |||
).</t> | ||||
<figure anchor="dpop-header-abnf"><name>DPoP header field ABNF </name> | <figure anchor="dpop-header-abnf"><name>DPoP Header Field ABNF</name> | |||
<artwork> DPoP = token68 | <sourcecode type="abnf"><![CDATA[ | |||
token68 = 1*( ALPHA / DIGIT / | DPoP = token68 | |||
"-" / "." / "_" / "~" | token68 = 1*( ALPHA / DIGIT / | |||
/ "+" / "/" ) *"=" | "-" / "." / "_" / "~" / "+" / "/" ) *"=" | |||
</artwork> | ]]></sourcecode></figure> | |||
</figure> | ||||
</section> | </section> | |||
<section anchor="DPoP-Proof-Syntax"><name>DPoP Proof JWT Syntax</name> | <section anchor="DPoP-Proof-Syntax"><name>DPoP Proof JWT Syntax</name> | |||
<t>A DPoP proof is a JWT (<xref target="RFC7519"></xref>) that is signed (using | <t>A DPoP proof is a JWT <xref target="RFC7519"></xref> that is signed (using JS | |||
JSON Web Signature (JWS) | ON Web Signature (JWS) <xref target="RFC7515"></xref>) with a private key chosen | |||
<xref target="RFC7515"></xref>) with a private key chosen by the client (see bel | by the client (see below). The | |||
ow). The | JOSE Header of a DPoP JWT <bcp14>MUST</bcp14> contain at least the following par | |||
JOSE header of a DPoP JWT MUST contain at least the following parameters:</t> | ameters:</t> | |||
<dl spacing="normal"> | ||||
<ul spacing="compact"> | <dt><tt>typ</tt>:</dt><dd>A field with the value <tt>dpop+jwt</tt>, which explic | |||
<li><tt>typ</tt>: with value <tt>dpop+jwt</tt>, which explicitly types the DPoP | itly types the DPoP proof JWT as recommended in <xref target="RFC8725" sectionFo | |||
proof JWT as recommended in <xref target="RFC8725" sectionFormat="of" relative=" | rmat="of" section="3.11"></xref>.</dd> | |||
#" section="3.11"></xref>.</li> | <dt><tt>alg</tt>:</dt><dd>An identifier for a JWS asymmetric digital signature a | |||
<li><tt>alg</tt>: an identifier for a JWS asymmetric digital signature algorithm | lgorithm from <xref target="IANA.JOSE.ALGS"></xref>. It | |||
from <xref target="IANA.JOSE.ALGS"></xref>. | <bcp14>MUST NOT</bcp14> be <tt>none</tt> or an identifier for a symmetric algori | |||
MUST NOT be <tt>none</tt> or an identifier for a symmetric algorithm (MAC).</li> | thm (Message Authentication Code (MAC)).</dd> | |||
<li><tt>jwk</tt>: representing the public key chosen by the client, in JSON Web | <dt><tt>jwk</tt>:</dt><dd>Represents the public key chosen by the client in JSON | |||
Key (JWK) <xref target="RFC7517"></xref> | Web Key (JWK) <xref target="RFC7517"/> format as defined in <xref target="RFC75 | |||
format, as defined in Section 4.1.3 of <xref target="RFC7515"></xref>. | 15" sectionFormat="of" section="4.1.3"></xref>. It | |||
MUST NOT contain a private key.</li> | <bcp14>MUST NOT</bcp14> contain a private key.</dd> | |||
</ul> | </dl> | |||
<t>The payload of a DPoP proof MUST contain at least the following claims:</t> | <t>The payload of a DPoP proof <bcp14>MUST</bcp14> contain at least the followin | |||
g claims:</t> | ||||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li><tt>jti</tt>: Unique identifier for the DPoP proof JWT. | <dt><tt>jti</tt>:</dt><dd>Unique identifier for the DPoP proof JWT. | |||
The value MUST be assigned such that there is a negligible | The value <bcp14>MUST</bcp14> be assigned such that there is a negligible | |||
probability that the same value will be assigned to any | probability that the same value will be assigned to any | |||
other DPoP proof used in the same context during the time window of validity. | other DPoP proof used in the same context during the time window of validity. | |||
Such uniqueness can be accomplished by encoding (base64url or any other | Such uniqueness can be accomplished by encoding (base64url or any other | |||
suitable encoding) at least 96 bits of | suitable encoding) at least 96 bits of | |||
pseudorandom data or by using a version 4 UUID string according to <xref target= "RFC4122"></xref>. | pseudorandom data or by using a version 4 Universally Unique Identifier (UUID) s tring according to <xref target="RFC4122"></xref>. | |||
The <tt>jti</tt> can be used by the server for replay | The <tt>jti</tt> can be used by the server for replay | |||
detection and prevention, see <xref target="Token_Replay"></xref>.</li> | detection and prevention; see <xref target="Token_Replay"></xref>.</dd> | |||
<li><tt>htm</tt>: The value of the HTTP method (Section 9.1 of <xref target="RFC | <dt><tt>htm</tt>:</dt><dd>The value of the HTTP method (<xref target="RFC9110" s | |||
9110"></xref>) of the | ectionFormat="of" section="9.1"></xref>) of the | |||
request to which the JWT is attached.</li> | request to which the JWT is attached.</dd> | |||
<li><tt>htu</tt>: The HTTP target URI (<xref target="RFC9110" sectionFormat="of" | <dt><tt>htu</tt>:</dt><dd>The HTTP target URI (<xref target="RFC9110" sectionFor | |||
relative="#" section="7.1"></xref>), without query and fragment | mat="of" section="7.1"></xref>) of the request to which the JWT is attached, wit | |||
parts, of the request to which the JWT is attached.</li> | hout query and fragment | |||
<li><tt>iat</tt>: Creation timestamp of the JWT (<xref target="RFC7519"></xref>, | parts.</dd> | |||
section 4.1.6]).</li> | <dt><tt>iat</tt>:</dt><dd>Creation timestamp of the JWT (<xref target="RFC7519" | |||
</ul> | sectionFormat="of" section="4.1.6"></xref>).</dd> | |||
<t>When the DPoP proof is used in conjunction with the presentation of an access | </dl> | |||
token in protected resource access, see | <t>When the DPoP proof is used in conjunction with the presentation of an access | |||
<xref target="protected-resource-access"></xref>, the DPoP proof MUST also conta | token in protected resource access (see | |||
in the following claim:</t> | <xref target="protected-resource-access"></xref>), the DPoP proof <bcp14>MUST</b | |||
cp14> also contain the following claim:</t> | ||||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li><tt>ath</tt>: hash of the access token. | <dt><tt>ath</tt>:</dt><dd>Hash of the access token. | |||
The value MUST be the result of a base64url encoding (as defined in <xref target | The value <bcp14>MUST</bcp14> be the result of a base64url encoding (as defined | |||
="RFC7515" sectionFormat="of" relative="#" section="2"></xref>) the SHA-256 <xre | in <xref target="RFC7515" sectionFormat="of" section="2"></xref>) the SHA-256 <x | |||
f target="SHS"></xref> | ref target="SHS"></xref> | |||
hash of the ASCII encoding of the associated access token's value.</li> | hash of the ASCII encoding of the associated access token's value.</dd> | |||
</ul> | </dl> | |||
<t>When the authentication server or resource server provides a <tt>DPoP-Nonce</ tt> HTTP header | <t>When the authentication server or resource server provides a <tt>DPoP-Nonce</ tt> HTTP header | |||
in a response (see <xref target="ASNonce"></xref>, <xref target="RSNonce"></xref >), the DPoP proof MUST also contain | in a response (see Sections <xref target="ASNonce" format="counter"></xref> and <xref target="RSNonce" format="counter"></xref>), the DPoP proof <bcp14>MUST</bc p14> also contain | |||
the following claim:</t> | the following claim:</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li><tt>nonce</tt>: A recent nonce provided via the <tt>DPoP-Nonce</tt> HTTP he | <dt><tt>nonce</tt>:</dt><dd>A recent nonce provided via the <tt>DPoP-Nonce</tt> | |||
ader.</li> | HTTP header.</dd> | |||
</ul> | </dl> | |||
<t>A DPoP proof MAY contain other JOSE header parameters or claims as defined by | <t>A DPoP proof <bcp14>MAY</bcp14> contain other JOSE Header Parameters or claim | |||
extension, | s as defined by extension, | |||
profile, or deployment specific requirements.</t> | profile, or deployment-specific requirements.</t> | |||
<t><xref target="dpop-proof"></xref> is a conceptual example showing the decoded content of the DPoP | <t><xref target="dpop-proof"></xref> is a conceptual example showing the decoded content of the DPoP | |||
proof in <xref target="dpop-proof-jwt"></xref>. The JSON of the JWT header and p ayload are shown, | proof in <xref target="dpop-proof-jwt"></xref>. The JSON of the JWT header and p ayload are shown, | |||
but the signature part is omitted. As usual, line breaks and extra spaces | but the signature part is omitted. As usual, line breaks and extra spaces | |||
are included for formatting and readability.</t> | are included for formatting and readability.</t> | |||
<figure anchor="dpop-proof"><name>Example JWT content of a <tt>DPoP</tt> proof < | <figure anchor="dpop-proof"><name>Example JWT Content of a <tt>DPoP</tt> Proof</ | |||
/name> | name> | |||
<artwork>{ | <sourcecode>{ | |||
"typ":"dpop+jwt", | "typ":"dpop+jwt", | |||
"alg":"ES256", | "alg":"ES256", | |||
"jwk": { | "jwk": { | |||
"kty":"EC", | "kty":"EC", | |||
"x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs", | "x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs", | |||
"y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA", | "y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA", | |||
"crv":"P-256" | "crv":"P-256" | |||
} | } | |||
} | } | |||
. | . | |||
{ | { | |||
"jti":"-BwC3ESc6acc2lTc", | "jti":"-BwC3ESc6acc2lTc", | |||
"htm":"POST", | "htm":"POST", | |||
"htu":"https://server.example.com/token", | "htu":"https://server.example.com/token", | |||
"iat":1562262616 | "iat":1562262616 | |||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>Of the HTTP request, only the HTTP method and URI are | <t>Of the HTTP request, only the HTTP method and URI are | |||
included in the DPoP JWT, and therefore only these two message parts | included in the DPoP JWT; therefore, only these two message parts | |||
are covered by the DPoP proof. | are covered by the DPoP proof. | |||
The idea is sign just enough of the HTTP data to | The idea is to sign just enough of the HTTP data to | |||
provide reasonable proof-of-possession with respect to the HTTP request. | provide reasonable proof of possession with respect to the HTTP request. | |||
This design approach of using only a minimal subset of the HTTP header | This design approach of using only a minimal subset of the HTTP header | |||
data is to avoid the substantial difficulties inherent in attempting to | data is to avoid the substantial difficulties inherent in attempting to | |||
normalize HTTP messages. | normalize HTTP messages. | |||
Nonetheless, DPoP proofs can be extended to contain other information of the | Nonetheless, DPoP proofs can be extended to contain other information of the | |||
HTTP request (see also <xref target="request_integrity"></xref>).</t> | HTTP request (see also <xref target="request_integrity"></xref>).</t> | |||
</section> | </section> | |||
<section anchor="checking"><name>Checking DPoP Proofs</name> | <section anchor="checking"><name>Checking DPoP Proofs</name> | |||
<t>To validate a DPoP proof, the receiving server MUST ensure that</t> | <t>To validate a DPoP proof, the receiving server <bcp14>MUST</bcp14> ensure the following:</t> | |||
<ol spacing="compact"> | <ol spacing="compact"> | |||
<li>there is not more than one <tt>DPoP</tt> HTTP request header field,</li> | <li>There is not more than one <tt>DPoP</tt> HTTP request header field.</li> | |||
<li>the DPoP HTTP request header field value is a single well-formed JWT,</li> | <li>The DPoP HTTP request header field value is a single and well-formed JWT.</l | |||
<li>all required claims per <xref target="DPoP-Proof-Syntax"></xref> are contain | i> | |||
ed in the JWT,</li> | <li>All required claims per <xref target="DPoP-Proof-Syntax"></xref> are contain | |||
<li>the <tt>typ</tt> JOSE header parameter has the value <tt>dpop+jwt</tt>,</li> | ed in the JWT.</li> | |||
<li>the <tt>alg</tt> JOSE header parameter indicates a registered asymmetric dig | <li>The <tt>typ</tt> JOSE Header Parameter has the value <tt>dpop+jwt</tt>.</li> | |||
ital | <li>The <tt>alg</tt> JOSE Header Parameter indicates a registered asymmetric dig | |||
ital | ||||
signature algorithm <xref target="IANA.JOSE.ALGS"></xref>, is not <tt>none</tt>, is supported by the | signature algorithm <xref target="IANA.JOSE.ALGS"></xref>, is not <tt>none</tt>, is supported by the | |||
application, and is acceptable per local policy,</li> | application, and is acceptable per local policy.</li> | |||
<li>the JWT signature verifies with the public key contained in the <tt>jwk</tt> | <li>The JWT signature verifies with the public key contained in the <tt>jwk</tt> | |||
JOSE header parameter,</li> | JOSE Header Parameter.</li> | |||
<li>the <tt>jwk</tt> JOSE header parameter does not contain a private key,</li> | <li>The <tt>jwk</tt> JOSE Header Parameter does not contain a private key.</li> | |||
<li>the <tt>htm</tt> claim matches the HTTP method of the current request,</li> | <li>The <tt>htm</tt> claim matches the HTTP method of the current request.</li> | |||
<li>the <tt>htu</tt> claim matches the HTTP URI value for the HTTP | <li>The <tt>htu</tt> claim matches the HTTP URI value for the HTTP | |||
request in which the JWT was received, ignoring any query and | request in which the JWT was received, ignoring any query and | |||
fragment parts,</li> | fragment parts.</li> | |||
<li>if the server provided a nonce value to the client, | <li>If the server provided a nonce value to the client, | |||
the <tt>nonce</tt> claim matches the server-provided nonce value,</li> | the <tt>nonce</tt> claim matches the server-provided nonce value.</li> | |||
<li>the creation time of the JWT, as determined by either the <tt>iat</tt> claim | <li>The creation time of the JWT, as determined by either the <tt>iat</tt> claim | |||
or a server managed timestamp via the <tt>nonce</tt> claim, is within an accept | or a server managed timestamp via the <tt>nonce</tt> claim, is within an accept | |||
able window (see <xref target="Token_Replay"></xref>),</li> | able window (see <xref target="Token_Replay"></xref>).</li> | |||
<li><t>if presented to a protected resource in conjunction with an access token, | <li><t>If presented to a protected resource in conjunction with an access token, | |||
</t> | </t> | |||
<ul spacing="compact"> | <ul spacing="compact"> | |||
<li>ensure that the value of the <tt>ath</tt> claim equals the hash of that acce ss token,</li> | <li>ensure that the value of the <tt>ath</tt> claim equals the hash of that acce ss token, and</li> | |||
<li>confirm that the public key to which the access token is bound matches the p ublic key from the DPoP proof.</li> | <li>confirm that the public key to which the access token is bound matches the p ublic key from the DPoP proof.</li> | |||
</ul></li> | </ul></li> | |||
</ol> | </ol> | |||
<t>To reduce the likelihood of false negatives, | <t>To reduce the likelihood of false negatives, | |||
servers SHOULD employ Syntax-Based Normalization (<xref target="RFC3986" section | servers <bcp14>SHOULD</bcp14> employ syntax-based normalization (<xref target="R | |||
Format="of" relative="#" section="6.2.2"></xref>) and Scheme-Based | FC3986" sectionFormat="of" section="6.2.2"></xref>) and scheme-based | |||
Normalization (<xref target="RFC3986" sectionFormat="of" relative="#" section="6 | normalization (<xref target="RFC3986" sectionFormat="of" section="6.2.3"></xref> | |||
.2.3"></xref>) before comparing the <tt>htu</tt> claim.</t> | ) before comparing the <tt>htu</tt> claim.</t> | |||
<t>These checks may be performed in any order.</t> | <t>These checks may be performed in any order.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="access-token-request"><name>DPoP Access Token Request</name> | <section anchor="access-token-request"><name>DPoP Access Token Request</name> | |||
<t>To request an access token that is bound to a public key using DPoP, the clie nt MUST | <t>To request an access token that is bound to a public key using DPoP, the clie nt <bcp14>MUST</bcp14> | |||
provide a valid DPoP proof JWT in a <tt>DPoP</tt> header when making an access t oken | provide a valid DPoP proof JWT in a <tt>DPoP</tt> header when making an access t oken | |||
request to the authorization server's token endpoint. This is applicable for all | request to the authorization server's token endpoint. This is applicable for all | |||
access token requests regardless of grant type (including, for example, | access token requests regardless of grant type (e.g., | |||
the common <tt>authorization_code</tt> and <tt>refresh_token</tt> grant types bu | the common <tt>authorization_code</tt> and <tt>refresh_token</tt> grant types an | |||
t also extension grants | d extension grants | |||
such as the JWT authorization grant <xref target="RFC7523"></xref>). The HTTP re quest shown in | such as the JWT authorization grant <xref target="RFC7523"></xref>). The HTTP re quest shown in | |||
<xref target="token-request-code"></xref> illustrates such an access | <xref target="token-request-code"></xref> illustrates such an access | |||
token request using an authorization code grant with a DPoP proof JWT | token request using an authorization code grant with a DPoP proof JWT | |||
in the <tt>DPoP</tt> header | in the <tt>DPoP</tt> header. <xref target="token-request-code"/> uses "\" line w | |||
(with '\' line wrapping per RFC 8792).</t> | rapping per <xref target="RFC8792"/>.</t> | |||
<figure anchor="token-request-code"><name>Token Request for a DPoP sender-constr | <figure anchor="token-request-code"><name>Token Request for a DPoP Sender-Constr | |||
ained token using an authorization code </name> | ained Token Using an Authorization Code</name> | |||
<artwork>POST /token HTTP/1.1 | <sourcecode type="http-message"><![CDATA[POST /token HTTP/1.1 | |||
Host: server.example.com | Host: server.example.com | |||
Content-Type: application/x-www-form-urlencoded | Content-Type: application/x-www-form-urlencoded | |||
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | |||
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | |||
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | |||
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ | QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ | |||
oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ | oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ | |||
WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\ | WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\ | |||
4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg | 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg | |||
grant_type=authorization_code\ | grant_type=authorization_code\ | |||
&client_id=s6BhdRkqt\ | &client_id=s6BhdRkqt\ | |||
&code=SplxlOBeZQQYbYS6WxSbIA | &code=SplxlOBeZQQYbYS6WxSbIA | |||
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\ | &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\ | |||
&code_verifier=bEaL42izcC-o-xBk0K2vuJ6U-y1p9r_wW2dFWIWgjz- | &code_verifier=bEaL42izcC-o-xBk0K2vuJ6U-y1p9r_wW2dFWIWgjz- | |||
</artwork> | ]]></sourcecode> | |||
</figure> | </figure> | |||
<t>The <tt>DPoP</tt> HTTP header field MUST contain a valid DPoP proof JWT. | <t>The <tt>DPoP</tt> HTTP header field <bcp14>MUST</bcp14> contain a valid DPoP proof JWT. | |||
If the DPoP proof is invalid, the authorization server issues an error | If the DPoP proof is invalid, the authorization server issues an error | |||
response per Section 5.2 of <xref target="RFC6749"></xref> with <tt>invalid_dpop _proof</tt> as the | response per <xref target="RFC6749" sectionFormat="of" section="5.2"></xref> wit h <tt>invalid_dpop_proof</tt> as the | |||
value of the <tt>error</tt> parameter.</t> | value of the <tt>error</tt> parameter.</t> | |||
<t>To sender-constrain the access token, after checking the validity of the | <t>To sender-constrain the access token after checking the validity of the | |||
DPoP proof, the authorization server associates the issued access token with the | DPoP proof, the authorization server associates the issued access token with the | |||
public key from the DPoP proof, which can be accomplished as described in <xref target="Confirmation"></xref>. | public key from the DPoP proof, which can be accomplished as described in <xref target="Confirmation"></xref>. | |||
A <tt>token_type</tt> of <tt>DPoP</tt> MUST be included in the access token | A <tt>token_type</tt> of <tt>DPoP</tt> <bcp14>MUST</bcp14> be included in the ac cess token | |||
response to signal to the client that the access token was bound to | response to signal to the client that the access token was bound to | |||
its DPoP key and can be used as described in <xref target="http-auth-scheme"></x ref>. | its DPoP key and can be used as described in <xref target="http-auth-scheme"></x ref>. | |||
The example response shown in <xref target="token-response"></xref> illustrates such a | The example response shown in <xref target="token-response"></xref> illustrates such a | |||
response.</t> | response.</t> | |||
<figure anchor="token-response"><name>Access Token Response </name> | <figure anchor="token-response"><name>Access Token Response </name> | |||
<artwork>HTTP/1.1 200 OK | <sourcecode type="http-message">HTTP/1.1 200 OK | |||
Content-Type: application/json | Content-Type: application/json | |||
Cache-Control: no-store | Cache-Control: no-store | |||
{ | { | |||
"access_token": "Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU&quo | "access_token": "Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU", | |||
t;, | "token_type": "DPoP", | |||
"token_type": "DPoP", | "expires_in": 2677, | |||
"expires_in": 2677, | "refresh_token": "Q..Zkm29lexi8VnWg2zPW1x-tgGad0Ibc3s3EwM_Ni4-g" | |||
"refresh_token": "Q..Zkm29lexi8VnWg2zPW1x-tgGad0Ibc3s3EwM_Ni4-g& | ||||
quot; | ||||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>The example response in <xref target="token-response"></xref> includes a refr esh token which the | <t>The example response in <xref target="token-response"></xref> includes a refr esh token that the | |||
client can use to obtain a new access token when the previous one expires. | client can use to obtain a new access token when the previous one expires. | |||
Refreshing an access token is a token request using the <tt>refresh_token</tt> | Refreshing an access token is a token request using the <tt>refresh_token</tt> | |||
grant type made to the authorization server's token endpoint. As with | grant type made to the authorization server's token endpoint. As with | |||
all access token requests, the client makes it a DPoP request by including | all access token requests, the client makes it a DPoP request by including | |||
a DPoP proof, as shown in the <xref target="token-request-rt"></xref> example | a DPoP proof, as shown in <xref target="token-request-rt"></xref>. <xref target= | |||
(with '\' line wrapping per RFC 8792).</t> | "token-request-rt"/> uses "\" line wrapping per <xref target="RFC8792"/>.</t> | |||
<figure anchor="token-request-rt"><name>Token Request for a DPoP-bound Token usi | <figure anchor="token-request-rt"><name>Token Request for a DPoP-Bound Token Usi | |||
ng a Refresh Token </name> | ng a Refresh Token </name> | |||
<artwork>POST /token HTTP/1.1 | <sourcecode type="http-message"><![CDATA[POST /token HTTP/1.1 | |||
Host: server.example.com | Host: server.example.com | |||
Content-Type: application/x-www-form-urlencoded | Content-Type: application/x-www-form-urlencoded | |||
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | |||
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | |||
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | |||
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ | QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ | |||
oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ | oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ | |||
WF0IjoxNTYyMjY1Mjk2fQ.pAqut2IRDm_De6PR93SYmGBPXpwrAk90e8cP2hjiaG5Qs\ | WF0IjoxNTYyMjY1Mjk2fQ.pAqut2IRDm_De6PR93SYmGBPXpwrAk90e8cP2hjiaG5Qs\ | |||
GSuKDYW7_X620BxqhvYC8ynrrvZLTk41mSRroapUA | GSuKDYW7_X620BxqhvYC8ynrrvZLTk41mSRroapUA | |||
grant_type=refresh_token\ | grant_type=refresh_token\ | |||
&client_id=s6BhdRkqt\ | &client_id=s6BhdRkqt\ | |||
&refresh_token=Q..Zkm29lexi8VnWg2zPW1x-tgGad0Ibc3s3EwM_Ni4-g | &refresh_token=Q..Zkm29lexi8VnWg2zPW1x-tgGad0Ibc3s3EwM_Ni4-g | |||
</artwork> | ]]></sourcecode> | |||
</figure> | </figure> | |||
<t>When an authorization server supporting DPoP issues a | <t>When an authorization server supporting DPoP issues a | |||
refresh token to a public client that presents a valid DPoP proof at the | refresh token to a public client that presents a valid DPoP proof at the | |||
token endpoint, the refresh token MUST be bound | token endpoint, the refresh token <bcp14>MUST</bcp14> be bound | |||
to the respective public key. The binding MUST be validated when the refresh | to the respective public key. The binding <bcp14>MUST</bcp14> be validated when | |||
the refresh | ||||
token is later presented to get new access tokens. As a result, such a client | token is later presented to get new access tokens. As a result, such a client | |||
MUST present a DPoP proof for the same key that was used to obtain the refresh | <bcp14>MUST</bcp14> present a DPoP proof for the same key that was used to obtai n the refresh | |||
token each time that refresh token is used to obtain a new access token. | token each time that refresh token is used to obtain a new access token. | |||
The implementation details of the binding of the refresh token are at the discre tion of | The implementation details of the binding of the refresh token are at the discre tion of | |||
the authorization server. Since the authorization server both produces and | the authorization server. Since the authorization server both produces and | |||
validates its refresh tokens, there is no interoperability | validates its refresh tokens, there is no interoperability | |||
consideration in the specific details of the binding.</t> | consideration in the specific details of the binding.</t> | |||
<t>An authorization server MAY elect to issue access tokens which are not DPoP b ound, | <t>An authorization server <bcp14>MAY</bcp14> elect to issue access tokens that are not DPoP bound, | |||
which is signaled to the client with a value of <tt>Bearer</tt> in the <tt>token _type</tt> parameter | which is signaled to the client with a value of <tt>Bearer</tt> in the <tt>token _type</tt> parameter | |||
of the access token response per <xref target="RFC6750"></xref>. For a public cl ient that is | of the access token response per <xref target="RFC6750"></xref>. For a public cl ient that is | |||
also issued a refresh token, this has the effect of DPoP-binding the refresh tok en | also issued a refresh token, this has the effect of DPoP-binding the refresh tok en | |||
alone, which can improve the security posture even when protected resources are not | alone, which can improve the security posture even when protected resources are not | |||
updated to support DPoP.</t> | updated to support DPoP.</t> | |||
<t>If the access token response contains a different <tt>token_type</tt> value t han <tt>DPoP</tt>, the | <t>If the access token response contains a different <tt>token_type</tt> value t han <tt>DPoP</tt>, the | |||
access token protection provided by DPoP is not given. The client MUST discard t | access token protection provided by DPoP is not given. The client <bcp14>MUST</b | |||
he response in this | cp14> discard the response in this | |||
case, if this protection is deemed important for the security of the | case if this protection is deemed important for the security of the | |||
application; otherwise, it may continue as in a regular OAuth interaction.</t> | application; otherwise, the client may continue as in a regular OAuth interactio | |||
n.</t> | ||||
<t>Refresh tokens issued to confidential clients (those having | <t>Refresh tokens issued to confidential clients (those having | |||
established authentication credentials with the authorization server) | established authentication credentials with the authorization server) | |||
are not bound to the DPoP proof public key because they are already | are not bound to the DPoP proof public key because they are already | |||
sender-constrained with a different existing mechanism. The OAuth 2.0 Authorizat ion | sender-constrained with a different existing mechanism. The OAuth 2.0 Authorizat ion | |||
Framework <xref target="RFC6749"></xref> already requires that an authorization server bind | Framework <xref target="RFC6749"></xref> already requires that an authorization server bind | |||
refresh tokens to the client to which they were issued and that | refresh tokens to the client to which they were issued and that | |||
confidential clients authenticate to the authorization server when | confidential clients authenticate to the authorization server when | |||
presenting a refresh token. As a result, such refresh tokens | presenting a refresh token. As a result, such refresh tokens | |||
are sender-constrained by way of the client identifier and the associated | are sender-constrained by way of the client identifier and the associated | |||
authentication requirement. This existing sender-constraining mechanism | authentication requirement. This existing sender-constraining mechanism | |||
is more flexible (e.g., it allows credential rotation for the client | is more flexible (e.g., it allows credential rotation for the client | |||
without invalidating refresh tokens) than binding directly to a particular publi c key.</t> | without invalidating refresh tokens) than binding directly to a particular publi c key.</t> | |||
<section anchor="as-meta"><name>Authorization Server Metadata</name> | <section anchor="as-meta"><name>Authorization Server Metadata</name> | |||
<t>This document introduces the following authorization server metadata | <t>This document introduces the following authorization server metadata | |||
<xref target="RFC8414"></xref> parameter to signal support for DPoP in general a nd the specific | <xref target="RFC8414"></xref> parameter to signal support for DPoP in general a nd the specific | |||
JWS <tt>alg</tt> values the authorization server supports for DPoP proof JWTs.</ t> | JWS <tt>alg</tt> values the authorization server supports for DPoP proof JWTs.</ t> | |||
<dl spacing="compact"> | <dl spacing="compact"> | |||
<dt><tt>dpop_signing_alg_values_supported</tt></dt> | <dt><tt>dpop_signing_alg_values_supported</tt>:</dt> | |||
<dd>A JSON array containing a list of the JWS <tt>alg</tt> values (from the <xre f target="IANA.JOSE.ALGS"></xref> registry) supported | <dd>A JSON array containing a list of the JWS <tt>alg</tt> values (from the <xre f target="IANA.JOSE.ALGS"></xref> registry) supported | |||
by the authorization server for DPoP proof JWTs.</dd> | by the authorization server for DPoP proof JWTs.</dd> | |||
</dl> | </dl> | |||
</section> | </section> | |||
<section anchor="client-meta"><name>Client Registration Metadata</name> | <section anchor="client-meta"><name>Client Registration Metadata</name> | |||
<t>The Dynamic Client Registration Protocol <xref target="RFC7591"></xref> defin es an API | <t>The Dynamic Client Registration Protocol <xref target="RFC7591"></xref> defin es an API | |||
for dynamically registering OAuth 2.0 client metadata with authorization servers . | for dynamically registering OAuth 2.0 client metadata with authorization servers . | |||
The metadata defined by <xref target="RFC7591"></xref>, and registered extension s to it, | The metadata defined by <xref target="RFC7591"></xref>, and registered extension s to it, | |||
also imply a general data model for clients that is useful for authorization ser ver implementations | also imply a general data model for clients that is useful for authorization ser ver implementations | |||
even when the Dynamic Client Registration Protocol isn't in play. | even when the Dynamic Client Registration Protocol isn't in play. | |||
Such implementations will typically have some sort of user interface available f or managing client configuration.</t> | Such implementations will typically have some sort of user interface available f or managing client configuration.</t> | |||
<t>This document introduces the following client registration metadata | <t>This document introduces the following client registration metadata | |||
<xref target="RFC7591"></xref> parameter to indicate that the client always uses | <xref target="RFC7591"></xref> parameter to indicate that the client always uses | |||
DPoP when requesting tokens from the authorization server.</t> | DPoP when requesting tokens from the authorization server.</t> | |||
<dl spacing="compact"> | <dl spacing="compact"> | |||
<dt><tt>dpop_bound_access_tokens</tt></dt> | <dt><tt>dpop_bound_access_tokens</tt>:</dt> | |||
<dd>Boolean value specifying whether the client always uses DPoP for token reque | <dd>A boolean value specifying whether the client always uses DPoP for token req | |||
sts. If omitted, the default value is <tt>false</tt>.</dd> | uests. If omitted, the default value is <tt>false</tt>.</dd> | |||
</dl> | </dl> | |||
<t>If <tt>true</tt>, the authorization server MUST reject token requests from th is client that do not contain the DPoP header.</t> | <t>If the value is <tt>true</tt>, the authorization server <bcp14>MUST</bcp14> r eject token requests from the client that do not contain the DPoP header.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="Confirmation"><name>Public Key Confirmation</name> | <section anchor="Confirmation"><name>Public Key Confirmation</name> | |||
<t>Resource servers MUST be able to reliably identify whether | <t>Resource servers <bcp14>MUST</bcp14> be able to reliably identify whether | |||
an access token is DPoP-bound and ascertain sufficient information | an access token is DPoP-bound and ascertain sufficient information | |||
to verify the binding to the public key of the DPoP proof (see <xref target="htt p-auth-scheme"></xref>). | to verify the binding to the public key of the DPoP proof (see <xref target="htt p-auth-scheme"></xref>). | |||
Such a binding is accomplished by associating the public key | Such a binding is accomplished by associating the public key | |||
with the token in a way that can be | with the token in a way that can be | |||
accessed by the protected resource, such as embedding the JWK | accessed by the protected resource, such as embedding the JWK | |||
hash in the issued access token directly, using the syntax described | hash in the issued access token directly, using the syntax described | |||
in <xref target="jwk-thumb-jwt"></xref>, or through token introspection as descr ibed in | in <xref target="jwk-thumb-jwt"></xref>, or through token introspection as descr ibed in | |||
<xref target="jwk-thumb-intro"></xref>. Other methods of associating a | <xref target="jwk-thumb-intro"></xref>. | |||
public key with an access token are possible, per agreement by the | Other methods of associating a | |||
authorization server and the protected resource, but are beyond the | public key with an access token are possible per an agreement by the | |||
authorization server and the protected resource; however, they are beyond the | ||||
scope of this specification.</t> | scope of this specification.</t> | |||
<t>Resource servers supporting DPoP MUST ensure that the public key from | <t>Resource servers supporting DPoP <bcp14>MUST</bcp14> ensure that the public k ey from | |||
the DPoP proof matches the one bound to the access token.</t> | the DPoP proof matches the one bound to the access token.</t> | |||
<section anchor="jwk-thumb-jwt"><name>JWK Thumbprint Confirmation Method</name> | <section anchor="jwk-thumb-jwt"><name>JWK Thumbprint Confirmation Method</name> | |||
<t>When access tokens are represented as JWTs <xref target="RFC7519"></xref>, | <t>When access tokens are represented as JWTs <xref target="RFC7519"></xref>, | |||
the public key information is represented | the public key information is represented | |||
using the <tt>jkt</tt> confirmation method member defined herein. | using the <tt>jkt</tt> confirmation method member defined herein. | |||
To convey the hash of a public key in a JWT, this specification | To convey the hash of a public key in a JWT, this specification | |||
introduces the following JWT Confirmation Method <xref target="RFC7800"></xref> member for | introduces the following JWT Confirmation Method <xref target="RFC7800"></xref> member for | |||
use under the <tt>cnf</tt> claim.</t> | use under the <tt>cnf</tt> claim.</t> | |||
<dl spacing="compact"> | <dl spacing="compact"> | |||
<dt><tt>jkt</tt></dt> | <dt><tt>jkt</tt>:</dt> | |||
<dd>JWK SHA-256 Thumbprint Confirmation Method. The value of the <tt>jkt</tt> me | <dd>JWK SHA-256 Thumbprint confirmation method. The value of the <tt>jkt</tt> me | |||
mber | mber | |||
MUST be the base64url encoding (as defined in <xref target="RFC7515"></xref>) | <bcp14>MUST</bcp14> be the base64url encoding (as defined in <xref target="RFC75 | |||
15"></xref>) | ||||
of the JWK SHA-256 Thumbprint (according to <xref target="RFC7638"></xref>) of t he DPoP public key | of the JWK SHA-256 Thumbprint (according to <xref target="RFC7638"></xref>) of t he DPoP public key | |||
(in JWK format) to which the access token is bound.</dd> | (in JWK format) to which the access token is bound.</dd> | |||
</dl> | </dl> | |||
<t>The following example JWT in <xref target="cnf-claim-jwt"></xref> with decode d JWT payload shown in | <t>The following example JWT in <xref target="cnf-claim-jwt"></xref> with a deco ded JWT payload shown in | |||
<xref target="cnf-claim"></xref> contains a <tt>cnf</tt> claim with the <tt>jkt< /tt> JWK Thumbprint confirmation | <xref target="cnf-claim"></xref> contains a <tt>cnf</tt> claim with the <tt>jkt< /tt> JWK Thumbprint confirmation | |||
method member. The <tt>jkt</tt> value in these examples is the hash of the publ ic key | method member. The <tt>jkt</tt> value in these examples is the hash of the publ ic key | |||
from the DPoP proofs in the examples in <xref target="access-token-request"></xr | from the DPoP proofs in the examples shown in <xref target="access-token-request | |||
ef>. | "></xref>. | |||
(The example uses '\' line wrapping per RFC 8792.)</t> | The example uses "\" line wrapping per <xref target="RFC8792"/>.</t> | |||
<figure anchor="cnf-claim-jwt"><name>JWT containing a JWK SHA-256 Thumbprint Con | <figure anchor="cnf-claim-jwt"><name>JWT Containing a JWK SHA-256 Thumbprint Con | |||
firmation </name> | firmation </name> | |||
<artwork>eyJhbGciOiJFUzI1NiIsImtpZCI6IkJlQUxrYiJ9.eyJzdWIiOiJzb21lb25lQGV4YW1\ | <sourcecode type="jwt">eyJhbGciOiJFUzI1NiIsImtpZCI6IkJlQUxrYiJ9.eyJzdWIiOiJzb21l | |||
b25lQGV4YW1\ | ||||
wbGUuY29tIiwiaXNzIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJuYmYiOjE\ | wbGUuY29tIiwiaXNzIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJuYmYiOjE\ | |||
1NjIyNjI2MTEsImV4cCI6MTU2MjI2NjIxNiwiY25mIjp7ImprdCI6IjBaY09DT1JaTll\ | 1NjIyNjI2MTEsImV4cCI6MTU2MjI2NjIxNiwiY25mIjp7ImprdCI6IjBaY09DT1JaTll\ | |||
5LURXcHFxMzBqWnlKR0hUTjBkMkhnbEJWM3VpZ3VBNEkifX0.3Tyo8VTcn6u_PboUmAO\ | 5LURXcHFxMzBqWnlKR0hUTjBkMkhnbEJWM3VpZ3VBNEkifX0.3Tyo8VTcn6u_PboUmAO\ | |||
YUY1kfAavomW_YwYMkmRNizLJoQzWy2fCo79Zi5yObpIzjWb5xW4OGld7ESZrh0fsrA | YUY1kfAavomW_YwYMkmRNizLJoQzWy2fCo79Zi5yObpIzjWb5xW4OGld7ESZrh0fsrA | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<figure anchor="cnf-claim"><name>JWT Claims Set with a JWK SHA-256 Thumbprint Co nfirmation </name> | <figure anchor="cnf-claim"><name>JWT Claims Set with a JWK SHA-256 Thumbprint Co nfirmation </name> | |||
<artwork>{ | <sourcecode type="json">{ | |||
"sub":"someone@example.com", | "sub":"someone@example.com", | |||
"iss":"https://server.example.com", | "iss":"https://server.example.com", | |||
"nbf":1562262611, | "nbf":1562262611, | |||
"exp":1562266216, | "exp":1562266216, | |||
"cnf": | "cnf": | |||
{ | { | |||
"jkt":"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" | "jkt":"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" | |||
} | } | |||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
</section> | </section> | |||
<section anchor="jwk-thumb-intro"><name>JWK Thumbprint Confirmation Method in To ken Introspection</name> | <section anchor="jwk-thumb-intro"><name>JWK Thumbprint Confirmation Method in To ken Introspection</name> | |||
<t>OAuth 2.0 Token Introspection <xref target="RFC7662"></xref> defines a method for a | <t>"OAuth 2.0 Token Introspection" <xref target="RFC7662"></xref> defines a meth od for a | |||
protected resource to query an authorization server about the active | protected resource to query an authorization server about the active | |||
state of an access token as well as to determine metainformation | state of an access token. The protected resource also determines metainformation | |||
about the token.</t> | about the token.</t> | |||
<t>For a DPoP-bound access token, the hash of the public key to which the token | <t>For a DPoP-bound access token, the hash of the public key to which the token | |||
is bound is conveyed to the protected resource as metainformation in a token | is bound is conveyed to the protected resource as metainformation in a token | |||
introspection response. The hash is conveyed using the same <tt>cnf</tt> content with | introspection response. The hash is conveyed using the same <tt>cnf</tt> content with | |||
<tt>jkt</tt> member structure as the JWK Thumbprint confirmation method, describ ed in | <tt>jkt</tt> member structure as the JWK Thumbprint confirmation method, describ ed in | |||
<xref target="jwk-thumb-jwt"></xref>, as a top-level member of the | <xref target="jwk-thumb-jwt"></xref>, as a top-level member of the | |||
introspection response JSON. Note that the resource server | introspection response JSON. Note that the resource server | |||
does not send a DPoP proof with the introspection request and the authorization | does not send a DPoP proof with the introspection request, and the authorization | |||
server does not validate an access token's DPoP binding at the introspection | server does not validate an access token's DPoP binding at the introspection | |||
endpoint. Rather the resource server uses the data of the introspection response | endpoint. Rather, the resource server uses the data of the introspection respons e | |||
to validate the access token binding itself locally.</t> | to validate the access token binding itself locally.</t> | |||
<t>If the <tt>token_type</tt> member is included in the introspection response, it MUST contain | <t>If the <tt>token_type</tt> member is included in the introspection response, it <bcp14>MUST</bcp14> contain | |||
the value <tt>DPoP</tt>.</t> | the value <tt>DPoP</tt>.</t> | |||
<t>The example introspection request in <xref target="introspect-req"></xref> an d corresponding response in | <t>The example introspection request in <xref target="introspect-req"></xref> an d corresponding response in | |||
<xref target="introspect-resp"></xref> illustrate an introspection exchange for the example DPoP-bound | <xref target="introspect-resp"></xref> illustrate an introspection exchange for the example DPoP-bound | |||
access token that was issued in <xref target="token-response"></xref>.</t> | access token that was issued in <xref target="token-response"></xref>.</t> | |||
<figure anchor="introspect-req"><name>Example Introspection Request </name> | <figure anchor="introspect-req"><name>Example Introspection Request </name> | |||
<artwork>POST /as/introspect.oauth2 HTTP/1.1 | <sourcecode type="http-message">POST /as/introspect.oauth2 HTTP/1.1 | |||
Host: server.example.com | Host: server.example.com | |||
Content-Type: application/x-www-form-urlencoded | Content-Type: application/x-www-form-urlencoded | |||
Authorization: Basic cnM6cnM6TWt1LTZnX2xDektJZHo0ZnNON2tZY3lhK1Rp | Authorization: Basic cnM6cnM6TWt1LTZnX2xDektJZHo0ZnNON2tZY3lhK1Rp | |||
token=Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | token=Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<figure anchor="introspect-resp"><name>Example Introspection Response for a DPoP -Bound Access Token </name> | <figure anchor="introspect-resp"><name>Example Introspection Response for a DPoP -Bound Access Token </name> | |||
<artwork>HTTP/1.1 200 OK | <sourcecode>HTTP/1.1 200 OK | |||
Content-Type: application/json | Content-Type: application/json | |||
Cache-Control: no-store | Cache-Control: no-store | |||
{ | { | |||
"active": true, | "active": true, | |||
"sub": "someone@example.com", | "sub": "someone@example.com", | |||
"iss": "https://server.example.com", | "iss": "https://server.example.com", | |||
"nbf": 1562262611, | "nbf": 1562262611, | |||
"exp": 1562266216, | "exp": 1562266216, | |||
"cnf": | "cnf": | |||
{ | { | |||
"jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" | "jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" | |||
} | } | |||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="protected-resource-access"><name>Protected Resource Access</nam e> | <section anchor="protected-resource-access"><name>Protected Resource Access</nam e> | |||
<t>Requests to DPoP protected resources | <t>Requests to DPoP-protected resources | |||
MUST include both a DPoP proof as per <xref target="the-proof"></xref> and | <bcp14>MUST</bcp14> include both a DPoP proof as per <xref target="the-proof"></ | |||
xref> and | ||||
the access token as described in <xref target="http-auth-scheme"></xref>. | the access token as described in <xref target="http-auth-scheme"></xref>. | |||
The DPoP proof MUST include the <tt>ath</tt> claim with a valid hash of the | The DPoP proof <bcp14>MUST</bcp14> include the <tt>ath</tt> claim with a valid h ash of the | |||
associated access token.</t> | associated access token.</t> | |||
<t>Binding the token value to the proof in this way prevents a proof | <t>Binding the token value to the proof in this way prevents a proof | |||
to be used with multiple different access token values across different requests . | to be used with multiple different access token values across different requests . | |||
For example, if a client holds tokens bound to two different resource owners, AT 1 and AT2, | For example, if a client holds tokens bound to two different resource owners, AT 1 and AT2, | |||
and uses the same key when talking to the AS, it's possible that these tokens co uld be swapped. | and uses the same key when talking to the authorization server, it's possible th at these tokens could be swapped. | |||
Without the <tt>ath</tt> field to bind it, a captured signature applied to AT1 c ould be | Without the <tt>ath</tt> field to bind it, a captured signature applied to AT1 c ould be | |||
replayed with AT2 instead, changing the rights and access of the intended reques t. | replayed with AT2 instead, changing the rights and access of the intended reques t. | |||
This same substitution prevention remains for rotated access tokens within the s ame | This same substitution prevention remains for rotated access tokens within the s ame | |||
combination of client and resource owner -- a rotated token value would require the | combination of client and resource owner -- a rotated token value would require the | |||
calculation of a new proof. This binding additionally ensures that a proof inten ded for use | calculation of a new proof. This binding additionally ensures that a proof inten ded for use | |||
with the access token is not usable without an access token, or vice-versa.</t> | with the access token is not usable without an access token, or vice-versa.</t> | |||
<t>The resource server is required to calculate the hash of the token value pres ented | <t>The resource server is required to calculate the hash of the token value pres ented | |||
and verify that it is the same as the hash value in the <tt>ath</tt> field as de scribed in <xref target="checking"></xref>. | and verify that it is the same as the hash value in the <tt>ath</tt> field as de scribed in <xref target="checking"></xref>. | |||
Since the <tt>ath</tt> field value is covered by the DPoP proof's signature, its inclusion binds | Since the <tt>ath</tt> field value is covered by the DPoP proof's signature, its inclusion binds | |||
the access token value to the holder of the key used to generate the signature.< /t> | the access token value to the holder of the key used to generate the signature.< /t> | |||
<t>Note that the <tt>ath</tt> field alone does not prevent replay of the DPoP pr oof or provide binding | <t>Note that the <tt>ath</tt> field alone does not prevent replay of the DPoP pr oof or provide binding | |||
to the request in which the proof is presented, and it is still important to che ck the time | to the request in which the proof is presented, and it is still important to che ck the time | |||
window of the proof as well as the included message parameters such as <tt>htm</ tt> and <tt>htu</tt>.</t> | window of the proof as well as the included message parameters, such as <tt>htm< /tt> and <tt>htu</tt>.</t> | |||
<section anchor="http-auth-scheme"><name>The DPoP Authentication Scheme</name> | <section anchor="http-auth-scheme"><name>The DPoP Authentication Scheme</name> | |||
<t>A DPoP-bound access token is sent using the <tt>Authorization</tt> request | <t>A DPoP-bound access token is sent using the <tt>Authorization</tt> request | |||
header field per Section 11.6.2 of <xref target="RFC9110"></xref> using an | header field per <xref target="RFC9110" sectionFormat="of" section="11.6.2"></xr | |||
authentication scheme of <tt>DPoP</tt>. The syntax of the <tt>Authorization</tt> | ef> with an authentication scheme of <tt>DPoP</tt>. The syntax of the <tt>Author | |||
ization</tt> | ||||
header field for the <tt>DPoP</tt> scheme | header field for the <tt>DPoP</tt> scheme | |||
uses the <tt>token68</tt> syntax defined in Section 11.2 of <xref target="RFC911 | uses the token68 syntax defined in <xref target="RFC9110" sectionFormat="of" sec | |||
0"></xref> | tion="11.2"></xref> for credentials and is repeated below for ease of reference. | |||
(repeated below for ease of reference) for credentials. | ||||
The ABNF notation syntax for DPoP authentication scheme credentials is as follow s:</t> | The ABNF notation syntax for DPoP authentication scheme credentials is as follow s:</t> | |||
<figure><name>DPoP Authentication Scheme ABNF | <figure anchor="dpop-auth-scheme-abnf"><name>DPoP Authentication Scheme ABNF | |||
</name> | </name> | |||
<artwork> token68 = 1*( ALPHA / DIGIT / | <sourcecode type="abnf"><![CDATA[ | |||
"-" / "." / "_" / "~" | token68 = 1*( ALPHA / DIGIT / | |||
/ "+" / "/" ) *"=" | "-" / "." / "_" / "~" / "+" / "/" ) *"=" | |||
credentials = "DPoP" 1*SP token68 | credentials = "DPoP" 1*SP token68 | |||
</artwork> | ]]></sourcecode> | |||
</figure> | </figure> | |||
<t>For such an access token, a resource server MUST check that a DPoP proof | <t>For such an access token, a resource server <bcp14>MUST</bcp14> check that a DPoP proof | |||
was also received in the <tt>DPoP</tt> header field of the HTTP request, | was also received in the <tt>DPoP</tt> header field of the HTTP request, | |||
check the DPoP proof according to the rules in <xref target="checking"></xref>, | check the DPoP proof according to the rules in <xref target="checking"></xref>, | |||
and check that the public key of the DPoP proof matches the public | and check that the public key of the DPoP proof matches the public | |||
key to which the access token is bound per <xref target="Confirmation"></xref>.< /t> | key to which the access token is bound per <xref target="Confirmation"></xref>.< /t> | |||
<t>The resource server MUST NOT grant access to the resource unless all | <t>The resource server <bcp14>MUST NOT</bcp14> grant access to the resource unle ss all | |||
checks are successful.</t> | checks are successful.</t> | |||
<t><xref target="protected-resource-request"></xref> shows an example request to a protected | <t><xref target="protected-resource-request"></xref> shows an example request to a protected | |||
resource with a DPoP-bound access token in the <tt>Authorization</tt> header | resource with a DPoP-bound access token in the <tt>Authorization</tt> header | |||
and the DPoP proof in the <tt>DPoP</tt> header | and the DPoP proof in the <tt>DPoP</tt> header. | |||
(with '\' line wrapping per RFC 8792). | The example uses "\" line wrapping per <xref target="RFC8792"/>. | |||
Following that is <xref target="dpop-proof-pr"></xref>, which shows the decoded | <xref target="dpop-proof-pr"></xref> shows the decoded content of that DPoP | |||
content of that DPoP | proof. The JSON of the JWT header and payload are shown, | |||
proof. The JSON of the JWT header and payload are shown | ||||
but the signature part is omitted. As usual, line breaks and indentation | but the signature part is omitted. As usual, line breaks and indentation | |||
are included for formatting and readability.</t> | are included for formatting and readability.</t> | |||
<figure anchor="protected-resource-request"><name>DPoP Protected Resource Reques | <figure anchor="protected-resource-request"><name>DPoP-Protected Resource Reques | |||
t </name> | t </name> | |||
<artwork>GET /protectedresource HTTP/1.1 | <sourcecode type="http-message">GET /protectedresource HTTP/1.1 | |||
Host: resource.example.org | Host: resource.example.org | |||
Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | |||
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ | |||
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ | |||
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ | |||
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiJlMWozVl9iS2ljOC1MQUVCIiwiaHRtIj\ | QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiJlMWozVl9iS2ljOC1MQUVCIiwiaHRtIj\ | |||
oiR0VUIiwiaHR1IjoiaHR0cHM6Ly9yZXNvdXJjZS5leGFtcGxlLm9yZy9wcm90ZWN0Z\ | oiR0VUIiwiaHR1IjoiaHR0cHM6Ly9yZXNvdXJjZS5leGFtcGxlLm9yZy9wcm90ZWN0Z\ | |||
WRyZXNvdXJjZSIsImlhdCI6MTU2MjI2MjYxOCwiYXRoIjoiZlVIeU8ycjJaM0RaNTNF\ | WRyZXNvdXJjZSIsImlhdCI6MTU2MjI2MjYxOCwiYXRoIjoiZlVIeU8ycjJaM0RaNTNF\ | |||
c05yV0JiMHhXWG9hTnk1OUlpS0NBcWtzbVFFbyJ9.2oW9RP35yRqzhrtNP86L-Ey71E\ | c05yV0JiMHhXWG9hTnk1OUlpS0NBcWtzbVFFbyJ9.2oW9RP35yRqzhrtNP86L-Ey71E\ | |||
OptxRimPPToA1plemAgR6pxHF8y6-yqyVnmcw6Fy1dqd-jfxSYoMxhAJpLjA | OptxRimPPToA1plemAgR6pxHF8y6-yqyVnmcw6Fy1dqd-jfxSYoMxhAJpLjA | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<figure anchor="dpop-proof-pr"><name>Decoded Content of the <tt>DPoP</tt> Proof | <figure anchor="dpop-proof-pr"><name>Decoded Content of the <tt>DPoP</tt> Proof | |||
JWT in <xref target="protected-resource-request"></xref> </name> | JWT in Figure 13</name> | |||
<artwork>{ | <sourcecode type="json">{ | |||
"typ":"dpop+jwt", | "typ":"dpop+jwt", | |||
"alg":"ES256", | "alg":"ES256", | |||
"jwk": { | "jwk": { | |||
"kty":"EC", | "kty":"EC", | |||
"x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs", | "x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs", | |||
"y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA", | "y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA", | |||
"crv":"P-256" | "crv":"P-256" | |||
} | } | |||
} | } | |||
. | . | |||
{ | { | |||
"jti":"e1j3V_bKic8-LAEB", | "jti":"e1j3V_bKic8-LAEB", | |||
"htm":"GET", | "htm":"GET", | |||
"htu":"https://resource.example.org/protectedresource", | "htu":"https://resource.example.org/protectedresource", | |||
"iat":1562262618, | "iat":1562262618, | |||
"ath":"fUHyO2r2Z3DZ53EsNrWBb0xWXoaNy59IiKCAqksmQEo" | "ath":"fUHyO2r2Z3DZ53EsNrWBb0xWXoaNy59IiKCAqksmQEo" | |||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>Upon receipt of a request to a protected resource within | <t>Upon receipt of a request to a protected resource within the protection | |||
the protection space requiring DPoP authentication, if the request does | space requiring DPoP authentication, the server can respond with a challenge | |||
not include valid credentials or does not contain an access | to the client to provide DPoP authentication information if the request does | |||
token sufficient for access, the server | not include valid credentials or does not contain an access token sufficient | |||
can respond with a challenge to the client to provide DPoP authentication inform | for access. Such a challenge is made using the 401 (Unauthorized) response | |||
ation. | status code (<xref target="RFC9110" sectionFormat="comma" | |||
Such a challenge is made using the 401 (Unauthorized) response status code | section="15.5.2"></xref>) and the <tt>WWW-Authenticate</tt> header field | |||
(<xref target="RFC9110"></xref>, Section 15.5.2) and the <tt>WWW-Authenticate</t | (<xref target="RFC9110" sectionFormat="comma" section="11.6.1"></xref>). The | |||
t> header field | server <bcp14>MAY</bcp14> include the <tt>WWW-Authenticate</tt> header in | |||
(<xref target="RFC9110"></xref>, Section 11.6.1). The server MAY include the | response to other conditions as well.</t> | |||
<tt>WWW-Authenticate</tt> header in response to other conditions as well.</t> | ||||
<t>In such challenges:</t> | <t>In such challenges:</t> | |||
<ul spacing="compact"> | <ul spacing="compact"> | |||
<li>The scheme name is <tt>DPoP</tt>.</li> | <li>The scheme name is <tt>DPoP</tt>.</li> | |||
<li>The authentication parameter <tt>realm</tt> MAY be included to indicate the | <li>The authentication parameter <tt>realm</tt> <bcp14>MAY</bcp14> be included t | |||
scope of protection in the manner described in <xref target="RFC9110"></xref>, S | o indicate the | |||
ection 11.5.</li> | scope of protection in the manner described in <xref target="RFC9110" sectionFor | |||
<li>A <tt>scope</tt> authentication parameter MAY be included as defined in | mat="comma" section="11.5"></xref>.</li> | |||
<xref target="RFC6750"></xref>, Section 3.</li> | <li>A <tt>scope</tt> authentication parameter <bcp14>MAY</bcp14> be included as | |||
<li>An <tt>error</tt> parameter (<xref target="RFC6750"></xref>, Section 3) SHOU | defined in | |||
LD be included | <xref target="RFC6750" sectionFormat="comma" section="3"></xref>.</li> | |||
<li>An <tt>error</tt> parameter (<xref target="RFC6750" sectionFormat="comma" se | ||||
ction="3"></xref>) <bcp14>SHOULD</bcp14> be included | ||||
to indicate the reason why the request was declined, | to indicate the reason why the request was declined, | |||
if the request included an access token but failed authentication. | if the request included an access token but failed authentication. | |||
The error parameter values described in Section 3.1 of <xref target="RFC6750"></ xref> are suitable | The error parameter values described in <xref target="RFC6750" sectionFormat="co mma" section="3.1"></xref> are suitable, | |||
as are any appropriate values defined by extension. The value <tt>use_dpop_nonce </tt> can be | as are any appropriate values defined by extension. The value <tt>use_dpop_nonce </tt> can be | |||
used as described in <xref target="RSNonce"></xref> to signal that a nonce is ne | used as described in <xref target="RSNonce"></xref> to signal that a nonce is ne | |||
eded in the DPoP proof of | eded in the DPoP proof of a | |||
subsequent request(s). And <tt>invalid_dpop_proof</tt> is used to indicate that | subsequent request(s). Additionally, <tt>invalid_dpop_proof</tt> is used to indi | |||
the DPoP proof | cate that the DPoP proof | |||
itself was deemed invalid based on the criteria of <xref target="checking"></xre f>.</li> | itself was deemed invalid based on the criteria of <xref target="checking"></xre f>.</li> | |||
<li>An <tt>error_description</tt> parameter (<xref target="RFC6750"></xref>, Sec tion 3) MAY be included | <li>An <tt>error_description</tt> parameter (<xref target="RFC6750" sectionForma t="comma" section="3"></xref>) <bcp14>MAY</bcp14> be included | |||
along with the <tt>error</tt> parameter to provide developers a human-readable | along with the <tt>error</tt> parameter to provide developers a human-readable | |||
explanation that is not meant to be displayed to end-users.</li> | explanation that is not meant to be displayed to end-users.</li> | |||
<li>An <tt>algs</tt> parameter SHOULD be included to signal to the client the | <li>An <tt>algs</tt> parameter <bcp14>SHOULD</bcp14> be included to signal to th e client the | |||
JWS algorithms that are acceptable for the DPoP proof JWT. | JWS algorithms that are acceptable for the DPoP proof JWT. | |||
The value of the parameter is a space-delimited list of JWS <tt>alg</tt> (Algori thm) | The value of the parameter is a space-delimited list of JWS <tt>alg</tt> (Algori thm) | |||
header values (<xref target="RFC7515"></xref>, Section 4.1.1).</li> | header values (<xref target="RFC7515" sectionFormat="comma" section="4.1.1"></xr | |||
<li>Additional authentication parameters MAY be used and unknown parameters | ef>).</li> | |||
MUST be ignored by recipients.</li> | <li>Additional authentication parameters <bcp14>MAY</bcp14> be used, and unknown | |||
parameters | ||||
<bcp14>MUST</bcp14> be ignored by recipients.</li> | ||||
</ul> | </ul> | |||
<t>For example, in response to a protected resource request without | <t><xref target="http-401-response-protected-req-without-auth"/> shows a respons | |||
authentication:</t> | e to a protected resource request without | |||
<figure><name>HTTP 401 Response to a Protected Resource Request without Authenti | authentication.</t> | |||
cation | <figure anchor="http-401-response-protected-req-without-auth"><name>HTTP 401 Res | |||
ponse to a Protected Resource Request without Authentication | ||||
</name> | </name> | |||
<artwork> HTTP/1.1 401 Unauthorized | <sourcecode type="http-message"> HTTP/1.1 401 Unauthorized | |||
WWW-Authenticate: DPoP algs="ES256 PS256" | WWW-Authenticate: DPoP algs="ES256 PS256" | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>And in response to a protected resource request that was rejected | <t><xref target="http-401-response-protected-req-with-invalid-token"/> shows a r | |||
because the confirmation of the DPoP binding in the access token failed | esponse to a protected resource request that was rejected | |||
(with '\' line wrapping per RFC 8792):</t> | due to the failed confirmation of the DPoP binding in the access token. <xref ta | |||
<figure><name>HTTP 401 Response to a Protected Resource Request with an Invalid | rget="http-401-response-protected-req-with-invalid-token"/> | |||
Token | uses "\" line wrapping per <xref target="RFC8792"/>.</t> | |||
<figure anchor="http-401-response-protected-req-with-invalid-token"><name>HTTP 4 | ||||
01 Response to a Protected Resource Request with an Invalid Token | ||||
</name> | </name> | |||
<artwork> HTTP/1.1 401 Unauthorized | <sourcecode type="http-message"> | |||
WWW-Authenticate: DPoP error="invalid_token", \ | HTTP/1.1 401 Unauthorized | |||
error_description="Invalid DPoP key binding", algs="ES256" | WWW-Authenticate: DPoP error="invalid_token", \ | |||
; | error_description="Invalid DPoP key binding", algs="ES256" | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>Note that browser-based client applications using CORS <xref target="WHATWG.F etch"></xref> only have access | <t>Note that browser-based client applications using Cross-Origin Resource Shari ng (CORS) <xref target="WHATWG.Fetch"></xref> only have access | |||
to CORS-safelisted response HTTP headers by default. | to CORS-safelisted response HTTP headers by default. | |||
In order for the application to obtain and use the <tt>WWW-Authenticate</tt> HTT P response header | In order for the application to obtain and use the <tt>WWW-Authenticate</tt> HTT P response header | |||
value, the server needs to make it available to the application by including | value, the server needs to make it available to the application by including | |||
<tt>WWW-Authenticate</tt> in the <tt>Access-Control-Expose-Headers</tt> response header list value.</t> | <tt>WWW-Authenticate</tt> in the <tt>Access-Control-Expose-Headers</tt> response header list value.</t> | |||
<t>This authentication scheme is for origin-server authentication only. | <t>This authentication scheme is for origin-server authentication only. | |||
Therefore, this authentication scheme MUST NOT be used with the | Therefore, this authentication scheme <bcp14>MUST NOT</bcp14> be used with the | |||
<tt>Proxy-Authenticate</tt> or <tt>Proxy-Authorization</tt> header fields.</t> | <tt>Proxy-Authenticate</tt> or <tt>Proxy-Authorization</tt> header fields.</t> | |||
<t>Note that the syntax of the <tt>Authorization</tt> header field for this auth entication scheme | <t>Note that the syntax of the <tt>Authorization</tt> header field for this auth entication scheme | |||
follows the usage of the <tt>Bearer</tt> scheme defined in Section 2.1 of <xref | follows the usage of the <tt>Bearer</tt> scheme defined in <xref target="RFC6750 | |||
target="RFC6750"></xref>. | " sectionFormat="of" section="2.1"></xref>. | |||
While not the preferred credential syntax of <xref target="RFC9110"></xref>, it | While it is not the preferred credential syntax of <xref target="RFC9110"></xref | |||
is compatible | >, it is compatible | |||
with the general authentication framework therein and was used for consistency | with the general authentication framework therein and is used for consistency | |||
and familiarity with the <tt>Bearer</tt> scheme.</t> | and familiarity with the <tt>Bearer</tt> scheme.</t> | |||
</section> | </section> | |||
<section anchor="compatibility-with-the-bearer-authentication-scheme"><name>Comp atibility with the Bearer Authentication Scheme</name> | <section anchor="compatibility-with-the-bearer-authentication-scheme"><name>Comp atibility with the Bearer Authentication Scheme</name> | |||
<t>Protected resources simultaneously supporting both the <tt>DPoP</tt> and <tt> Bearer</tt> | <t>Protected resources simultaneously supporting both the <tt>DPoP</tt> and <tt> Bearer</tt> | |||
schemes need to update how evaluation of bearer tokens is performed to prevent | schemes need to update how the evaluation process is performed for bearer tokens to prevent | |||
downgraded usage of a DPoP-bound access token. | downgraded usage of a DPoP-bound access token. | |||
Specifically, such a protected resource MUST reject a DPoP-bound access | Specifically, such a protected resource <bcp14>MUST</bcp14> reject a DPoP-bound access | |||
token received as a bearer token per <xref target="RFC6750"></xref>.</t> | token received as a bearer token per <xref target="RFC6750"></xref>.</t> | |||
<t>Section 11.6.1 of <xref target="RFC9110"></xref> allows a protected resource to indicate support for | <t><xref target="RFC9110" sectionFormat="of" section="11.6.1"></xref> allows a p rotected resource to indicate support for | |||
multiple authentication schemes (i.e., <tt>Bearer</tt> and <tt>DPoP</tt>) with t he | multiple authentication schemes (i.e., <tt>Bearer</tt> and <tt>DPoP</tt>) with t he | |||
<tt>WWW-Authenticate</tt> header field of a 401 (Unauthorized) response.</t> | <tt>WWW-Authenticate</tt> header field of a 401 (Unauthorized) response.</t> | |||
<t>A protected resource that supports only <xref target="RFC6750"></xref> and is unaware of DPoP | <t>A protected resource that supports only <xref target="RFC6750"></xref> and is unaware of DPoP | |||
would most presumably accept a DPoP-bound access token as a bearer token | would most presumably accept a DPoP-bound access token as a bearer token | |||
(JWT <xref target="RFC7519"></xref> says to ignore unrecognized claims, Introspe ction <xref target="RFC7662"></xref> | (JWT <xref target="RFC7519"></xref> says to ignore unrecognized claims, Introspe ction <xref target="RFC7662"></xref> | |||
says that other parameters might be present while placing no functional | says that other parameters might be present while placing no functional | |||
requirements on their presence, and <xref target="RFC6750"></xref> is effectivel y silent on | requirements on their presence, and <xref target="RFC6750"></xref> is effectivel y silent on | |||
the content of the access token as it relates to validity). As such, a | the content of the access token since it relates to validity). | |||
As such, a | ||||
client can send a DPoP-bound access token using the <tt>Bearer</tt> scheme upon | client can send a DPoP-bound access token using the <tt>Bearer</tt> scheme upon | |||
receipt of a <tt>WWW-Authenticate: Bearer</tt> challenge from a protected resour ce | receipt of a <tt>WWW-Authenticate: Bearer</tt> challenge from a protected resour ce | |||
(or if it has prior such knowledge about the capabilities of the protected | (or it can send a DPoP-bound access token if it has prior knowledge of the capab ilities of the protected | |||
resource). The effect of this likely simplifies the logistics of phased | resource). The effect of this likely simplifies the logistics of phased | |||
upgrades to protected resources in their support DPoP or even | upgrades to protected resources in their support DPoP or | |||
prolonged deployments of protected resources with mixed token type support.</t> | prolonged deployments of protected resources with mixed token type support.</t> | |||
<t>If a protected resource supporting both <tt>Bearer</tt> and <tt>DPoP</tt> sch emes elects to | <t>If a protected resource supporting both <tt>Bearer</tt> and <tt>DPoP</tt> sch emes elects to | |||
respond with multiple <tt>WWW-Authenticate</tt> challenges, attention should be paid to | respond with multiple <tt>WWW-Authenticate</tt> challenges, attention should be paid to | |||
which challenge(s) should deliver the actual error information. It is | which challenge(s) should deliver the actual error information. It is | |||
RECOMMENDED that the following rules be adhered to:</t> | <bcp14>RECOMMENDED</bcp14> that the following rules be adhered to:</t> | |||
<ul> | <ul> | |||
<li><t>If no authentication information has been included with the request, then the | <li><t>If no authentication information has been included with the request, then the | |||
challenges SHOULD NOT include an error code or other error information, as per | challenges <bcp14>SHOULD NOT</bcp14> include an error code or other error inform | |||
<xref target="RFC6750"></xref>, Section 3.1 (<xref target="multi-challenge-no-to | ation, as per | |||
ken"></xref>).</t> | <xref target="RFC6750" sectionFormat="of" section="3.1"></xref> (<xref target="m | |||
ulti-challenge-no-token"></xref>).</t> | ||||
</li> | </li> | |||
<li><t>If the mechanism used to attempt authentication could be established | <li><t>If the mechanism used to attempt authentication could be established | |||
unambiguously, then the corresponding challenge SHOULD be used to deliver error | unambiguously, then the corresponding challenge <bcp14>SHOULD</bcp14> be used to deliver error | |||
information (<xref target="multi-challenge-invalid-token"></xref>).</t> | information (<xref target="multi-challenge-invalid-token"></xref>).</t> | |||
</li> | </li> | |||
<li><t>Otherwise, both <tt>Bearer</tt> and <tt>DPoP</tt> challenged MAY be used | <li><t>Otherwise, both <tt>Bearer</tt> and <tt>DPoP</tt> challenges <bcp14>MAY</ | |||
to deliver error | bcp14> be used to deliver error information (<xref target="multi-challenge-ambig | |||
information (<xref target="multi-challenge-ambiguous"></xref>).</t> | uous"></xref>).</t> | |||
</li> | </li> | |||
</ul> | </ul> | |||
<t>(Where needed, the following examples use '\' line wrapping per RFC 8792.)</t > | <t>The following examples use "\" line wrapping per <xref target="RFC8792"/>.</t > | |||
<figure anchor="multi-challenge-no-token"><name>HTTP 401 Response to a Protected Resource Request without Authentication </name> | <figure anchor="multi-challenge-no-token"><name>HTTP 401 Response to a Protected Resource Request without Authentication </name> | |||
<artwork>GET /protectedresource HTTP/1.1 | <sourcecode type="http-message">GET /protectedresource HTTP/1.1 | |||
Host: resource.example.org | Host: resource.example.org | |||
HTTP/1.1 401 Unauthorized | HTTP/1.1 401 Unauthorized | |||
WWW-Authenticate: Bearer, DPoP algs="ES256 PS256" | WWW-Authenticate: Bearer, DPoP algs="ES256 PS256" | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<figure anchor="multi-challenge-invalid-token"><name>HTTP 401 Response to a Prot ected Resource Request with Invalid Authentication </name> | <figure anchor="multi-challenge-invalid-token"><name>HTTP 401 Response to a Prot ected Resource Request with Invalid Authentication </name> | |||
<artwork>GET /protectedresource HTTP/1.1 | <sourcecode type="http-message">GET /protectedresource HTTP/1.1 | |||
Host: resource.example.org | Host: resource.example.org | |||
Authorization: Bearer INVALID_TOKEN | Authorization: Bearer INVALID_TOKEN | |||
HTTP/1.1 401 Unauthorized | HTTP/1.1 401 Unauthorized | |||
WWW-Authenticate: Bearer error="invalid_token", \ | WWW-Authenticate: Bearer error="invalid_token", \ | |||
error_description="Invalid token", DPoP algs="ES256 PS256&quo | error_description="Invalid token", DPoP algs="ES256 PS256" | |||
t; | </sourcecode> | |||
</artwork> | ||||
</figure> | </figure> | |||
<figure anchor="multi-challenge-ambiguous"><name>HTTP 400 Response to a Protecte d Resource Request with Ambiguous Authentication </name> | <figure anchor="multi-challenge-ambiguous"><name>HTTP 400 Response to a Protecte d Resource Request with Ambiguous Authentication </name> | |||
<artwork>GET /protectedresource HTTP/1.1 | <sourcecode type="http-message">GET /protectedresource HTTP/1.1 | |||
Host: resource.example.org | Host: resource.example.org | |||
Authorization: Bearer Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | Authorization: Bearer Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | |||
Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU | |||
HTTP/1.1 400 Bad Request | HTTP/1.1 400 Bad Request | |||
WWW-Authenticate: Bearer error="invalid_request", \ | WWW-Authenticate: Bearer error="invalid_request", \ | |||
error_description="Multiple methods used to include access token", \ | error_description="Multiple methods used to include access token", \ | |||
DPoP algs="ES256 PS256", error="invalid_request", \ | DPoP algs="ES256 PS256", error="invalid_request", \ | |||
error_description="Multiple methods used to include access token" | error_description="Multiple methods used to include access token" | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
</section> | </section> | |||
<section anchor="client-considerations"><name>Client Considerations</name> | <section anchor="client-considerations"><name>Client Considerations</name> | |||
<t>Authorization including a DPoP proof may not be idempotent (depending on serv er | <t>Authorization including a DPoP proof may not be idempotent (depending on serv er | |||
enforcement of <tt>jti</tt>, <tt>iat</tt> and <tt>nonce</tt> claims). Consequent ly, all previously | enforcement of <tt>jti</tt>, <tt>iat</tt>, and <tt>nonce</tt> claims). Consequen tly, all previously | |||
idempotent requests for protected resources that were previously idempotent may | idempotent requests for protected resources that were previously idempotent may | |||
no longer be idempotent. It is RECOMMENDED that clients generate a unique DPoP | no longer be idempotent. It is <bcp14>RECOMMENDED</bcp14> that clients generate | |||
proof even when retrying idempotent requests in response to HTTP errors | a unique DPoP | |||
proof, even when retrying idempotent requests in response to HTTP errors | ||||
generally understood as transient.</t> | generally understood as transient.</t> | |||
<t>Clients that encounter frequent network errors may experience additional | <t>Clients that encounter frequent network errors may experience additional | |||
challenges when interacting with servers with more strict nonce validation | challenges when interacting with servers with stricter nonce validation | |||
implementations.</t> | implementations.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="ASNonce"><name>Authorization Server-Provided Nonce</name> | <section anchor="ASNonce"><name>Authorization Server-Provided Nonce</name> | |||
<t>This section specifies a mechanism using opaque nonces provided by the server | <t>This section specifies a mechanism using opaque nonces provided by the server | |||
that can be used to limit the lifetime of DPoP proofs. | that can be used to limit the lifetime of DPoP proofs. | |||
Without employing such a mechanism, a malicious party controlling the client | Without employing such a mechanism, a malicious party controlling the client | |||
(including potentially the end-user) | (potentially including the end-user) | |||
can create DPoP proofs for use arbitrarily far in the future.</t> | can create DPoP proofs for use arbitrarily far in the future.</t> | |||
<t>Including a nonce value contributed by the authorization server in the DPoP p roof | <t>Including a nonce value contributed by the authorization server in the DPoP p roof | |||
MAY be used by authorization servers to limit the lifetime of DPoP proofs. | <bcp14>MAY</bcp14> be used by authorization servers to limit the lifetime of DPo | |||
The server determines when and if to issue a new DPoP nonce challenge | P proofs. | |||
thereby requiring the use of the nonce value in subsequent DPoP proofs. | The server determines when to issue a new DPoP nonce challenge and if | |||
it is needed, thereby requiring the use of the nonce value in | ||||
subsequent DPoP proofs. | ||||
The logic through which the server makes that determination is out of scope of t his document.</t> | The logic through which the server makes that determination is out of scope of t his document.</t> | |||
<t>An authorization server MAY supply a nonce value to be included by the client | <t>An authorization server <bcp14>MAY</bcp14> supply a nonce value to be include | |||
in DPoP proofs sent. In this case, the authorization server responds to requests | d by the client | |||
not including a nonce | in DPoP proofs sent. In this case, the authorization server responds to requests | |||
with an HTTP <tt>400</tt> (Bad Request) error response per Section 5.2 of <xref | that do not include a nonce | |||
target="RFC6749"></xref> using <tt>use_dpop_nonce</tt> as the | with an HTTP 400 (Bad Request) error response per <xref target="RFC6749" section | |||
Format="of" section="5.2"></xref> using <tt>use_dpop_nonce</tt> as the | ||||
error code value. The authorization server includes a <tt>DPoP-Nonce</tt> HTTP h eader in the response supplying | error code value. The authorization server includes a <tt>DPoP-Nonce</tt> HTTP h eader in the response supplying | |||
a nonce value to be used when sending the subsequent request. Nonce values MUST be unpredictable. | a nonce value to be used when sending the subsequent request. Nonce values <bcp1 4>MUST</bcp14> be unpredictable. | |||
This same error code is used when supplying a new nonce value when there was a n once mismatch. | This same error code is used when supplying a new nonce value when there was a n once mismatch. | |||
The client will typically retry the request with the new nonce value supplied | The client will typically retry the request with the new nonce value supplied | |||
upon receiving a <tt>use_dpop_nonce</tt> error with an accompanying nonce value. </t> | upon receiving a <tt>use_dpop_nonce</tt> error with an accompanying nonce value. </t> | |||
<t>For example, in response to a token request without a nonce when the authoriz ation server requires one, | <t>For example, in response to a token request without a nonce when the authoriz ation server requires one, | |||
the authorization server can respond with a <tt>DPoP-Nonce</tt> value such as th e following to provide | the authorization server can respond with a <tt>DPoP-Nonce</tt> value such as th e following to provide | |||
a nonce value to include in the DPoP proof:</t> | a nonce value to include in the DPoP proof:</t> | |||
<figure><name>HTTP 400 Response to a Token Request without a Nonce | <figure anchor="http-400-response-token-without-nonce"><name>HTTP 400 Response t o a Token Request without a Nonce | |||
</name> | </name> | |||
<artwork> HTTP/1.1 400 Bad Request | <sourcecode type="http-message"> HTTP/1.1 400 Bad Request | |||
DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v | DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v | |||
{ | { | |||
"error": "use_dpop_nonce", | "error": "use_dpop_nonce", | |||
"error_description": | "error_description": | |||
"Authorization server requires nonce in DPoP proof" | "Authorization server requires nonce in DPoP proof" | |||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>Other HTTP headers and JSON fields MAY also be included in the error response | <t>Other HTTP headers and JSON fields <bcp14>MAY</bcp14> also be included in the | |||
, | error response, | |||
but there MUST NOT be more than one <tt>DPoP-Nonce</tt> header.</t> | but there <bcp14>MUST NOT</bcp14> be more than one <tt>DPoP-Nonce</tt> header.</ | |||
t> | ||||
<t>Upon receiving the nonce, the client is expected to retry its token request | <t>Upon receiving the nonce, the client is expected to retry its token request | |||
using a DPoP proof including the supplied nonce value in the <tt>nonce</tt> clai m | using a DPoP proof including the supplied nonce value in the <tt>nonce</tt> clai m | |||
of the DPoP proof. | of the DPoP proof. | |||
An example unencoded JWT Payload of such a DPoP proof including a nonce is:</t> | An example unencoded JWT payload of such a DPoP proof including a nonce is shown | |||
<figure><name>DPoP Proof Payload Including a Nonce Value | below.</t> | |||
<figure anchor="dpop-proof-payload-nonce-value"><name>DPoP Proof Payload includi | ||||
ng a Nonce Value | ||||
</name> | </name> | |||
<artwork> { | <sourcecode type="json"> { | |||
"jti": "-BwC3ESc6acc2lTc", | "jti": "-BwC3ESc6acc2lTc", | |||
"htm": "POST", | "htm": "POST", | |||
"htu": "https://server.example.com/token", | "htu": "https://server.example.com/token", | |||
"iat": 1562262616, | "iat": 1562262616, | |||
"nonce": "eyJ7S_zG.eyJH0-Z.HX4w-7v" | "nonce": "eyJ7S_zG.eyJH0-Z.HX4w-7v" | |||
} | } | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>The nonce is opaque to the client.</t> | <t>The nonce is opaque to the client.</t> | |||
<t>If the <tt>nonce</tt> claim in the DPoP proof | <t>If the <tt>nonce</tt> claim in the DPoP proof | |||
does not exactly match a nonce recently supplied by the authorization server to the client, | does not exactly match a nonce recently supplied by the authorization server to the client, | |||
the authorization server MUST reject the request. | the authorization server <bcp14>MUST</bcp14> reject the request. | |||
The rejection response MAY include a <tt>DPoP-Nonce</tt> HTTP header | The rejection response <bcp14>MAY</bcp14> include a <tt>DPoP-Nonce</tt> HTTP hea | |||
der | ||||
providing a new nonce value to use for subsequent requests.</t> | providing a new nonce value to use for subsequent requests.</t> | |||
<t>The intent is that clients need to keep only one nonce value and servers keep | ||||
a | <t>The intent is that clients need to keep only one nonce value and servers need | |||
to keep a | ||||
window of recent nonces. | window of recent nonces. | |||
That said, transient circumstances may arise in which the server's and client's | That said, transient circumstances may arise in which the | |||
stored nonce values differ. | stored nonce values for the server and the client differ. | |||
However, this situation is self-correcting; | However, this situation is self-correcting. | |||
with any rejection message, | With any rejection message, | |||
the server can send the client the nonce value that the server wants it to use | the server can send the client the nonce value it wants to use | |||
and the client can store that nonce value and retry the request with it. | to the client, and the client can store that nonce value and retry the request w | |||
ith it. | ||||
Even if the client and/or server discard their stored nonce values, | Even if the client and/or server discard their stored nonce values, | |||
that situation is also self-correcting because new nonce values can be communica ted | that situation is also self-correcting because new nonce values can be communica ted | |||
when responding to or retrying failed requests.</t> | when responding to or retrying failed requests.</t> | |||
<t>Note that browser-based client applications using CORS <xref target="WHATWG.F etch"></xref> only have access | <t>Note that browser-based client applications using CORS <xref target="WHATWG.F etch"></xref> only have access | |||
to CORS-safelisted response HTTP headers by default. | to CORS-safelisted response HTTP headers by default. | |||
In order for the application to obtain and use the <tt>DPoP-Nonce</tt> HTTP resp onse header | In order for the application to obtain and use the <tt>DPoP-Nonce</tt> HTTP resp onse header | |||
value, the server needs to make it available to the application by including | value, the server needs to make it available to the application by including | |||
<tt>DPoP-Nonce</tt> in the <tt>Access-Control-Expose-Headers</tt> response heade r list value.</t> | <tt>DPoP-Nonce</tt> in the <tt>Access-Control-Expose-Headers</tt> response heade r list value.</t> | |||
<section anchor="NonceSyntax"><name>Nonce Syntax</name> | <section anchor="NonceSyntax"><name>Nonce Syntax</name> | |||
<t>The nonce syntax in ABNF as used by <xref target="RFC6749"></xref> | <t>The nonce syntax in ABNF as used by <xref target="RFC6749"></xref> | |||
(which is the same as the <tt>scope-token</tt> syntax) is:</t> | (which is the same as the scope-token syntax) is shown below.</t> | |||
<figure><name>Nonce ABNF | <figure anchor="nonce-abnf"><name>Nonce ABNF | |||
</name> | </name> | |||
<artwork> nonce = 1*NQCHAR | <sourcecode type="abnf"><![CDATA[nonce = 1*NQCHAR]]></sourcecode> | |||
</artwork> | ||||
</figure> | </figure> | |||
</section> | </section> | |||
<section anchor="NewNonce"><name>Providing a New Nonce Value</name> | <section anchor="NewNonce"><name>Providing a New Nonce Value</name> | |||
<t>It is up to the authorization server when to supply a new nonce value | <t>It is up to the authorization server when to supply a new nonce value | |||
for the client to use. | for the client to use. | |||
The client is expected to use the existing supplied nonce in DPoP proofs | The client is expected to use the existing supplied nonce in DPoP proofs | |||
until the server supplies a new nonce value.</t> | until the server supplies a new nonce value.</t> | |||
<t>The authorization server MAY supply the new nonce in the same way that | <t>The authorization server <bcp14>MAY</bcp14> supply the new nonce in the same | |||
the initial one was supplied: | way that | |||
by using a <tt>DPoP-Nonce</tt> HTTP header in the response. | the initial one was supplied: by using a <tt>DPoP-Nonce</tt> HTTP header in the | |||
response. | ||||
The <tt>DPoP-Nonce</tt> HTTP header field uses the nonce syntax defined in <xref target="NonceSyntax"></xref>. | The <tt>DPoP-Nonce</tt> HTTP header field uses the nonce syntax defined in <xref target="NonceSyntax"></xref>. | |||
Of course, each time this happens it requires an extra protocol round trip.</t> | Each time this happens, it requires an extra protocol round trip.</t> | |||
<t>A more efficient manner of supplying a new nonce value is also defined -- | <t>A more efficient manner of supplying a new nonce value is also defined | |||
by including a <tt>DPoP-Nonce</tt> HTTP header | by including a <tt>DPoP-Nonce</tt> HTTP header | |||
in the HTTP <tt>200</tt> (OK) response from the previous request. | in the HTTP 200 (OK) response from the previous request. | |||
The client MUST use the new nonce value supplied for the next token request, | The client <bcp14>MUST</bcp14> use the new nonce value supplied for the next tok | |||
en request | ||||
and for all subsequent token requests until the authorization server | and for all subsequent token requests until the authorization server | |||
supplies a new nonce.</t> | supplies a new nonce.</t> | |||
<t>Responses that include the <tt>DPoP-Nonce</tt> HTTP header should be uncachea ble | <t>Responses that include the <tt>DPoP-Nonce</tt> HTTP header should be uncachea ble | |||
(e.g., using <tt>Cache-Control: no-store</tt> in response to a <tt>GET</tt> requ est) to | (e.g., using <tt>Cache-Control: no-store</tt> in response to a <tt>GET</tt> requ est) to | |||
prevent the response being used to serve a subsequent request and a stale | prevent the response from being used to serve a subsequent request and a stale | |||
nonce value being used as a result.</t> | nonce value from being used as a result.</t> | |||
<t>An example 200 OK response providing a new nonce value is:</t> | <t>An example 200 OK response providing a new nonce value is shown below.</t> | |||
<figure><name>HTTP 200 Response Providing the Next Nonce Value | <figure anchor="http-200-response-next-nonce-value"><name>HTTP 200 Response Prov | |||
iding the Next Nonce Value | ||||
</name> | </name> | |||
<artwork> HTTP/1.1 200 OK | <sourcecode type="http-message"> HTTP/1.1 200 OK | |||
Cache-Control: no-store | Cache-Control: no-store | |||
DPoP-Nonce: eyJ7S_zG.eyJbYu3.xQmBj-1 | DPoP-Nonce: eyJ7S_zG.eyJbYu3.xQmBj-1 | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="RSNonce"><name>Resource Server-Provided Nonce</name> | <section anchor="RSNonce"><name>Resource Server-Provided Nonce</name> | |||
<t>Resource servers can also choose to provide a nonce value to be included | <t>Resource servers can also choose to provide a nonce value to be included | |||
in DPoP proofs sent to them. | in DPoP proofs sent to them. | |||
They provide the nonce using the <tt>DPoP-Nonce</tt> header in the same way that authorization servers do | They provide the nonce using the <tt>DPoP-Nonce</tt> header in the same way that authorization servers do | |||
as described in <xref target="ASNonce"></xref> and <xref target="NewNonce"></xre f>. | as described in Sections <xref target="ASNonce" format="counter"></xref> and <xr ef target="NewNonce" format="counter"></xref>. | |||
The error signaling is performed as described in <xref target="http-auth-scheme" ></xref>. | The error signaling is performed as described in <xref target="http-auth-scheme" ></xref>. | |||
Resource servers use an HTTP <tt>401</tt> (Unauthorized) error code | Resource servers use an HTTP 401 (Unauthorized) error code | |||
with an accompanying <tt>WWW-Authenticate: DPoP</tt> value | with an accompanying <tt>WWW-Authenticate: DPoP</tt> value | |||
and <tt>DPoP-Nonce</tt> value to accomplish this.</t> | and <tt>DPoP-Nonce</tt> value to accomplish this.</t> | |||
<t>For example, in response to a resource request without a nonce when the resou rce server requires one, | <t>For example, in response to a resource request without a nonce when the resou rce server requires one, | |||
the resource server can respond with a <tt>DPoP-Nonce</tt> value such as the fol lowing to provide | the resource server can respond with a <tt>DPoP-Nonce</tt> value such as the fol lowing to provide | |||
a nonce value to include in the DPoP proof | a nonce value to include in the DPoP proof. | |||
(with '\' line wrapping per RFC 8792):</t> | The example below uses "\" line wrapping per <xref target="RFC8792"/>.</t> | |||
<figure><name>HTTP 401 Response to a Resource Request without a Nonce | <figure anchor="http-401-response-resource-request-without-nonce"><name>HTTP 401 | |||
Response to a Resource Request without a Nonce | ||||
</name> | </name> | |||
<artwork> HTTP/1.1 401 Unauthorized | <sourcecode type="http-message"> HTTP/1.1 401 Unauthorized | |||
WWW-Authenticate: DPoP error="use_dpop_nonce", \ | WWW-Authenticate: DPoP error="use_dpop_nonce", \ | |||
error_description="Resource server requires nonce in DPoP proof" | error_description="Resource server requires nonce in DPoP proof" | |||
DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v | DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v | |||
</artwork> | </sourcecode> | |||
</figure> | </figure> | |||
<t>Note that the nonces provided by an authorization server and a resource serve r are different | <t>Note that the nonces provided by an authorization server and a resource serve r are different | |||
and should not be confused with one another, | and should not be confused with one another | |||
since nonces will be only accepted by the server that issued them. | since nonces will be only accepted by the server that issued them. | |||
Likewise, should a client use multiple authorization servers and/or resource ser vers, | Likewise, should a client use multiple authorization servers and/or resource ser vers, | |||
a nonce issued by any of them should be used only at the issuing server. | a nonce issued by any of them should be used only at the issuing server. | |||
Developers should also take care to not confuse DPoP nonces with the | Developers should also be careful to not confuse DPoP nonces with the | |||
OpenID Connect <xref target="OpenID.Core"></xref> ID Token nonce.</t> | OpenID Connect <xref target="OpenID.Core"></xref> ID Token nonce.</t> | |||
</section> | </section> | |||
<section anchor="dpop_jkt"><name>Authorization Code Binding to DPoP Key</name> | <section anchor="dpop_jkt"><name>Authorization Code Binding to a DPoP Key</name> | |||
<t>Binding the authorization code issued to the client's proof-of-possession key | <t>Binding the authorization code issued to the client's proof-of-possession key | |||
can enable end-to-end binding of the entire authorization flow. | can enable end-to-end binding of the entire authorization flow. | |||
This specification defines the <tt>dpop_jkt</tt> authorization request parameter for this purpose. | This specification defines the <tt>dpop_jkt</tt> authorization request parameter for this purpose. | |||
The value of the <tt>dpop_jkt</tt> authorization request parameter is the | The value of the <tt>dpop_jkt</tt> authorization request parameter is the | |||
JSON Web Key (JWK) Thumbprint <xref target="RFC7638"></xref> of the proof-of-pos | JWK Thumbprint <xref target="RFC7638"></xref> of the proof-of-possession public | |||
session public key | key | |||
using the SHA-256 hash function - | using the SHA-256 hash function, which is | |||
the same value as used for the <tt>jkt</tt> confirmation method defined in <xref target="jwk-thumb-jwt"></xref>.</t> | the same value as used for the <tt>jkt</tt> confirmation method defined in <xref target="jwk-thumb-jwt"></xref>.</t> | |||
<t>When a token request is received, the authorization server computes the | <t>When a token request is received, the authorization server computes the | |||
JWK thumbprint of the proof-of-possession public key in the DPoP proof | JWK Thumbprint of the proof-of-possession public key in the DPoP proof | |||
and verifies that it matches the <tt>dpop_jkt</tt> parameter value in the author ization request. | and verifies that it matches the <tt>dpop_jkt</tt> parameter value in the author ization request. | |||
If they do not match, it MUST reject the request.</t> | If they do not match, it <bcp14>MUST</bcp14> reject the request.</t> | |||
<t>An example authorization request using the <tt>dpop_jkt</tt> authorization re | <t>An example authorization request using the <tt>dpop_jkt</tt> authorization re | |||
quest parameter follows | quest parameter is shown below and uses "\" line wrapping per <xref target="RFC8 | |||
(with '\' line wrapping per RFC 8792):</t> | 792"/>.</t> | |||
<figure><name>Authorization Request using the <tt>dpop_jkt</tt> Parameter | <figure anchor="auth-req-using-dpopjkt-parameter"><name>Authorization Request Us | |||
ing the <tt>dpop_jkt</tt> Parameter | ||||
</name> | </name> | |||
<artwork> GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=x | <sourcecode type="http-message"><![CDATA[ | |||
yz\ | GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz\ | |||
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\ | &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\ | |||
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\ | &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\ | |||
&code_challenge_method=S256\ | &code_challenge_method=S256\ | |||
&dpop_jkt=NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs HTTP/1.1 | &dpop_jkt=NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs HTTP/1.1 | |||
Host: server.example.com | Host: server.example.com | |||
</artwork> | ]]></sourcecode> | |||
</figure> | </figure> | |||
<t>Use of the <tt>dpop_jkt</tt> authorization request parameter is OPTIONAL. | <t>Use of the <tt>dpop_jkt</tt> authorization request parameter is <bcp14>OPTION | |||
Note that the <tt>dpop_jkt</tt> authorization request parameter MAY also be used | AL</bcp14>. | |||
in combination with PKCE <xref target="RFC7636"></xref>, which is recommended by | Note that the <tt>dpop_jkt</tt> authorization request parameter <bcp14>MAY</bcp1 | |||
<xref target="I-D.ietf-oauth-security-topics"></xref> | 4> also be used | |||
in combination with Proof Key for Code Exchange (PKCE) <xref target="RFC7636"></ | ||||
xref>, which is recommended by <xref target="I-D.ietf-oauth-security-topics"></x | ||||
ref> | ||||
as a countermeasure to authorization code injection. The <tt>dpop_jkt</tt> autho rization | as a countermeasure to authorization code injection. The <tt>dpop_jkt</tt> autho rization | |||
request parameter only provides similar protections when a unique DPoP key is | request parameter only provides similar protections when a unique DPoP key is | |||
used for each authorization request.</t> | used for each authorization request.</t> | |||
<section anchor="dpop-with-pushed-authorization-requests"><name>DPoP with Pushed Authorization Requests</name> | <section anchor="dpop-with-pushed-authorization-requests"><name>DPoP with Pushed Authorization Requests</name> | |||
<t>When Pushed Authorization Requests (PAR, <xref target="RFC9126"></xref>) are used in conjunction with DPoP, there are two ways in which the DPoP key can be communicated in the PAR request:</t> | <t>When Pushed Authorization Requests (PARs) <xref target="RFC9126"></xref> are used in conjunction with DPoP, there are two ways in which the DPoP key can be c ommunicated in the PAR request:</t> | |||
<ul spacing="compact"> | <ul spacing="compact"> | |||
<li>The <tt>dpop_jkt</tt> parameter can be used as described in <xref target="dp op_jkt"></xref> to bind the issued | <li>The <tt>dpop_jkt</tt> parameter can be used as described in <xref target="dp op_jkt"></xref> to bind the issued | |||
authorization code to a specific key. In this case, <tt>dpop_jkt</tt> MUST be in cluded alongside other authorization request parameters in the POST body of the PAR request.</li> | authorization code to a specific key. In this case, <tt>dpop_jkt</tt> <bcp14>MUS T</bcp14> be included alongside other authorization request parameters in the PO ST body of the PAR request.</li> | |||
<li>Alternatively, the <tt>DPoP</tt> header can be added to the PAR request. In this | <li>Alternatively, the <tt>DPoP</tt> header can be added to the PAR request. In this | |||
case, the authorization server MUST check the provided DPoP proof JWT as | case, the authorization server <bcp14>MUST</bcp14> check the provided DPoP proof | |||
defined in <xref target="checking"></xref>. It MUST further behave as if the con | JWT as | |||
tained public key's | defined in <xref target="checking"></xref>. It <bcp14>MUST</bcp14> further behav | |||
e as if the contained public key's | ||||
thumbprint was provided using <tt>dpop_jkt</tt>, i.e., reject the subsequent tok en | thumbprint was provided using <tt>dpop_jkt</tt>, i.e., reject the subsequent tok en | |||
request unless a DPoP proof for the same key is provided. This can help to | request unless a DPoP proof for the same key is provided. This can help to | |||
simplify the implementation of the client, as it can "blindly" attach the | simplify the implementation of the client, as it can "blindly" attach the | |||
<tt>DPoP</tt> header to all requests to the authorization server regardless of t he | <tt>DPoP</tt> header to all requests to the authorization server regardless of t he | |||
type of request. Additionally, it provides a stronger binding, as the <tt>DPoP</ tt> | type of request. Additionally, it provides a stronger binding, as the <tt>DPoP</ tt> | |||
header contains a proof of possession of the private key.</li> | header contains a proof of possession of the private key.</li> | |||
</ul> | </ul> | |||
<t>Both mechanisms MUST be supported by an authorization server that supports PA | <t>Both mechanisms <bcp14>MUST</bcp14> be supported by an authorization server t | |||
R and DPoP. If both mechanisms are used at the same time, the authorization serv | hat supports PAR and DPoP. If both mechanisms are used at the same time, the aut | |||
er MUST reject the request if the JWK Thumbprint in <tt>dpop_jkt</tt> does not m | horization server <bcp14>MUST</bcp14> reject the request if the JWK Thumbprint i | |||
atch the public key in the <tt>DPoP</tt> header.</t> | n <tt>dpop_jkt</tt> does not match the public key in the <tt>DPoP</tt> header.</ | |||
<t>Allowing both mechanisms ensures that clients that use <tt>dpop_jkt</tt> do n | t> | |||
ot need to | <t>Allowing both mechanisms ensures that clients using <tt>dpop_jkt</tt> do not | |||
need to | ||||
distinguish between front-channel and pushed authorization requests, and at the | distinguish between front-channel and pushed authorization requests, and at the | |||
same time, clients that only have one code path for protecting all calls to auth orization server | same time, clients that only have one code path for protecting all calls to auth orization server | |||
endpoints do not need to distinguish between requests to the PAR endpoint and | endpoints do not need to distinguish between requests to the PAR endpoint and th | |||
the token endpoint.</t> | e | |||
token endpoint.</t> | ||||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="Security"><name>Security Considerations</name> | <section anchor="Security"><name>Security Considerations</name> | |||
<t>In DPoP, the prevention of token replay at a different endpoint (see | <t>In DPoP, the prevention of token replay at a different endpoint (see | |||
<xref target="objective"></xref>) is achieved through authentication of the serv er per <xref target="RFC6125"></xref> and | <xref target="objective"></xref>) is achieved through authentication of the serv er per <xref target="RFC6125"></xref> and | |||
binding of the DPoP proof to a certain URI and HTTP method. DPoP, however, | the binding of the DPoP proof to a certain URI and HTTP method. However, DPoP | |||
has a somewhat different nature of protection than TLS-based | has a somewhat different nature of protection than TLS-based | |||
methods such as OAuth Mutual TLS <xref target="RFC8705"></xref> or OAuth Token | methods such as OAuth Mutual TLS <xref target="RFC8705"></xref> or OAuth Token | |||
Binding <xref target="I-D.ietf-oauth-token-binding"></xref> (see also <xref targ et="Token_Replay"></xref> and <xref target="request_integrity"></xref>). | Binding <xref target="I-D.ietf-oauth-token-binding"></xref> (see also Sections < xref target="Token_Replay" format="counter"/> and <xref target="request_integrit y" format="counter"/>). | |||
TLS-based mechanisms can leverage a tight integration | TLS-based mechanisms can leverage a tight integration | |||
between the TLS layer and the application layer to achieve strong | between the TLS layer and the application layer to achieve strong | |||
message integrity, authenticity, | message integrity, authenticity, | |||
and replay protection.</t> | and replay protection.</t> | |||
<section anchor="Token_Replay"><name>DPoP Proof Replay</name> | <section anchor="Token_Replay"><name>DPoP Proof Replay</name> | |||
<t>If an adversary is able to get hold of a DPoP proof JWT, the adversary | <t>If an adversary is able to get hold of a DPoP proof JWT, the adversary | |||
could replay that token at the same endpoint (the HTTP endpoint | could replay that token at the same endpoint (the HTTP endpoint | |||
and method are enforced via the respective claims in the JWTs). To | and method are enforced via the respective claims in the JWTs). To | |||
limit this, servers MUST only accept DPoP proofs for a limited time | limit this, servers <bcp14>MUST</bcp14> only accept DPoP proofs for a limited ti me | |||
after their creation (preferably only for a relatively brief period | after their creation (preferably only for a relatively brief period | |||
on the order of seconds or minutes).</t> | on the order of seconds or minutes).</t> | |||
<t>To prevent multiple uses of the same DPoP proof, servers can store, in | <t>In the context of the target URI, servers can store the <tt>jti</tt> value of | |||
the context of the target URI, the <tt>jti</tt> value of each DPoP proof for the | each DPoP proof for the time window in which the respective DPoP proof JWT | |||
time window in which the respective DPoP proof JWT would be accepted. | would be accepted to prevent multiple uses of the same DPoP proof. | |||
HTTP requests to the same URI for which the <tt>jti</tt> value has been seen bef ore | HTTP requests to the same URI for which the <tt>jti</tt> value has been seen bef ore | |||
would be declined. Such a single-use check, | would be declined. When strictly enforced, such a single-use check provides a ve | |||
when strictly enforced, provides a very strong protection against DPoP | ry strong protection against DPoP | |||
proof replay, but may not always be feasible in practice, e.g., when | proof replay, but it may not always be feasible in practice, e.g., when | |||
multiple servers behind a single endpoint have no shared state.</t> | multiple servers behind a single endpoint have no shared state.</t> | |||
<t>In order to guard against | <t>In order to guard against | |||
memory exhaustion attacks, a server that is tracking <tt>jti</tt> values should reject | memory exhaustion attacks, a server that is tracking <tt>jti</tt> values should reject | |||
DPoP proof JWTs with unnecessarily large <tt>jti</tt> values or store only a has h thereof.</t> | DPoP proof JWTs with unnecessarily large <tt>jti</tt> values or store only a has h thereof.</t> | |||
<t>Note: To accommodate for clock offsets, the server MAY accept DPoP | <t>Note: To accommodate for clock offsets, the server <bcp14>MAY</bcp14> accept DPoP | |||
proofs that carry an <tt>iat</tt> time in the reasonably near future (on the ord er of seconds or minutes). | proofs that carry an <tt>iat</tt> time in the reasonably near future (on the ord er of seconds or minutes). | |||
Because clock skews between servers | Because clock skews between servers | |||
and clients may be large, servers MAY limit DPoP proof lifetimes by using | and clients may be large, servers <bcp14>MAY</bcp14> limit DPoP proof lifetimes by using | |||
server-provided nonce values containing the time at the server rather than | server-provided nonce values containing the time at the server rather than | |||
comparing the client-supplied <tt>iat</tt> time to the time at the server. Nonc es | comparing the client-supplied <tt>iat</tt> time to the time at the server. Nonc es | |||
created in this way yield the same result even in the face of arbitrarily | created in this way yield the same result even in the face of arbitrarily | |||
large clock skews.</t> | large clock skews.</t> | |||
<t>Server-provided nonces are an effective means for further reducing the chance s for successful DPoP proof replay. | <t>Server-provided nonces are an effective means for further reducing the chance s for successful DPoP proof replay. | |||
Unlike cryptographic nonces, it is acceptable for clients to use the same | Unlike cryptographic nonces, it is acceptable for clients to use the same | |||
<tt>nonce</tt> multiple times, and for the server to accept the same nonce multi | <tt>nonce</tt> multiple times and for the server to accept the same nonce multip | |||
ple | le | |||
times. As long as the <tt>jti</tt> value is tracked and duplicates rejected for | times. As long as the <tt>jti</tt> value is tracked and duplicates are rejected | |||
the lifetime of the <tt>nonce</tt>, there | for the lifetime of the <tt>nonce</tt>, there | |||
is no additional risk of token replay.</t> | is no additional risk of token replay.</t> | |||
</section> | </section> | |||
<section anchor="Pre-Generation"><name>DPoP Proof Pre-Generation</name> | <section anchor="Pre-Generation"><name>DPoP Proof Pre-generation</name> | |||
<t>An attacker in control of the client can pre-generate DPoP proofs for | <t>An attacker in control of the client can pre-generate DPoP proofs for | |||
specific endpoints arbitrarily far into the future by choosing the | specific endpoints arbitrarily far into the future by choosing the | |||
<tt>iat</tt> value in the DPoP proof to be signed by the proof-of-possession key . | <tt>iat</tt> value in the DPoP proof to be signed by the proof-of-possession key . | |||
Note that one such attacker is the person who is the legitimate user of the clie nt. | Note that one such attacker is the person who is the legitimate user of the clie nt. | |||
The user may pre-generate DPoP proofs to exfiltrate | The user may pre-generate DPoP proofs to exfiltrate | |||
from the machine possessing the proof-of-possession key | from the machine possessing the proof-of-possession key | |||
upon which they were generated | upon which they were generated | |||
and copy them to another machine that does not possess the key. | and copy them to another machine that does not possess the key. | |||
For instance, a bank employee might pre-generate DPoP proofs | For instance, a bank employee might pre-generate DPoP proofs | |||
on a bank computer and then copy them to another machine | on a bank computer and then copy them to another machine | |||
skipping to change at line 1155 ¶ | skipping to change at line 1178 ¶ | |||
is possession of a DPoP proof -- not of the proof-of-possession key.</t> | is possession of a DPoP proof -- not of the proof-of-possession key.</t> | |||
<t>Use of server-provided nonce values that are not predictable by attackers can prevent this attack. | <t>Use of server-provided nonce values that are not predictable by attackers can prevent this attack. | |||
By providing new nonce values at times of its choosing, | By providing new nonce values at times of its choosing, | |||
the server can limit the lifetime of DPoP proofs, | the server can limit the lifetime of DPoP proofs, | |||
preventing pre-generated DPoP proofs from being used. | preventing pre-generated DPoP proofs from being used. | |||
When server-provided nonces are used, possession | When server-provided nonces are used, possession | |||
of the proof-of-possession key is being demonstrated -- | of the proof-of-possession key is being demonstrated -- | |||
not just possession of a DPoP proof.</t> | not just possession of a DPoP proof.</t> | |||
<t>The <tt>ath</tt> claim limits the use of pre-generated DPoP proofs to the lif etime | <t>The <tt>ath</tt> claim limits the use of pre-generated DPoP proofs to the lif etime | |||
of the access token. Deployments that do not utilize the nonce mechanism | of the access token. Deployments that do not utilize the nonce mechanism | |||
SHOULD NOT issue long-lived DPoP constrained access tokens, | <bcp14>SHOULD NOT</bcp14> issue long-lived DPoP constrained access tokens, | |||
preferring instead to use short-lived access tokens and refresh tokens. | preferring instead to use short-lived access tokens and refresh tokens. | |||
Whilst an attacker could pre-generate DPoP proofs to use the refresh token | Whilst an attacker could pre-generate DPoP proofs to use the refresh token | |||
to obtain a new access token, they would be unable to realistically | to obtain a new access token, they would be unable to realistically | |||
pre-generate DPoP proofs to use a newly issued access token.</t> | pre-generate DPoP proofs to use a newly issued access token.</t> | |||
</section> | </section> | |||
<section anchor="Nonce-Downgrade"><name>DPoP Nonce Downgrade</name> | <section anchor="Nonce-Downgrade"><name>DPoP Nonce Downgrade</name> | |||
<t>A server MUST NOT accept any DPoP proofs without the <tt>nonce</tt> claim whe n a DPoP nonce has been provided to the client.</t> | <t>A server <bcp14>MUST NOT</bcp14> accept any DPoP proofs without the <tt>nonce </tt> claim when a DPoP nonce has been provided to the client.</t> | |||
</section> | </section> | |||
<section anchor="untrusted-code-in-the-client-context"><name>Untrusted Code in t he Client Context</name> | <section anchor="untrusted-code-in-the-client-context"><name>Untrusted Code in t he Client Context</name> | |||
<t>If an adversary is able to run code in the client's execution context, | <t>If an adversary is able to run code in the client's execution context, | |||
the security of DPoP is no longer guaranteed. Common issues in web | the security of DPoP is no longer guaranteed. Common issues in web | |||
applications leading to the execution of untrusted code are cross-site | applications leading to the execution of untrusted code are XSS and remote code | |||
scripting and remote code inclusion attacks.</t> | inclusion attacks.</t> | |||
<t>If the private key used for DPoP is stored in such a way that it | <t>If the private key used for DPoP is stored in such a way that it | |||
cannot be exported, e.g., in a hardware or software security module, | cannot be exported, e.g., in a hardware or software security module, | |||
the adversary cannot exfiltrate the key and use it to create arbitrary | the adversary cannot exfiltrate the key and use it to create arbitrary | |||
DPoP proofs. The adversary can, however, create new DPoP proofs as | DPoP proofs. The adversary can, however, create new DPoP proofs as | |||
long as the client is online, and use these proofs (together with the | long as the client is online and uses these proofs (together with the | |||
respective tokens) either on the victim's device or on a device under | respective tokens) either on the victim's device or on a device under | |||
the attacker's control to send arbitrary requests that will be | the attacker's control to send arbitrary requests that will be | |||
accepted by servers.</t> | accepted by servers.</t> | |||
<t>To send requests even when the client is offline, an adversary can try | <t>To send requests even when the client is offline, an adversary can try | |||
to pre-compute DPoP proofs using timestamps in the future and | to pre-compute DPoP proofs using timestamps in the future and | |||
exfiltrate these together with the access or refresh token.</t> | exfiltrate these together with the access or refresh token.</t> | |||
<t>An adversary might further try to associate tokens issued from the | <t>An adversary might further try to associate tokens issued from the | |||
token endpoint with a key pair under the adversary's control. One way | token endpoint with a key pair under the adversary's control. One way | |||
to achieve this is to modify existing code, e.g., by replacing | to achieve this is to modify existing code, e.g., by replacing | |||
cryptographic APIs. Another way is to launch a new authorization grant | cryptographic APIs. Another way is to launch a new authorization grant | |||
between the client and the authorization server in an iframe. This | between the client and the authorization server in an iframe. This | |||
grant needs to be "silent", i.e., not require interaction with the | grant needs to be "silent", i.e., not require interaction with the | |||
user. With code running in the client's origin, the adversary has | user. With code running in the client's origin, the adversary has | |||
access to the resulting authorization code and can use it to associate | access to the resulting authorization code and can use it to associate | |||
their own DPoP keys with the tokens returned from the token endpoint. | their own DPoP keys with the tokens returned from the token endpoint. | |||
The adversary is then able to use the resulting tokens on their own | The adversary is then able to use the resulting tokens on their own | |||
device even if the client is offline.</t> | device even if the client is offline.</t> | |||
<t>Therefore, protecting clients against the execution of untrusted code | <t>Therefore, protecting clients against the execution of untrusted code | |||
is extremely important even if DPoP is used. Besides secure coding | is extremely important even if DPoP is used. Besides secure coding | |||
practices, Content Security Policy <xref target="W3C.CSP"></xref> can be used as a second | practices, Content Security Policy <xref target="W3C.CSP"></xref> can be used as a second | |||
layer of defense against cross-site scripting.</t> | layer of defense against XSS.</t> | |||
</section> | </section> | |||
<section anchor="signed-jwt-swapping"><name>Signed JWT Swapping</name> | <section anchor="signed-jwt-swapping"><name>Signed JWT Swapping</name> | |||
<t>Servers accepting signed DPoP proof JWTs MUST verify that the <tt>typ</tt> fi eld is <tt>dpop+jwt</tt> in the | <t>Servers accepting signed DPoP proof JWTs <bcp14>MUST</bcp14> verify that the <tt>typ</tt> field is <tt>dpop+jwt</tt> in the | |||
headers of the JWTs to ensure that adversaries cannot use JWTs created | headers of the JWTs to ensure that adversaries cannot use JWTs created | |||
for other purposes.</t> | for other purposes.</t> | |||
</section> | </section> | |||
<section anchor="signature-algorithms"><name>Signature Algorithms</name> | <section anchor="signature-algorithms"><name>Signature Algorithms</name> | |||
<t>Implementers MUST ensure that only asymmetric digital signature algorithms (s uch as <tt>ES256</tt>) that | <t>Implementers <bcp14>MUST</bcp14> ensure that only asymmetric digital signatur e algorithms (such as <tt>ES256</tt>) that | |||
are deemed secure can be used for signing DPoP proofs. In particular, | are deemed secure can be used for signing DPoP proofs. In particular, | |||
the algorithm <tt>none</tt> MUST NOT be allowed.</t> | the algorithm <tt>none</tt> <bcp14>MUST NOT</bcp14> be allowed.</t> | |||
</section> | </section> | |||
<section anchor="request_integrity"><name>Request Integrity</name> | <section anchor="request_integrity"><name>Request Integrity</name> | |||
<t>DPoP does not ensure the integrity of the payload or headers of | <t>DPoP does not ensure the integrity of the payload or headers of | |||
requests. The DPoP proof only contains claims for the HTTP URI and | requests. The DPoP proof only contains claims for the HTTP URI and | |||
method, but not, for example, the message body or general request | method, but not the message body or general request | |||
headers.</t> | headers, for example.</t> | |||
<t>This is an intentional design decision intended to keep DPoP simple to use, b ut | <t>This is an intentional design decision intended to keep DPoP simple to use, b ut | |||
as described, makes DPoP potentially susceptible to replay attacks | as described, it makes DPoP potentially susceptible to replay attacks | |||
where an attacker is able to modify message contents and headers. In | where an attacker is able to modify message contents and headers. In | |||
many setups, the message integrity and confidentiality provided by TLS | many setups, the message integrity and confidentiality provided by TLS | |||
is sufficient to provide a good level of protection.</t> | is sufficient to provide a good level of protection.</t> | |||
<t>Note: While signatures covering other parts of requests are out of the scope of | <t>Note: While signatures covering other parts of requests are out of the scope of | |||
this specification, additional information to be signed can be | this specification, additional information to be signed can be | |||
added into DPoP proofs.</t> | added into DPoP proofs.</t> | |||
</section> | </section> | |||
<section anchor="access-token-and-public-key-binding"><name>Access Token and Pub lic Key Binding</name> | <section anchor="access-token-and-public-key-binding"><name>Access Token and Pub lic Key Binding</name> | |||
<t>The binding of the access token to the DPoP public key, which is | <t>The binding of the access token to the DPoP public key, as specified in <xref | |||
specified in <xref target="Confirmation"></xref>, uses a cryptographic hash of t | target="Confirmation"></xref>, uses a cryptographic hash of the JWK | |||
he JWK | ||||
representation of the public key. It relies | representation of the public key. It relies | |||
on the hash function having sufficient second-preimage resistance so | on the hash function having sufficient second-preimage resistance so | |||
as to make it computationally infeasible to find or create another | as to make it computationally infeasible to find or create another | |||
key that produces to the same hash output value. The SHA-256 | key that produces to the same hash output value. The SHA-256 | |||
hash function was used because it meets the aforementioned | hash function was used because it meets the aforementioned | |||
requirement while being widely available.</t> | requirement while being widely available.</t> | |||
<t>Similarly, the binding of the DPoP proof to the access token uses a | <t>Similarly, the binding of the DPoP proof to the access token uses a | |||
hash of that access token as the value of the <tt>ath</tt> claim | hash of that access token as the value of the <tt>ath</tt> claim | |||
in the DPoP proof (see <xref target="DPoP-Proof-Syntax"></xref>). This relies on the value | in the DPoP proof (see <xref target="DPoP-Proof-Syntax"></xref>). This relies on the value | |||
of the hash being sufficiently unique so as to reliably identify the | of the hash being sufficiently unique so as to reliably identify the | |||
access token. The collision resistance of SHA-256 meets that requirement.</t> | access token. The collision resistance of SHA-256 meets that requirement.</t> | |||
</section> | </section> | |||
<section anchor="authorization-code-and-public-key-binding"><name>Authorization Code and Public Key Binding</name> | <section anchor="authorization-code-and-public-key-binding"><name>Authorization Code and Public Key Binding</name> | |||
<t>Cryptographic binding of the authorization code to the DPoP public key, | <t>Cryptographic binding of the authorization code to the DPoP public key | |||
is specified in <xref target="dpop_jkt"></xref>. | is specified in <xref target="dpop_jkt"></xref>. | |||
This binding prevents attacks in which the attacker captures the authorization c | This binding prevents attacks in which the attacker captures the | |||
ode | authorization code and creates a DPoP proof using a proof-of-possession key | |||
and creates a DPoP proof using a proof-of-possession key | other than the one held by the client and redeems the authorization code | |||
other than that held by the client | using that DPoP proof. By ensuring end to end that only the client's DPoP | |||
and redeems the authorization code using that DPoP proof. | key can be used, this prevents captured authorization codes from being | |||
By ensuring end-to-end that only the client's DPoP key can be used, | exfiltrated and used at locations other than the one to which the | |||
this prevents captured authorization codes from being exfiltrated and used | authorization code was issued.</t> | |||
at locations other than the one to which the authorization code was issued.</t> | ||||
<t>Authorization codes can, for instance, be harvested by attackers | <t>Authorization codes can, for instance, be harvested by attackers | |||
from places that the HTTP messages containing them are logged. | from places where the HTTP messages containing them are logged. | |||
Even when efforts are made to make authorization codes one-time-use, | Even when efforts are made to make authorization codes one-time-use, in practice | |||
in practice, there is often a time window during which attackers can replay them | , | |||
. | there is often a time window during which attackers can replay them. | |||
For instance, when authorization servers are implemented as scalable replicated services, | For instance, when authorization servers are implemented as scalable replicated services, | |||
some replicas may temporarily not yet have the information needed to prevent rep lay. | some replicas may temporarily not yet have the information needed to prevent rep lay. | |||
DPoP binding of the authorization code solves these problems.</t> | DPoP binding of the authorization code solves these problems.</t> | |||
<t>If an authorization server does not (or cannot) strictly enforce the single-u se limitation for authorization codes | <t>If an authorization server does not (or cannot) strictly enforce the single-u se limitation for authorization codes | |||
and an attacker can access the authorization code (and if PKCE is used, the <tt> code_verifier</tt>), | and an attacker can access the authorization code (and if PKCE is used, the <tt> code_verifier</tt>), | |||
the attacker can create a forged token request, binding the resulting token to a n attacker-controlled key. | the attacker can create a forged token request, binding the resulting token to a n attacker-controlled key. | |||
For example, using cross-site scripting, attackers might obtain access to the au thorization code and PKCE parameters. | For example, using XSS, attackers might obtain access to the authorization code and PKCE parameters. | |||
Use of the <tt>dpop_jkt</tt> parameter prevents this attack.</t> | Use of the <tt>dpop_jkt</tt> parameter prevents this attack.</t> | |||
<t>The binding of the authorization code to the DPoP public key | <t>The binding of the authorization code to the DPoP public key | |||
uses a JWK Thumbprint of the public key, just as the access token binding does. | uses a JWK Thumbprint of the public key, just as the access token binding does. | |||
The same JWK Thumbprint considerations apply.</t> | The same JWK Thumbprint considerations apply.</t> | |||
</section> | </section> | |||
<section anchor="hash-algorithm-agility"><name>Hash Algorithm Agility</name> | <section anchor="hash-algorithm-agility"><name>Hash Algorithm Agility</name> | |||
<t>The <tt>jkt</tt> confirmation method member, the <tt>ath</tt> JWT claim, and the <tt>dpop_jkt</tt> authorization | <t>The <tt>jkt</tt> confirmation method member, the <tt>ath</tt> JWT claim, and the <tt>dpop_jkt</tt> authorization | |||
request parameter defined herein all use the output of the SHA-256 hash function as their value. | request parameter defined herein all use the output of the SHA-256 hash function as their value. | |||
The use of a single hash function by this specification was intentional and aime d at | The use of a single hash function by this specification was intentional and aime d at | |||
simplicity and avoidance of potential security and interoperability issues arisi ng from | simplicity and avoidance of potential security and interoperability issues arisi ng from | |||
common mistakes implementing and deploying parameterized algorithm agility schem es. | common mistakes implementing and deploying parameterized algorithm agility schem es. | |||
The use of a different hash function is not precluded, however, if future circum | However, the use of a different hash function is not precluded if future circums | |||
stances | tances | |||
change making SHA-256 insufficient for the requirements of this specification. | change and make SHA-256 insufficient for the requirements of this specification. | |||
Should that need arise, it is expected that a short specification be produced th | Should that need arise, it is expected that a short specification will be produc | |||
at | ed that | |||
updates this one. That specification will likely define, using the output of a t | updates this one. | |||
hen appropriate | Using the output of an appropriate | |||
hash function as the value, a new confirmation method member, a new JWT claim, | hash function as the value, that specification will likely define a new confirma | |||
tion method member, a new JWT claim, | ||||
and a new authorization request parameter. These items will be used in place of, or alongside, their | and a new authorization request parameter. These items will be used in place of, or alongside, their | |||
respective counterparts in the same message structures and flows of the larger p rotocol defined | respective counterparts in the same message structures and flows of the larger p rotocol defined | |||
by this specification.</t> | by this specification.</t> | |||
</section> | </section> | |||
<section anchor="binding-to-client-identity"><name>Binding to Client Identity</n ame> | <section anchor="binding-to-client-identity"><name>Binding to Client Identity</n ame> | |||
<t>In cases where DPoP is used with client authentication, it is only bound to a uthentication by being | <t>In cases where DPoP is used with client authentication, it is only bound to a uthentication by being | |||
coincident in the same TLS tunnel. Since the DPoP proof is not directly cryptog | coincident in the same TLS tunnel. Since the DPoP proof is not directly bound | |||
raphically bound | to the authentication cryptographically, it's possible that the authentication o | |||
to the authentication, it's possible that the authentication or the DPoP message | r the DPoP messages were copied into | |||
s were copied into | ||||
the tunnel. While including the URI in the DPoP can partially mitigate some of this risk, modifying | the tunnel. While including the URI in the DPoP can partially mitigate some of this risk, modifying | |||
the authentication mechanism to provide cryptographic binding between authentica tion and DPoP could | the authentication mechanism to provide cryptographic binding between authentica tion and DPoP could | |||
provide better protection. However, providing additional binding with authentic ation through the | provide better protection. However, providing additional binding with authentic ation through the | |||
modification of authentication mechanisms or other means is beyond the scope of this specification.</t> | modification of authentication mechanisms or other means is beyond the scope of this specification.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="IANA"><name>IANA Considerations</name> | <section anchor="IANA"><name>IANA Considerations</name> | |||
<section anchor="oauth-access-token-type-registration"><name>OAuth Access Token | ||||
<section anchor="oauth-access-token-type-registration"><name>OAuth Access Token | Types Registration</name> | |||
Type Registration</name> | <t>IANA has registered the following access token | |||
<t>This specification requests registration of the following access token | type in the "OAuth Access Token Types" registry <xref target="IANA.OAuth.Params" | |||
type in the "OAuth Access Token Types" registry <xref target="IANA.OAu | ></xref> | |||
th.Params"></xref> | ||||
established by <xref target="RFC6749"></xref>.</t> | established by <xref target="RFC6749"></xref>.</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Type name: <tt>DPoP</tt></li> | <dt>Name:</dt><dd><tt>DPoP</tt></dd> | |||
<li>Additional Token Endpoint Response Parameters: (none)</li> | <dt>Additional Token Endpoint Response Parameters:</dt><dd>(none)</dd> | |||
<li>HTTP Authentication Scheme(s): <tt>DPoP</tt></li> | <dt>HTTP Authentication Scheme(s):</dt><dd><tt>DPoP</tt></dd> | |||
<li>Change controller: IETF</li> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<li>Specification document(s): [[ this specification ]]</li> | <dt>Reference:</dt><dd>RFC 9449</dd> | |||
</ul> | </dl> | |||
</section> | </section> | |||
<section anchor="oauth-extensions-error-registration"><name>OAuth Extensions Err or Registration</name> | <section anchor="oauth-extensions-error-registration"><name>OAuth Extensions Err or Registration</name> | |||
<t>This specification requests registration of the following error values | <t>IANA has registered the following error values | |||
in the "OAuth Extensions Error" registry <xref target="IANA.OAuth.Para | in the "OAuth Extensions Error" registry <xref target="IANA.OAuth.Params"></xref | |||
ms"></xref> | > | |||
established by <xref target="RFC6749"></xref>.</t> | established by <xref target="RFC6749"></xref>.</t> | |||
<t>Invalid DPoP proof:</t> | <dl spacing="normal"> | |||
<dt>Invalid DPoP proof:</dt> | ||||
<ul spacing="compact"> | <dd><t><br/></t> | |||
<li>Name: <tt>invalid_dpop_proof</tt></li> | <dl spacing="normal"> | |||
<li>Usage Location: token error response, resource access error response</li> | <dt>Name:</dt><dd><tt>invalid_dpop_proof</tt></dd> | |||
<li>Protocol Extension: Demonstrating Proof of Possession (DPoP)</li> | <dt>Usage Location:</dt><dd>token error response, resource access error response | |||
<li>Change controller: IETF</li> | </dd> | |||
<li>Specification document(s): [[ this specification ]]</li> | <dt>Protocol Extension:</dt><dd>Demonstrating Proof of Possession (DPoP)</dd> | |||
</ul> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<t>Use DPoP nonce:</t> | <dt>Reference:</dt><dd>RFC 9449</dd> | |||
</dl> | ||||
</dd> | ||||
</dl> | ||||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Name: <tt>use_dpop_nonce</tt></li> | <dt>Use DPoP nonce:</dt> | |||
<li>Usage Location: token error response, resource access error response</li> | <dd> | |||
<li>Protocol Extension: Demonstrating Proof of Possession (DPoP)</li> | <t><br/></t> | |||
<li>Change controller: IETF</li> | <dl spacing="normal"> | |||
<li>Specification document(s): [[ this specification ]]</li> | <dt>Name:</dt><dd><tt>use_dpop_nonce</tt></dd> | |||
</ul> | <dt>Usage Location:</dt><dd>token error response, resource access error response | |||
</dd> | ||||
<dt>Protocol Extension:</dt><dd>Demonstrating Proof of Possession (DPoP)</dd> | ||||
<dt>Change Controller:</dt><dd>IETF</dd> | ||||
<dt>Reference:</dt><dd>RFC 9449</dd> | ||||
</dl></dd></dl> | ||||
</section> | </section> | |||
<section anchor="oauth-parameters-registration"><name>OAuth Parameters Registrat ion</name> | <section anchor="oauth-parameters-registration"><name>OAuth Parameters Registrat ion</name> | |||
<t>This specification requests registration of the following | <t>IANA has registered the following authorization request parameter | |||
authorization request parameter | in the "OAuth Parameters" registry <xref target="IANA.OAuth.Params"></xref> | |||
in the "OAuth Parameters" registry <xref target="IANA.OAuth.Params"></ | ||||
xref> | ||||
established by <xref target="RFC6749"></xref>.</t> | established by <xref target="RFC6749"></xref>.</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Name: <tt>dpop_jkt</tt></li> | <dt>Name:</dt><dd><tt>dpop_jkt</tt></dd> | |||
<li>Parameter Usage Location: authorization request</li> | <dt>Parameter Usage Location:</dt><dd>authorization request</dd> | |||
<li>Change Controller: IETF</li> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<li>Reference: [[ <xref target="dpop_jkt"></xref> of this specification ]]</li> | <dt>Reference:</dt><dd><xref target="dpop_jkt"></xref> of RFC 9449</dd> | |||
</ul> | </dl> | |||
</section> | </section> | |||
<section anchor="http-authentication-scheme-registration"><name>HTTP Authenticat | <section anchor="http-authentication-scheme-registration"><name>HTTP Authenticat | |||
ion Scheme Registration</name> | ion Schemes Registration</name> | |||
<t>This specification requests registration of the following scheme in the | <t>IANA has registered the following scheme in the | |||
"Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry" <x | "HTTP Authentication Schemes" registry <xref target="IANA.HTTP.AuthSchemes"></xr | |||
ref target="RFC9110"></xref><xref target="IANA.HTTP.AuthSchemes"></xref>:</t> | ef> established by <xref target="RFC9110" sectionFormat="comma" section="16.4.1" | |||
></xref>.</t> | ||||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Authentication Scheme Name: <tt>DPoP</tt></li> | <dt>Authentication Scheme Name:</dt><dd><tt>DPoP</tt></dd> | |||
<li>Reference: [[ <xref target="http-auth-scheme"></xref> of this specification | <dt>Reference:</dt><dd><xref target="http-auth-scheme"></xref> of RFC 9449</dd> | |||
]]</li> | </dl> | |||
</ul> | ||||
</section> | </section> | |||
<section anchor="media-type-registration"><name>Media Type Registration</name> | <section anchor="media-type-registration"><name>Media Type Registration</name> | |||
<t>This section registers the <tt>application/dpop+jwt</tt> media type <xref tar | <t>IANA has registered the <tt>application/dpop+jwt</tt> media type <xref target | |||
get="RFC2046"></xref> | ="RFC2046"></xref> | |||
in the IANA "Media Types" registry <xref target="IANA.MediaTypes"></xr | in the "Media Types" registry <xref target="IANA.MediaTypes"></xref> in the mann | |||
ef> in the manner described in <xref target="RFC6838"></xref>, | er described in <xref target="RFC6838"></xref>, | |||
which is used to indicate that the content is a DPoP JWT.</t> | which is used to indicate that the content is a DPoP JWT.</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Type name: application</li> | <dt>Type name:</dt><dd>application</dd> | |||
<li>Subtype name: dpop+jwt</li> | <dt>Subtype name:</dt><dd>dpop+jwt</dd> | |||
<li>Required parameters: n/a</li> | <dt>Required parameters:</dt><dd>n/a</dd> | |||
<li>Optional parameters: n/a</li> | <dt>Optional parameters:</dt><dd> n/a</dd> | |||
<li>Encoding considerations: binary; A DPoP JWT is a JWT; JWT values are encoded | <dt>Encoding considerations:</dt><dd>binary. A DPoP JWT is a JWT; JWT values are | |||
as a series of base64url-encoded values (some of which may be the empty string) | encoded as a series of base64url-encoded values (some of which may be the empty | |||
separated by period ('.') characters.</li> | string) separated by period ('.') characters.</dd> | |||
<li>Security considerations: See <xref target="Security"></xref> of [[ this spec | <dt>Security considerations:</dt><dd>See <xref target="Security"></xref> of RFC | |||
ification ]]</li> | 9449</dd> | |||
<li>Interoperability considerations: n/a</li> | <dt>Interoperability considerations:</dt><dd>n/a</dd> | |||
<li>Published specification: [[ this specification ]]</li> | <dt>Published specification:</dt><dd>RFC 9449</dd> | |||
<li>Applications that use this media type: Applications using [[ this specificat | <dt>Applications that use this media type:</dt><dd>Applications using RFC 9449 f | |||
ion ]] for application-level proof of possession</li> | or application-level proof of possession</dd> | |||
<li>Fragment identifier considerations: n/a</li> | <dt>Fragment identifier considerations:</dt><dd>n/a</dd> | |||
<li><t>Additional information:</t> | <dt>Additional information:</dt> | |||
<dd> | ||||
<ul spacing="compact"> | <t><br/></t> | |||
<li>File extension(s): n/a</li> | <dl spacing="compact"> | |||
<li>Macintosh file type code(s): n/a</li> | <dt>File extension(s):</dt><dd>n/a</dd> | |||
</ul></li> | <dt>Macintosh file type code(s):</dt><dd>n/a</dd> | |||
<li>Person & email address to contact for further information: Michael B. Jo | </dl></dd> | |||
nes, mbj@microsoft.com</li> | <dt>Person & email address to contact for further information:</dt><dd>Micha | |||
<li>Intended usage: COMMON</li> | el B. Jones, michael_b_jones@hotmail.com</dd> | |||
<li>Restrictions on usage: none</li> | <dt>Intended usage:</dt><dd>COMMON</dd> | |||
<li>Author: Michael B. Jones, mbj@microsoft.com</li> | <dt>Restrictions on usage:</dt><dd>none</dd> | |||
<li>Change controller: IETF</li> | <dt>Author:</dt><dd>Michael B. Jones, michael_b_jones@hotmail.com</dd> | |||
<li>Provisional registration? No</li> | <dt>Change controller:</dt><dd>IETF</dd> | |||
</ul> | </dl> | |||
</section> | </section> | |||
<section anchor="jwt-confirmation-methods-registration"><name>JWT Confirmation M ethods Registration</name> | <section anchor="jwt-confirmation-methods-registration"><name>JWT Confirmation M ethods Registration</name> | |||
<t>This specification requests registration of the following value | <t>IANA has registered the following JWT <tt>cnf</tt> member value | |||
in the IANA "JWT Confirmation Methods" registry <xref target="IANA.JWT | in the "JWT Confirmation Methods" registry <xref target="IANA.JWT"></xref> | |||
"></xref> | established by <xref target="RFC7800"></xref>.</t> | |||
for JWT <tt>cnf</tt> member values established by <xref target="RFC7800"></xref> | ||||
.</t> | ||||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Confirmation Method Value: <tt>jkt</tt></li> | <dt>Confirmation Method Value:</dt><dd><tt>jkt</tt></dd> | |||
<li>Confirmation Method Description: JWK SHA-256 Thumbprint</li> | <dt>Confirmation Method Description:</dt><dd>JWK SHA-256 Thumbprint</dd> | |||
<li>Change Controller: IETF</li> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<li>Specification Document(s): [[ <xref target="Confirmation"></xref> of this s | <dt>Reference:</dt><dd><xref target="Confirmation"></xref> of RFC 9449</dd> | |||
pecification ]]</li> | </dl> | |||
</ul> | ||||
</section> | </section> | |||
<section anchor="json-web-token-claims-registration"><name>JSON Web Token Claims Registration</name> | <section anchor="json-web-token-claims-registration"><name>JSON Web Token Claims Registration</name> | |||
<t>This specification requests registration of the following Claims in the | <t>IANA has registered the following Claims in the "JSON Web Token Claims" regis | |||
IANA "JSON Web Token Claims" registry <xref target="IANA.JWT"></xref> | try <xref target="IANA.JWT"></xref> established by <xref target="RFC7519"></xref | |||
established by <xref target="RFC7519"></xref>.</t> | >.</t> | |||
<t>HTTP method:</t> | <dl spacing="normal"> | |||
<dt>HTTP method:</dt> | ||||
<ul spacing="compact"> | <dd> | |||
<li>Claim Name: <tt>htm</tt></li> | <t><br/></t> | |||
<li>Claim Description: The HTTP method of the request</li> | <dl spacing="normal"> | |||
<li>Change Controller: IETF</li> | <dt>Claim Name:</dt><dd><tt>htm</tt></dd> | |||
<li>Specification Document(s): [[ <xref target="DPoP-Proof-Syntax"></xref> of t | <dt>Claim Description:</dt><dd>The HTTP method of the request</dd> | |||
his specification ]]</li> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
</ul> | <dt>Reference:</dt><dd><xref target="DPoP-Proof-Syntax"></xref> of RFC 9449</dd> | |||
<t>HTTP URI:</t> | </dl> | |||
</dd></dl> | ||||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Claim Name: <tt>htu</tt></li> | <dt>HTTP URI:</dt> | |||
<li>Claim Description: The HTTP URI of the request (without query and fragment p | <dd> | |||
arts)</li> | <t><br/></t> | |||
<li>Change Controller: IETF</li> | <dl spacing="normal"> | |||
<li>Specification Document(s): [[ <xref target="DPoP-Proof-Syntax"></xref> of t | <dt>Claim Name:</dt><dd><tt>htu</tt></dd> | |||
his specification ]]</li> | <dt>Claim Description:</dt><dd>The HTTP URI of the request (without query and fr | |||
</ul> | agment parts)</dd> | |||
<t>Access token hash:</t> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<dt>Reference:</dt><dd><xref target="DPoP-Proof-Syntax"></xref> of RFC 9449</dd> | ||||
<ul spacing="compact"> | </dl></dd></dl> | |||
<li>Claim Name: <tt>ath</tt></li> | <dl spacing="normal"> | |||
<li>Claim Description: The base64url encoded SHA-256 hash of the ASCII encoding | <dt>Access token hash:</dt> | |||
of the associated access token's value</li> | <dd> | |||
<li>Change Controller: IETF</li> | <t><br/></t> | |||
<li>Specification Document(s): [[ <xref target="DPoP-Proof-Syntax"></xref> of t | <dl spacing="normal"> | |||
his specification ]]</li> | <dt>Claim Name:</dt><dd><tt>ath</tt></dd> | |||
</ul> | <dt>Claim Description:</dt><dd>The base64url-encoded SHA-256 hash of the ASCII e | |||
ncoding of the associated access token's value</dd> | ||||
<section anchor="nonce-registry-update"><name>"nonce" Registry Update< | <dt>Change Controller:</dt><dd>IETF</dd> | |||
/name> | <dt>Reference:</dt><dd><xref target="DPoP-Proof-Syntax"></xref> of RFC 9449</dd> | |||
</dl> | ||||
</dd> | ||||
</dl> | ||||
<section anchor="nonce-registry-update"><name>"nonce" Registration Update</name> | ||||
<t>The Internet Security Glossary <xref target="RFC4949"></xref> provides a usef ul definition of nonce | <t>The Internet Security Glossary <xref target="RFC4949"></xref> provides a usef ul definition of nonce | |||
as a random or non-repeating value that is included in data | as a random or non-repeating value that is included in data | |||
exchanged by a protocol, usually for the purpose of guaranteeing | exchanged by a protocol, usually for the purpose of guaranteeing | |||
liveness and thus detecting and protecting against replay attacks.</t> | liveness and thus detecting and protecting against replay attacks.</t> | |||
<t>However, the initial registration of the <tt>nonce</tt> claim by <xref target ="OpenID.Core"></xref> | <t>However, the initial registration of the <tt>nonce</tt> claim by <xref target ="OpenID.Core"></xref> | |||
used language that was contextually specific to that application, | used language that was contextually specific to that application, | |||
which was potentially limiting to its general applicability.</t> | which was potentially limiting to its general applicability.</t> | |||
<t>This specification therefore requests that the entry for <tt>nonce</tt> in th | <t>Therefore, IANA has updated the entry for <tt>nonce</tt> in the | |||
e | "JSON Web Token Claims" registry <xref target="IANA.JWT"></xref> with an expande | |||
IANA "JSON Web Token Claims" registry <xref target="IANA.JWT"></xref> | d definition to reflect | |||
be updated as follows to | that the claim can be used appropriately in other contexts and with the addition | |||
reflect that the claim can be used appropriately in other contexts.</t> | of this document as a reference, as follows.</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Claim Name: <tt>nonce</tt></li> | <dt>Claim Name:</dt><dd><tt>nonce</tt></dd> | |||
<li>Claim Description: Value used to associate a Client session with an ID Token | <dt>Claim Description:</dt><dd>Value used to associate a Client session with an | |||
(MAY also be used for nonce values in other applications of JWTs)</li> | ID Token (<bcp14>MAY</bcp14> also be used for nonce values in other applications | |||
<li>Change Controller: OpenID Foundation Artifact Binding Working Group - openid | of JWTs)</dd> | |||
-specs-ab@lists.openid.net</li> | <dt>Change Controller:</dt><dd>OpenID Foundation Artifact Binding Working Group, | |||
<li>Specification Document(s): <xref target="OpenID.Core" sectionFormat="of" re | openid-specs-ab@lists.openid.net</dd> | |||
lative="#" section="2"></xref> and [[ this specification ]]</li> | <dt>Specification Document(s):</dt><dd><xref target="OpenID.Core" sectionFormat= | |||
</ul> | "of" relative="openid-connect-core-1_0.html#IDToken" section="2"></xref> and RFC | |||
9449</dd> | ||||
</dl> | ||||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="http-message-header-field-names-registration"><name>HTTP Messag | <section anchor="http-message-header-field-names-registration"><name>Hypertext T | |||
e Header Field Names Registration</name> | ransfer Protocol (HTTP) Field Name Registration</name> | |||
<t>This document specifies the following HTTP header fields, | <t>IANA has registered the following HTTP header fields, as specified by this do | |||
registration of which is requested in the "Hypertext Transfer Protocol (HTT | cument, in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" | |||
P) Field Name Registry" | <xref target="IANA.HTTP.Fields"></xref> established by <xref target="RFC9110">< | |||
registry <xref target="RFC9110"></xref><xref target="IANA.HTTP.Fields"></xref>:< | /xref>:</t> | |||
/t> | ||||
<ul> | <dl spacing="normal"> | |||
<li>Field name: <tt>DPoP</tt></li> | <dt>DPoP:</dt> | |||
<li>Status: permanent</li> | <dd> | |||
<li><t>Specification document: [[ this specification ]] | <t><br/></t> | |||
<br /> | <dl spacing="normal"> | |||
</t> | <dt>Field Name:</dt><dd><tt>DPoP</tt></dd> | |||
</li> | <dt>Status:</dt><dd>permanent</dd> | |||
<li><t>Field name: <tt>DPoP-Nonce</tt></t> | <dt>Reference:</dt><dd>RFC 9449</dd> | |||
</li> | </dl> | |||
<li><t>Status: permanent</t> | </dd> | |||
</li> | </dl> | |||
<li><t>Specification document: [[ this specification ]]</t> | <dl spacing="normal"> | |||
</li> | <dt>DPoP-Nonce:</dt> | |||
</ul> | <dd> | |||
<t><br/></t> | ||||
<dl spacing="normal"> | ||||
<dt>Field Name:</dt><dd><tt>DPoP-Nonce</tt></dd> | ||||
<dt>Status:</dt><dd>permanent</dd> | ||||
<dt>Reference:</dt><dd>RFC 9449</dd> | ||||
</dl> | ||||
</dd> | ||||
</dl> | ||||
</section> | </section> | |||
<section anchor="oauth-authorization-server-metadata-registration"><name>OAuth A uthorization Server Metadata Registration</name> | <section anchor="oauth-authorization-server-metadata-registration"><name>OAuth A uthorization Server Metadata Registration</name> | |||
<t>This specification requests registration of the following value | <t>IANA has registered the following value | |||
in the IANA "OAuth Authorization Server Metadata" registry <xref targe | in the "OAuth Authorization Server Metadata" registry <xref target="IANA.OAuth.P | |||
t="IANA.OAuth.Params"></xref> | arams"></xref> | |||
established by <xref target="RFC8414"></xref>.</t> | established by <xref target="RFC8414"></xref>.</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Metadata Name: <tt>dpop_signing_alg_values_supported</tt></li> | <dt>Metadata Name:</dt><dd><tt>dpop_signing_alg_values_supported</tt></dd> | |||
<li>Metadata Description: JSON array containing a list of the JWS algorithms su | <dt>Metadata Description:</dt><dd>JSON array containing a list of the JWS algori | |||
pported for DPoP proof JWTs</li> | thms supported for DPoP proof JWTs</dd> | |||
<li>Change Controller: IETF</li> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<li>Specification Document(s): [[ <xref target="as-meta"></xref> of this specif | <dt>Reference:</dt><dd><xref target="as-meta"></xref> of RFC 9449</dd> | |||
ication ]]</li> | </dl> | |||
</ul> | ||||
</section> | </section> | |||
<section anchor="oauth-dynamic-client-registration-metadata"><name>OAuth Dynamic Client Registration Metadata</name> | <section anchor="oauth-dynamic-client-registration-metadata"><name>OAuth Dynamic Client Registration Metadata</name> | |||
<t>This specification requests registration of the following value | <t>IANA has registered the following value | |||
in the IANA "OAuth Dynamic Client Registration Metadata" registry <xre | in the IANA "OAuth Dynamic Client Registration Metadata" registry <xref target=" | |||
f target="IANA.OAuth.Params"></xref> | IANA.OAuth.Params"></xref> | |||
established by <xref target="RFC7591"></xref>.</t> | established by <xref target="RFC7591"></xref>.</t> | |||
<ul spacing="compact"> | <dl spacing="normal"> | |||
<li>Metadata Name: <tt>dpop_bound_access_tokens</tt></li> | <dt>Client Metadata Name:</dt><dd><tt>dpop_bound_access_tokens</tt></dd> | |||
<li>Metadata Description: Boolean value specifying whether the client always us | <dt>Client Metadata Description:</dt><dd>Boolean value specifying whether the cl | |||
es DPoP for token requests</li> | ient always uses DPoP for token requests</dd> | |||
<li>Change Controller: IETF</li> | <dt>Change Controller:</dt><dd>IETF</dd> | |||
<li>Specification Document(s): [[ <xref target="client-meta"></xref> of this sp | <dt>Reference:</dt><dd><xref target="client-meta"></xref> of RFC 9449</dd> | |||
ecification ]]</li> | </dl> | |||
</ul> | ||||
</section> | </section> | |||
</section> | </section> | |||
</middle> | </middle> | |||
<back> | <back> | |||
<references><name>Normative References</name> | ||||
<displayreference target="I-D.ietf-oauth-security-topics" to="SECURITY-TOPICS"/> | ||||
<displayreference target="I-D.ietf-oauth-token-binding" to="TOKEN-BINDING"/> | ||||
<references> | ||||
<name>References</name> | ||||
<references> | ||||
<name>Normative References</name> | ||||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.3986. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.3986. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5234. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5234. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6125. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6125. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6749. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6749. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6750. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6750. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7515. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7515. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7517. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7517. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7519. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7519. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7638. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7638. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7800. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7800. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174. xml"/> | |||
<reference anchor="SHS" target="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS | ||||
.180-4.pdf"> | <reference anchor="SHS" target="http://dx.doi.org/10.6028/NIST.FIPS.180-4"> | |||
<front> | <front> | |||
<title>Secure Hash Standard (SHS)</title> | <title>Secure Hash Standard (SHS)</title> | |||
<author> | <author> | |||
<organization>National Institute of Standards and Technology</organization > | <organization>National Institute of Standards and Technology</organization > | |||
</author> | </author> | |||
<date year="2015" month="August"></date> | <date year="2015" month="August"></date> | |||
</front> | </front> | |||
<format type="PDF" target="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.18 0-4.pdf"></format> | ||||
<seriesInfo name="FIPS" value="PUB 180-4"></seriesInfo> | <seriesInfo name="FIPS" value="PUB 180-4"></seriesInfo> | |||
<seriesInfo name="DOI" value="10.6028/NIST.FIPS.180-4"/> | ||||
</reference> | </reference> | |||
</references> | </references> | |||
<references><name>Informative References</name> | <references><name>Informative References</name> | |||
<reference anchor="BREACH" target="https://cve.mitre.org/cgi-bin/cvename.cgi?nam e=CVE-2013-3587"> | <reference anchor="BREACH" target="https://cve.mitre.org/cgi-bin/cvename.cgi?nam e=CVE-2013-3587"> | |||
<front> | <front> | |||
<title>CVE-2013-3587</title> | <title>CVE-2013-3587</title> | |||
<author></author> | <author><organization>CVE</organization></author> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="CRIME" target="https://cve.mitre.org/cgi-bin/cvename.cgi?name =cve-2012-4929"> | <reference anchor="CRIME" target="https://cve.mitre.org/cgi-bin/cvename.cgi?name =cve-2012-4929"> | |||
<front> | <front> | |||
<title>CVE-2012-4929</title> | <title>CVE-2012-4929</title> | |||
<author></author> | <author><organization>CVE</organization></author> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="Cloudbleed" target="https://blog.cloudflare.com/incident-repo rt-on-memory-leak-caused-by-cloudflare-parser-bug/"> | <reference anchor="Cloudbleed" target="https://blog.cloudflare.com/incident-repo rt-on-memory-leak-caused-by-cloudflare-parser-bug/"> | |||
<front> | <front> | |||
<title>Incident report on memory leak caused by Cloudflare parser bug</title > | <title>Incident report on memory leak caused by Cloudflare parser bug</title > | |||
<author></author> | <author initials="J." surname="Graham-Cumming" fullname="John Graham-Cumming | |||
"/> | ||||
<date month="February" year="2017"/> | ||||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="GitHub.Tokens" target="https://github.blog/2022-04-15-securit y-alert-stolen-oauth-user-tokens/"> | <reference anchor="GitHub.Tokens" target="https://github.blog/2022-04-15-securit y-alert-stolen-oauth-user-tokens/"> | |||
<front> | <front> | |||
<title>Security alert: Attack campaign involving stolen OAuth user tokens is sued to two third-party integrators</title> | <title>Security alert: Attack campaign involving stolen OAuth user tokens is sued to two third-party integrators</title> | |||
<author></author> | <author initials="M." surname="Hanley" fullname="Mike Hanley"/> | |||
<date month="April" year="2022"/> | ||||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="Heartbleed" target="https://cve.mitre.org/cgi-bin/cvename.cgi ?name=cve-2014-0160"> | <reference anchor="Heartbleed" target="https://cve.mitre.org/cgi-bin/cvename.cgi ?name=cve-2014-0160"> | |||
<front> | <front> | |||
<title>CVE-2014-0160</title> | <title>CVE-2014-0160</title> | |||
<author></author> | <author></author> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<!-- [I-D.ietf-oauth-security-topics] IESG state I-D Exists as of 8/9/23 --> | ||||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.i etf-oauth-security-topics.xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.i etf-oauth-security-topics.xml"/> | |||
<!-- [I-D.ietf-oauth-token-binding] IESG state Expired as of 8/9/23 --> | ||||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.i etf-oauth-token-binding.xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.i etf-oauth-token-binding.xml"/> | |||
<reference anchor="IANA.HTTP.AuthSchemes" target="https://www.iana.org/assignmen | ||||
ts/http-authschemes"> | <reference anchor="IANA.HTTP.AuthSchemes" target="https://www.iana.org/assignmen | |||
ts/http-authschemes/"> | ||||
<front> | <front> | |||
<title>Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry</ti tle> | <title>Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry</ti tle> | |||
<author> | <author> | |||
<organization>IANA</organization> | <organization>IANA</organization> | |||
</author> | </author> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="IANA.HTTP.Fields" target="https://www.iana.org/assignments/ht | ||||
tp-fields/http-fields.xhtml"> | <reference anchor="IANA.HTTP.Fields" target="https://www.iana.org/assignments/ht | |||
tp-fields/"> | ||||
<front> | <front> | |||
<title>Hypertext Transfer Protocol (HTTP) Field Name Registry</title> | <title>Hypertext Transfer Protocol (HTTP) Field Name Registry</title> | |||
<author> | <author> | |||
<organization>IANA</organization> | <organization>IANA</organization> | |||
</author> | </author> | |||
<date></date> | ||||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="IANA.JOSE.ALGS" target="https://www.iana.org/assignments/jose | ||||
/jose.xhtml#web-signature-encryption-algorithms"> | <reference anchor="IANA.JOSE.ALGS" target="https://www.iana.org/assignments/jose | |||
/"> | ||||
<front> | <front> | |||
<title>JSON Web Signature and Encryption Algorithms</title> | <title>JSON Web Signature and Encryption Algorithms</title> | |||
<author> | <author> | |||
<organization>IANA</organization> | <organization>IANA</organization> | |||
</author> | </author> | |||
<date></date> | ||||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="IANA.JWT" target="https://www.iana.org/assignments/jwt"> | ||||
<reference anchor="IANA.JWT" target="https://www.iana.org/assignments/jwt/"> | ||||
<front> | <front> | |||
<title>JSON Web Token Claims</title> | <title>JSON Web Token Claims</title> | |||
<author> | <author> | |||
<organization>IANA</organization> | <organization>IANA</organization> | |||
</author> | </author> | |||
<date></date> | ||||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="IANA.MediaTypes" target="https://www.iana.org/assignments/med | ||||
ia-types"> | <reference anchor="IANA.MediaTypes" target="https://www.iana.org/assignments/med | |||
ia-types/"> | ||||
<front> | <front> | |||
<title>Media Types</title> | <title>Media Types</title> | |||
<author> | <author> | |||
<organization>IANA</organization> | <organization>IANA</organization> | |||
</author> | </author> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="IANA.OAuth.Params" target="https://www.iana.org/assignments/o | ||||
auth-parameters"> | <reference anchor="IANA.OAuth.Params" target="https://www.iana.org/assignments/o | |||
auth-parameters/"> | ||||
<front> | <front> | |||
<title>OAuth Parameters</title> | <title>OAuth Parameters</title> | |||
<author> | <author> | |||
<organization>IANA</organization> | <organization>IANA</organization> | |||
</author> | </author> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="OpenID.Core" target="https://openid.net/specs/openid-connect- core-1_0.html"> | <reference anchor="OpenID.Core" target="https://openid.net/specs/openid-connect- core-1_0.html"> | |||
<front> | <front> | |||
<title>OpenID Connect Core 1.0</title> | <title>OpenID Connect Core 1.0 incorporating errata set 1</title> | |||
<author fullname="Nat Sakimura" initials="N." surname="Sakimura"> | <author fullname="Nat Sakimura" initials="N." surname="Sakimura"> | |||
<organization></organization> | ||||
</author> | </author> | |||
<author fullname="John Bradley" initials="J." surname="Bradley"> | <author fullname="John Bradley" initials="J." surname="Bradley"> | |||
<organization></organization> | ||||
</author> | </author> | |||
<author fullname="Michael B. Jones" initials="M.B." surname="Jones"> | <author fullname="Michael B. Jones" initials="M." surname="Jones"> | |||
<organization></organization> | ||||
</author> | </author> | |||
<author fullname="Breno de Medeiros" initials="B.d." surname="Medeiros"> | <author fullname="Breno de Medeiros" initials="B." surname="de Medeiros"> | |||
<organization></organization> | ||||
</author> | </author> | |||
<author fullname="Chuck Mortimore" initials="C." surname="Mortimore"> | <author fullname="Chuck Mortimore" initials="C." surname="Mortimore"> | |||
<organization></organization> | ||||
</author> | </author> | |||
<date year="2014" month="November"></date> | <date year="2014" month="November"></date> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2046. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2046. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.4122. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.4122. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.4949. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.4949. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6838. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6838. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7523. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7523. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7591. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7591. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7636. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7636. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7662. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7662. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8414. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8414. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8705. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8705. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8707. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8707. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8725. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8725. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8792. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8792. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9110. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9110. xml"/> | |||
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9126. xml"/> | <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9126. xml"/> | |||
<reference anchor="W3C.CSP" target="https://www.w3.org/TR/2018/WD-CSP3-20181015/ | ||||
"> | <reference anchor="W3C.CSP" target="https://www.w3.org/TR/CSP3/"> | |||
<front> | <front> | |||
<title>Content Security Policy Level 3</title> | <title>Content Security Policy Level 3</title> | |||
<author fullname="Mike West" initials="M." surname="West"> | <author fullname="Mike West" initials="M." surname="West"> | |||
<organization></organization> | <organization></organization> | |||
</author> | </author> | |||
<date year="2018" month="October" day="15"></date> | <date year="2023" month="July"></date> | |||
</front> | </front> | |||
<format type="HTML" target="https://www.w3.org/TR/2018/WD-CSP3-20181015/"></fo | <refcontent>W3C Working Draft</refcontent> | |||
rmat> | ||||
<seriesInfo name="World Wide Web Consortium Working Draft" value="WD-CSP3-2018 | ||||
1015"></seriesInfo> | ||||
</reference> | </reference> | |||
<reference anchor="W3C.WebCryptoAPI" target="https://www.w3.org/TR/2017/REC-WebC ryptoAPI-20170126"> | <reference anchor="W3C.WebCryptoAPI" target="https://www.w3.org/TR/2017/REC-WebC ryptoAPI-20170126"> | |||
<front> | <front> | |||
<title>Web Cryptography API</title> | <title>Web Cryptography API</title> | |||
<author fullname="Mark Watson" initials="M." surname="Watson"> | <author fullname="Mark Watson" initials="M." surname="Watson"> | |||
<organization></organization> | <organization></organization> | |||
</author> | </author> | |||
<date year="2017" month="January" day="26"></date> | <date year="2017" month="January"></date> | |||
</front> | </front> | |||
<format type="HTML" target="https://www.w3.org/TR/2017/REC-WebCryptoAPI-201701 | <refcontent>W3C Recommendation</refcontent> | |||
26"></format> | ||||
<seriesInfo name="World Wide Web Consortium Recommendation" value="REC-WebCryp | ||||
toAPI-20170126"></seriesInfo> | ||||
</reference> | </reference> | |||
<reference anchor="WHATWG.Fetch" target="https://fetch.spec.whatwg.org/"> | <reference anchor="WHATWG.Fetch" target="https://fetch.spec.whatwg.org/"> | |||
<front> | <front> | |||
<title>Fetch Living Standard</title> | <title>Fetch Living Standard</title> | |||
<author fullname="WHATWG" surname="WHATWG"> | <author> | |||
<organization>WHATWG</organization> | <organization>WHATWG</organization> | |||
</author> | </author> | |||
<date year="2022" month="May"></date> | <date year="2023" month="July"></date> | |||
</front> | </front> | |||
</reference> | </reference> | |||
</references> | </references> | |||
</references> | ||||
<section anchor="Acknowledgements"><name>Acknowledgements</name> | <section anchor="Acknowledgements" numbered="false"><name>Acknowledgements</name | |||
> | ||||
<t>We would like to thank | <t>We would like to thank | |||
Brock Allen, | <contact fullname="Brock Allen"/>, | |||
Annabelle Backman, | <contact fullname="Annabelle Backman"/>, | |||
Spencer Balogh, | <contact fullname="Dominick Baier"/>, | |||
Dominick Baier, | <contact fullname="Spencer Balogh"/>, | |||
Vittorio Bertocci, | <contact fullname="Vittorio Bertocci"/>, | |||
Jeff Corrigan, | <contact fullname="Jeff Corrigan"/>, | |||
Domingos Creado, | <contact fullname="Domingos Creado"/>, | |||
Andrii Deinega, | <contact fullname="Philippe De Ryck"/>, | |||
William Denniss, | <contact fullname="Andrii Deinega"/>, | |||
Vladimir Dzhuvinov, | <contact fullname="William Denniss"/>, | |||
Mike Engan, | <contact fullname="Vladimir Dzhuvinov"/>, | |||
Nikos Fotiou, | <contact fullname="Mike Engan"/>, | |||
Mark Haine, | <contact fullname="Nikos Fotiou"/>, | |||
Dick Hardt, | <contact fullname="Mark Haine"/>, | |||
Joseph Heenan, | <contact fullname="Dick Hardt"/>, | |||
Bjorn Hjelm, | <contact fullname="Joseph Heenan"/>, | |||
Jacob Ideskog, | <contact fullname="Bjorn Hjelm"/>, | |||
Jared Jennings, | <contact fullname="Jacob Ideskog"/>, | |||
Benjamin Kaduk, | <contact fullname="Jared Jennings"/>, | |||
Pieter Kasselman, | <contact fullname="Benjamin Kaduk"/>, | |||
Neil Madden, | <contact fullname="Pieter Kasselman"/>, | |||
Rohan Mahy, | <contact fullname="Neil Madden"/>, | |||
Karsten Meyer zu Selhausen, | <contact fullname="Rohan Mahy"/>, | |||
Nicolas Mora, | <contact fullname="Karsten Meyer zu Selhausen"/>, | |||
Steinar Noem, | <contact fullname="Nicolas Mora"/>, | |||
Mark Nottingham, | <contact fullname="Steinar Noem"/>, | |||
Rob Otto, | <contact fullname="Mark Nottingham"/>, | |||
Aaron Parecki, | <contact fullname="Rob Otto"/>, | |||
Michael Peck, | <contact fullname="Aaron Parecki"/>, | |||
Roberto Polli, | <contact fullname="Michael Peck"/>, | |||
Paul Querna, | <contact fullname="Roberto Polli"/>, | |||
Justin Richer, | <contact fullname="Paul Querna"/>, | |||
Joseph Salowey, | <contact fullname="Justin Richer"/>, | |||
Rifaat Shekh-Yusef, | <contact fullname="Joseph Salowey"/>, | |||
Filip Skokan, | <contact fullname="Rifaat Shekh-Yusef"/>, | |||
Dmitry Telegin, | <contact fullname="Filip Skokan"/>, | |||
Dave Tonge, | <contact fullname="Dmitry Telegin"/>, | |||
Jim Willeke, | <contact fullname="Dave Tonge"/>, | |||
Philippe De Ryck, | <contact fullname="Jim Willeke"/>, | |||
and others (please let us know, if you've been mistakenly omitted) | and others for their valuable input, feedback, and general support of this work. | |||
for their valuable input, feedback and general support of this work.</t> | </t> | |||
<t>This document originated from discussions at the 4th OAuth Security | <t>This document originated from discussions at the 4th OAuth Security | |||
Workshop in Stuttgart, Germany. We thank the organizers of this | Workshop in Stuttgart, Germany. We thank the organizers of this | |||
workshop (Ralf Kusters, Guido Schmitz).</t> | workshop (<contact fullname="Ralf Küsters"/> and <contact fullname="Guido Schmit | |||
</section> | z"/>).</t> | |||
<section anchor="document-history"><name>Document History</name> | ||||
<t>[[ To be removed from the final specification ]]</t> | ||||
<t>-16</t> | ||||
<ul spacing="compact"> | ||||
<li>Per suggestion of the registry's designated expert, change "resource er | ||||
ror response" to "resource access error response" for location of | ||||
the two items in the "OAuth Extensions Error Registration" section</l | ||||
i> | ||||
</ul> | ||||
<t>-15</t> | ||||
<ul spacing="compact"> | ||||
<li>Editorial updates from IESG review/ballot</li> | ||||
<li>Mike Jones and Daniel Fett with new email/organization info</li> | ||||
</ul> | ||||
<t>-14</t> | ||||
<ul spacing="compact"> | ||||
<li>Add sec considerations sub-section about binding to client identity</li> | ||||
<li>Explicitly say that nonces must be unpredictable</li> | ||||
<li>Change to a numbered list in 'Checking DPoP Proofs'</li> | ||||
<li>Editorial adjustments</li> | ||||
<li>Incorporated HTTP header field definition and RFC 8792 '\' line wrapping sug | ||||
gestions by Mark Nottingham</li> | ||||
</ul> | ||||
<t>-13</t> | ||||
<ul spacing="compact"> | ||||
<li>Editorial updates/fixes</li> | ||||
<li>Make sure RFC7519 is a normative reference</li> | ||||
</ul> | ||||
<t>-12</t> | ||||
<ul spacing="compact"> | ||||
<li>Updates from Roman Danyliw's AD review</li> | ||||
<li>DPoP-Nonce now included in HTTP header field registration request</li> | ||||
<li>Fixed section reference to URI Scheme-Based Normalization</li> | ||||
<li>Attempt to better describe the rationale for SHA-256 only and expectations f | ||||
or how hash algorithm agility would be achieved if needed in the future</li> | ||||
<li>Elaborate on the use of multiple WWW-Authenticate challenges by protected re | ||||
sources</li> | ||||
<li>Fix access token request examples that were missing a client_id</li> | ||||
</ul> | ||||
<t>-11</t> | ||||
<ul spacing="compact"> | ||||
<li>Updates addressing outstanding shepherd review comments per side meeting dis | ||||
cussions at IETF 114</li> | ||||
<li>Added more explanation of the PAR considerations</li> | ||||
<li>Added parenthetical remark "(such as ES256)" to Signature Algorith | ||||
ms subsection</li> | ||||
<li>Added more explanation for ath</li> | ||||
<li>Added a reference to RFC8725 in mention of explicit JWT typing</li> | ||||
</ul> | ||||
<t>-10</t> | ||||
<ul spacing="compact"> | ||||
<li>Updates addressing some shepherd review comments</li> | ||||
<li>Update HTTP references as RFCs 723x have been superseded by RFC 9110</li> | ||||
<li>Editorial fixes</li> | ||||
<li>Added some clarifications, etc. around nonce</li> | ||||
<li>Added client considerations subsection</li> | ||||
<li>Use bullets rather than numbers in Checking DPoP Proofs so as not to imply s | ||||
pecific order</li> | ||||
<li>Added notes/reminders about browser-based client applications using CORS nee | ||||
ding access to response headers</li> | ||||
<li>Added a JWT claims registry update request for "nonce" to (better) | ||||
allow for more general use in other contexts</li> | ||||
</ul> | ||||
<t>-09</t> | ||||
<ul spacing="compact"> | ||||
<li>Add note/reminder about browser-based client applications using CORS needing | ||||
access to response headers.</li> | ||||
<li>Fixed typo</li> | ||||
</ul> | ||||
<t>-08</t> | ||||
<ul spacing="compact"> | ||||
<li>Lots of editorial updates from WGLC feedback</li> | ||||
<li>Further clarify that either iat or nonce can be used alone in validating the | ||||
timeliness of the proof and somewhat de-emphasize jti tracking</li> | ||||
</ul> | ||||
<t>-07</t> | ||||
<ul spacing="compact"> | ||||
<li>Registered the <tt>application/dpop+jwt</tt> media type.</li> | ||||
<li>Editorial updates/clarifications based on review feedback.</li> | ||||
<li>Added "(on the order of seconds or minutes)" to somewhat qualify & | ||||
quot;relatively brief period" and "reasonably near future" and gi | ||||
ve a general idea of expected timeframe without being overly prescriptive.</li> | ||||
<li>Added a step to <xref target="checking"></xref> to reiterate that the jwk he | ||||
ader cannot have a private key.</li> | ||||
</ul> | ||||
<t>-06</t> | ||||
<ul spacing="compact"> | ||||
<li>Editorial updates and fixes</li> | ||||
<li>Changed name of client metadata parameter to <tt>dpop_bound_access_tokens</t | ||||
t></li> | ||||
</ul> | ||||
<t>-05</t> | ||||
<ul spacing="compact"> | ||||
<li>Added Authorization Code binding via the <tt>dpop_jkt</tt> parameter.</li> | ||||
<li>Described the authorization code reuse attack and how <tt>dpop_jkt</tt> miti | ||||
gates it.</li> | ||||
<li>Enhanced description of DPoP proof expiration checking.</li> | ||||
<li>Described nonce storage requirements and how nonce mismatches and missing no | ||||
nces are self-correcting.</li> | ||||
<li>Specified the use of the <tt>use_dpop_nonce</tt> error for missing and misma | ||||
tched nonce values.</li> | ||||
<li>Specified that authorization servers use <tt>400 (Bad Request)</tt> errors t | ||||
o supply nonces and resource servers use <tt>401 (Unauthorized)</tt> errors to d | ||||
o so.</li> | ||||
<li>Added a bit more about <tt>ath</tt> and pre-generated proofs to the security | ||||
considerations.</li> | ||||
<li>Mentioned confirming the DPoP binding of the access token in the list in <xr | ||||
ef target="checking"></xref>.</li> | ||||
<li>Added the <tt>always_uses_dpop</tt> client registration metadata parameter.< | ||||
/li> | ||||
<li>Described the relationship between DPoP and Pushed Authorization Requests (P | ||||
AR).</li> | ||||
<li>Updated references for drafts that are now RFCs.</li> | ||||
</ul> | ||||
<t>-04</t> | ||||
<ul spacing="compact"> | ||||
<li>Added the option for a server-provided nonce in the DPoP proof.</li> | ||||
<li>Registered the <tt>invalid_dpop_proof</tt> and <tt>use_dpop_nonce</tt> error | ||||
codes.</li> | ||||
<li>Removed fictitious uses of <tt>realm</tt> from the examples, as they added n | ||||
o value.</li> | ||||
<li>State that if the introspection response has a <tt>token_type</tt>, it has t | ||||
o be <tt>DPoP</tt>.</li> | ||||
<li>Mention that RFC7235 allows multiple authentication schemes in <tt>WWW-Authe | ||||
nticate</tt> with a 401.</li> | ||||
<li>Editorial fixes.</li> | ||||
</ul> | ||||
<t>-03</t> | ||||
<ul spacing="compact"> | ||||
<li>Add an access token hash (<tt>ath</tt>) claim to the DPoP proof when used in | ||||
conjunction with the presentation of an access token for protected resource acc | ||||
ess</li> | ||||
<li>add Untrusted Code in the Client Context section to security considerations< | ||||
/li> | ||||
<li>Editorial updates and fixes</li> | ||||
</ul> | ||||
<t>-02</t> | ||||
<ul spacing="compact"> | ||||
<li>Lots of editorial updates and additions including expanding on the objective | ||||
s, | ||||
better defining the key confirmation representations, example updates and addit | ||||
ions, | ||||
better describing mixed bearer/dpop token type deployments, clarify RT binding | ||||
only being | ||||
done for public clients and why, more clearly allow for a bound RT but with bea | ||||
rer AT, | ||||
explain/justify the choice of SHA-256 for key binding, and more</li> | ||||
<li>Require that a protected resource supporting bearer and DPoP at the same tim | ||||
e | ||||
must reject an access token received as bearer, if that token is DPoP-bound</li | ||||
> | ||||
<li>Remove the case-insensitive qualification on the <tt>htm</tt> claim check</l | ||||
i> | ||||
<li>Relax the jti tracking requirements a bit and qualify it by URI</li> | ||||
</ul> | ||||
<t>-01</t> | ||||
<ul spacing="compact"> | ||||
<li>Editorial updates</li> | ||||
<li>Attempt to more formally define the DPoP Authorization header scheme</li> | ||||
<li>Define the 401/WWW-Authenticate challenge</li> | ||||
<li>Added <tt>invalid_dpop_proof</tt> error code for DPoP errors in token reques | ||||
t</li> | ||||
<li>Fixed up and added to the IANA section</li> | ||||
<li>Added <tt>dpop_signing_alg_values_supported</tt> authorization server metada | ||||
ta</li> | ||||
<li>Moved the Acknowledgements into an Appendix and added a bunch of names (best | ||||
effort)</li> | ||||
</ul> | ||||
<t>-00 [[ Working Group Draft ]]</t> | ||||
<ul spacing="compact"> | ||||
<li>Working group draft</li> | ||||
</ul> | ||||
<t>-04</t> | ||||
<ul spacing="compact"> | ||||
<li>Update OAuth MTLS reference to RFC 8705</li> | ||||
<li>Use the newish RFC v3 XML and HTML format</li> | ||||
</ul> | ||||
<t>-03</t> | ||||
<ul spacing="compact"> | ||||
<li>rework the text around uniqueness requirements on the jti claim in the DPoP | ||||
proof JWT</li> | ||||
<li>make tokens a bit smaller by using <tt>htm</tt>, <tt>htu</tt>, and <tt>jkt</ | ||||
tt> rather than <tt>http_method</tt>, <tt>http_uri</tt>, and <tt>jkt#S256</tt> r | ||||
espectively</li> | ||||
<li>more explicit recommendation to use mTLS if that is available</li> | ||||
<li>added David Waite as co-author</li> | ||||
<li>editorial updates</li> | ||||
</ul> | ||||
<t>-02</t> | ||||
<ul spacing="compact"> | ||||
<li>added normalization rules for URIs</li> | ||||
<li>removed distinction between proof and binding</li> | ||||
<li>"jwk" header again used instead of "cnf" claim in DPoP p | ||||
roof</li> | ||||
<li>renamed "Bearer-DPoP" token type to "DPoP"</li> | ||||
<li>removed ability for key rotation</li> | ||||
<li>added security considerations on request integrity</li> | ||||
<li>explicit advice on extending DPoP proofs to sign other parts of the HTTP mes | ||||
sages</li> | ||||
<li>only use the jkt#S256 in ATs</li> | ||||
<li>iat instead of exp in DPoP proof JWTs</li> | ||||
<li>updated guidance on token_type evaluation</li> | ||||
</ul> | ||||
<t>-01</t> | ||||
<ul spacing="compact"> | ||||
<li>fixed inconsistencies</li> | ||||
<li>moved binding and proof messages to headers instead of parameters</li> | ||||
<li>extracted and unified definition of DPoP JWTs</li> | ||||
<li>improved description</li> | ||||
</ul> | ||||
<t>-00</t> | ||||
<ul spacing="compact"> | ||||
<li>first draft</li> | ||||
</ul> | ||||
</section> | </section> | |||
</back> | </back> | |||
</rfc> | </rfc> | |||
End of changes. 292 change blocks. | ||||
1123 lines changed or deleted | 965 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. |