<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-jenkins-oauth-public-01" submissionType="IETF" category="info" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" consensus="true">

<front>
<title abbrev="OAuth Public">OAuth Profile for Open Public Clients</title><seriesInfo value="draft-jenkins-oauth-public-01" stream="IETF" status="informational" name="Internet-Draft"></seriesInfo>
<author role="editor" initials="N.M." surname="Jenkins" fullname="Neil Jenkins"><organization>Fastmail</organization><address><postal><street>PO Box 234, Collins St West</street>
<city>Melbourne</city>
<code>VIC 8007</code>
<country>Australia</country>
</postal><email>neilj@fastmailteam.com</email>
<uri>https://www.fastmail.com</uri>
</address></author><date year="2024" month="October" day="15"></date>
<area>Security</area>
<workgroup>OAuth</workgroup>
<keyword>OAuth</keyword>

<abstract>
<t>This document specifies a profile of the OAuth authorization protocol to allow for interoperability between clients and servers using open protocols, such as JMAP, IMAP, SMTP, POP, CalDAV, and CardDAV.</t>
</abstract>

</front>

<middle>

<section anchor="introduction"><name>Introduction</name>
<t>This document pulls together several existing standards and specifies a specific profile using them to allow for interoperable modern authentication for clients of open protocols, such as IMAP, JMAP, SMTP, POP, CalDAV, and CardDAV. For these protocols, there are many servers and many clients with no pre-existing relationship, that need to be able to connect. At the moment, the only interoperable way to do so is with a basic username and password, which have many deficiences from a security standpoint.</t>

<section anchor="presumptions"><name>Presumptions</name>
<t>This OAuth flow presumes you have a username that is used to identify the user, along with:</t>

<ol spacing="compact">
<li>The set of services that may be available for this username
(e.g., JMAP/IMAP/SMTP/POP/CardDAV/CalDAV);</li>
<li>The Application Server endpoint to connect to in order to access them;
(e.g. a JMAP session endpoint <tt>https://api.example.com/jmap/session</tt>, or an IMAP endpoint <tt>imaps://imap.example.com:993</tt>).</li>
<li>The authorization server issuer identifier, needed to do OAuth, e.g.
<tt>https://auth.example.com</tt>.</li>
</ol>
<t>Ideally, the client may use an autodiscovery mechanism to find these given the username. Such a mechanism is out of scope of this document.</t>
</section>

<section anchor="scopes"><name>Scopes</name>
<t>To work interoperably, clients and server must use a standard set of scopes for access. A separate document will bring together an autodiscovery mechanism (to get the details described above), this document (for authorization), and a set of standard scopes.</t>
</section>

<section anchor="notational-conventions"><name>Notational Conventions</name>
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"></xref> <xref target="RFC8174"></xref> when, and only when, they appear in all capitals, as shown here.</t>
</section>
</section>

<section anchor="the-open-public-client-oauth-profile"><name>The Open Public Client OAuth Profile</name>

<section anchor="overview"><name>Overview</name>
<t>OAuth 2 can be used in many different ways. This document specifies one particular set of options to ensure interoperability and security. Servers may implement more options, but MUST support the flow as described in this document for interoperability with clients. Similarly, clients may choose to support additional flows but there is no guarantee that this will be interoperable.</t>
<t>The general flow works like this:</t>

<ol spacing="compact">
<li>The OAuth 2.0 Authorization Server Metadata (<xref target="RFC8414"></xref>) is fetched.</li>
<li>The client registers with the authorization server to get a client id using
the OAuth 2.0 Dynamic Client Registration Protocol (<xref target="RFC7591"></xref>).</li>
<li>The client authorizes using the Authorization Code Grant flow (<xref target="RFC6749"></xref>,
Section 4.1) with PKCE (<xref target="RFC7636"></xref>), Issuer Identification (<xref target="RFC9207"></xref>) and
Resource Indicators (<xref target="RFC8707"></xref>).</li>
<li>The client gets an access token and refresh token (as per <xref target="RFC6749"></xref>,
Section 5).</li>
</ol>
<t>The access token can now be used as a Bearer token to authenticate requests to the application servers as per <xref target="RFC6750"></xref> for HTTP requests, or <xref target="RFC7628"></xref> for SASL authentication. When it expires, a new one can be requested using the refresh token as per <xref target="RFC6749"></xref>, Section 6.</t>
<t>The rest of this document describes in detail each of the above steps.</t>
</section>

<section anchor="fetching-the-authorization-server-data"><name>Fetching the Authorization Server Data</name>
<t>The authorization server issuer identifier MUST be an HTTPS URL with no query parameters or fragment part. Otherwise, abort the flow. The authorization server metadata may be fetched by a GET request to the path found by removing any trailing <tt>/</tt> and then appending <tt>/.well-known/oauth-authorization-server</tt> to this URL.</t>
<t>When fetched, a successful response is indicated by a 200 OK HTTP status code. The reponse MUST have an &quot;application/json&quot; content type. Anything else MUST be treated as an error, and the flow MUST be aborted.</t>
<t>The authorization server metadata is a JSON document with properties as specified in <xref target="RFC8414"></xref>. It MUST include the following properties:</t>

<ul>
<li><t>issuer</t>
<t>The authorization server's issuer identifier. This MUST be identical to the issuer identifier used to fetch this document. For example, if this document was fetched from <eref target="https://example.com/foo/.well-known/oauth-authorization-server">https://example.com/foo/.well-known/oauth-authorization-server</eref>, the issuer MUST be &quot;<eref target="https://example.com/foo&quot;">https://example.com/foo"</eref>. If not, the flow MUST be aborted.</t>
<t>This MUST be verified again during the authorization flow (see Section XXX), to prevent against mix-up attacks (as defined in <xref target="RFC9207"></xref>).</t>
</li>
<li><t>registration_endpoint</t>
<t>The URL the client will use to register, to get a client id it needs for authentication (see Section XXX).</t>
</li>
<li><t>authorization_endpoint</t>
<t>The URL the client will use to start the authentication process (see Section XXX) once it has registered.</t>
</li>
<li><t>token_endpoint</t>
<t>The URL the client will use to get an access token after successful authentication (see Section XXX).</t>
</li>
<li><t>scopes_supported</t>
<t>An array of supported scopes on the server (see Section XXX).</t>
</li>
<li><t>response_types_supported</t>
<t>A list of response types supported in the OAuth authorization flow. This is an array of strings that MUST include &quot;code&quot;.</t>
</li>
<li><t>grant_types_supported</t>
<t>A list of the OAuth 2.0 grant type values that this authorization server supports. This is an array of strings that MUST include &quot;authorization_code&quot; and &quot;refresh_token&quot;.</t>
</li>
<li><t>token_endpoint_auth_methods_supported</t>
<t>This is an array of strings that MUST include &quot;none&quot;.</t>
</li>
<li><t>code_challenge_methods_supported</t>
<t>An array of strings listing Proof Key for Code Exchange (PKCE) <xref target="RFC7636"></xref>
  code challenge methods supported by this authorization server.
  This MUST include &quot;S256&quot;.</t>
</li>
<li><t>authorization_response_iss_parameter_supported</t>
<t>This MUST have the boolean value true.</t>
</li>
</ul>
<t>The metadata MAY include other properties, or other values for multi-valued properties, however clients are not required to understand or use any of them for interoperability.</t>
<t>It is RECOMMENDED servers support DPoP (<xref target="RFC9449"></xref>) to allow sender-constrained refresh and access tokens for HTTP-based protocols. Servers that support DPoP MUST include the following property:</t>

<ul>
<li><t>dpop_signing_alg_values_supported</t>
<t>A JSON array containing a list of the JWS alg values (from the [IANA.JOSE.ALGS] registry) supported by the authorization server for DPoP proof JWTs, as defined in <xref target="RFC9449"></xref>, Section 5.1.</t>
</li>
</ul>
<t>Also of possible interest to client/server implementors following this document:</t>

<ul>
<li><t>revocation_endpoint</t>
<t>The URL the client can use to revoke their tokens, as per <xref target="RFC7009"></xref>.</t>
</li>
<li><t>revocation_endpoint_auth_methods_supported</t>
<t>If a revocation_endpoint is included, this property MUST be included,
  and is an array of strings that MUST include &quot;none&quot;.</t>
</li>
</ul>
<t>Clients MUST verify the required properties are present and conform to the requirements of this document. If not, the server is not using OAuth in conformance with this document and no compatibility may be presumed. It is RECOMMENDED clients abort the flow in such a case.</t>
</section>

<section anchor="dynamic-client-registration"><name>Dynamic Client Registration</name>
<t>To register, the client sends an HTTP POST to the client registration endpoint (as found in the metadata) with a content type of &quot;application/json&quot;, and a body consisting of a JSON document with the following properties:</t>

<ul>
<li><t>redirect_uris</t>
<t>An array of URIs the client may use to receive back information at the
  end of the authorization flow. Each URI MUST satisfy all of these
  conditions:</t>

<ul spacing="compact">
<li><t>The URI MUST start with one of the following:</t>

<ul spacing="compact">
<li><eref target="http://127.0.0.1/">http://127.0.0.1/</eref></li>
<li>http://::1/</li>
<li>A private-use scheme in reverse domain notation,
e.g., <tt>com.example:/</tt>. Such a scheme MUST have at
least one dot in it.</li>
</ul></li>
<li>The URI MUST NOT include two consecutive dots (e.g., <tt>/../</tt>).</li>
<li>The URI MUST NOT include a fragment part (<tt>#</tt>).</li>
</ul>
<t>The URI may include a path and query parameters. Clients MUST generate
  a unique redirect URI for each authorization server they register with
  to ensure they can protect against mix up attacks (see later).</t>
</li>
<li><t>token_endpoint_auth_method</t>
<t>This MUST be &quot;none&quot;.</t>
</li>
<li><t>grant_types</t>
<t>This is an array of strings that MUST include &quot;authorization_code&quot; and &quot;refresh_token&quot;.</t>
</li>
<li><t>response_types</t>
<t>This is an array of strings that MUST include &quot;code&quot;.</t>
</li>
<li><t>scope</t>
<t>A string containing a space-separated list of scope values the client
  may request access for. (Note! This is not a JSON array.)</t>
</li>
<li><t>client_name</t>
<t>Human-readable string name of the client to be presented to the
  end-user during authorization.</t>
</li>
<li><t>client_uri</t>
<t>A URL string of a web page providing information about the client. This
  MUST use HTTPS.</t>
</li>
<li><t>logo_uri</t>
<t>A URL for a logo to display for this client. This SHOULD be square, and
  in a PNG or SVG image format. This MUST use HTTPS.</t>
</li>
<li><t>tos_uri</t>
<t>A URL that points to a human-readable terms of service or license document for the client. This MUST use HTTPS.</t>
</li>
<li><t>policy_uri</t>
<t>A URL that points to a human-readable privacy policy document for the
  client. This MUST use HTTPS.</t>
</li>
<li><t>software_id</t>
<t>A unique identifier string (e.g., a Universally Unique Identifier
  (UUID)) assigned by the client developer or software publisher, used by
  registration endpoints to identify the client software to be
  dynamically registered.  Unlike &quot;client_id&quot;, which is issued by the
  authorization server and SHOULD vary between instances, the
  &quot;software_id&quot; SHOULD remain the same for all instances of the client
  software.  The &quot;software_id&quot; SHOULD remain the same across multiple
  updates or versions of the same piece of software. The value of this
  field is not intended to be human readable and is usually opaque to the
  client and authorization server.</t>
</li>
<li><t>software_version</t>
<t>A version identifier string for the client software identified by
  &quot;software_id&quot;.  The value of the &quot;software_version&quot; SHOULD change on
  any update to the client software identified by the same
  &quot;software_id&quot;.  The value of this field is intended to be compared
  using string equality matching and no other comparison semantics are
  defined by this specification.</t>
</li>
</ul>
<t>If the server indicated in its metadata that it supports DPoP <xref target="RFC9449"></xref> and the client is intending to authenticate all requests using DPoP, the client SHOULD also include the following property:</t>

<ul>
<li><t>dpop_bound_access_tokens</t>
<t>true</t>
</li>
</ul>
<t>(If set, the server MUST then require all token requests from this client use DPoP. Note, DPoP is only currently defined for HTTP protocols, so this precludes usage for non-HTTP procols as of time of writing.)</t>
<t>The server will check that all required properties are present and have valid values. Any unknown properties supplied by the client MUST just be ignored. The authorization server MAY replace any of the client's requested metadata values submitted during the registration and substitute them with suitable values.</t>
<t>If there is an exact match for all properties except for software_version, an existing registration may be returned. Otherwise, servers SHOULD create a new registration and client id.</t>
<t>There is no way to verify the authenticity of the information supplied by the client, however the general case of accurate information is still useful to the server, for example to be able to contact client authors to help debug issues if aberrant behaviour is observed. Servers MAY choose to ignore all of the information instead and just return a static client id to all requests.</t>
<t>The redirect URI restrictions MUST be enforced. These ensure the OAuth flow can only be completed by native clients <u format="char-num">—</u> not web clients. Since a malicious native client could present the user with a custom browser to phish credentials anyway, the lack of verification of client registration details does not provide additional danger beyond existing threats. Allowing seamless dynamic registration for web-based clients however, unfortunately makes it much easier for a phishing site to gain access to an account, by sending the user through the OAuth flow.</t>
<t>If successful, the server responds with an HTTP 201 Created status code and a body of type &quot;application/json&quot;, with the content being a JSON object containing all the properties submitted during registration (with their values as set by the server, if overwritten), plus the following property:</t>

<ul>
<li><t>client_id</t>
<t>The OAuth 2.0 client identifier string, used in the authorization flow (
  see Section XXX).</t>
</li>
</ul>
<t>If the registration fails, the server will respond with an HTTP 400 status code and a JSON body as described in <xref target="RFC7591"></xref>, section 3.2.2.</t>
</section>

<section anchor="authorization"><name>Authorization</name>
<t>Clients initiate authorization by opening the authorization_endpoint URL in a web browser, with the following additional query parameters:</t>

<ul>
<li><t>client_id</t>
<t>The client id as returned in the registration.</t>
</li>
<li><t>redirect_uri</t>
<t>One of the redirect uris registered by the client. This MUST be identical to the registered URI. The one exception to this is if a
  URI with the prefix &quot;<eref target="http://127.0.0.1/&quot;">http://127.0.0.1/"</eref> or &quot;http://::1/&quot; was registered, in which case the matching URI MUST also include an arbitrary port.</t>
<t>For example, if &quot;<eref target="http://127.0.0.1/redirect&quot;">http://127.0.0.1/redirect"</eref> was registered, then the
  client could send &quot;<eref target="http://127.0.0.1:49152/redirect&quot;">http://127.0.0.1:49152/redirect"</eref> as the redirect_uri
  for authorization.</t>
</li>
<li><t>response_type</t>
<t>This MUST be &quot;code&quot;.</t>
</li>
<li><t>scope</t>
<t>A space delimited set of scopes the client would like access to. This
    MUST be a subset of the scopes registered for the client.</t>
</li>
<li><t>code_challenge</t>
<t>A PKCE code challenge as per <xref target="RFC7636"></xref>, using SHA 256. To generate a
  challenge, first generate a code_verifier: a high-entropy cryptographic
  random STRING using the unreserved characters
  <tt>[A-Z] / [a-z] / [0-9] / &quot;-&quot; / &quot;.&quot; / &quot;_&quot; / &quot;~&quot;</tt>
  from Section 2.3 of <xref target="RFC3986"></xref>, with a minimum length of 43 characters
  and a maximum length of 128 characters.</t>
<t>The code_challenge is then
  <tt>BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))</tt></t>
</li>
<li><t>code_challenge_method</t>
<t>This MUST be &quot;S256&quot;.</t>
</li>
<li><t>resource</t>
<t>The URL for the initial resource endpoint (as returned in the autodiscover) you wish to access after successful authorization. For example, &quot;<eref target="https://api.example.com/jmap/session&quot;">https://api.example.com/jmap/session"</eref>. If you wish to use multiple protocols, the client MUST include multiple &quot;resource&quot; query parameters: one for each endpoint. The server MUST verify that all requested endpoints are permitted locations to send access tokens to (i.e., they are the real endpoints resource associated with this authentication server), in order to prevent mix up attacks.</t>
</li>
<li><t>state</t>
<t>An opaque value used by the client to verify that an authorization
  response is due to a request that the client initiated. The
  authorization server will include this value when redirecting the
  user-agent back to the client.  Clients MUST generate a state with a
  unique, unguessable random string when initiating an authorization
  request.</t>
</li>
<li><t>login_hint (optional)</t>
<t>The username the user originally asked to log in with. The server can prefill this in a login form. Note, the user may choose to log in with a different username.</t>
</li>
</ul>
<t>The authorization server MUST verify all required parameters, and that they conform to the restrictions in this document. Other URL parameters MAY be supplied but will be ignored.</t>
<t>If verified, the authorization server will authenticate the user and ask them if they wish to grant authorization to the client. If successful, the client will receive a response via the redirect_uri, which will include the following query parameters:</t>

<ul>
<li><t>code</t>
<t>The authorization code. This may be exchanged for the refresh token. This code MUST have a limited expiry, which MUST be at least 10 minutes from authorization. It MUST NOT be used again once the client has successfully exchanged it for a refresh token. Doing so may cause the server to detect it as stolen and revoke all associated tokens.</t>
</li>
<li><t>state</t>
<t>The value of the state parameter that was passed in with the initial
  request.</t>
</li>
<li><t>iss</t>
<t>The issuer identifier of the authorization server.</t>
</li>
</ul>
<t>The client MUST verify all of the following:</t>

<ul spacing="compact">
<li>The &quot;iss&quot; returned is identical to the &quot;issuer&quot; property in the metadata
object. This is critical for preventing against various mix-up attacks should a malicious OAuth metadata object be fetched, as discussed in the security considerations.</li>
<li>The state returned matches exactly the state it sent, to verify that this
request was indeed initiated by the client and not an attacker.</li>
<li>The redirect URI the authorization response came in on was the one they used
when generating the request. This prevents mix-up attacks when the client supports more than one authorization server, where it thinks it was authenticating against one AS, but actually the user authenticated with another AS.</li>
</ul>
<t>If any verification fails, the client MUST abort the flow and not send the authorization code anywhere.</t>
</section>

<section anchor="obtaining-a-refresh-token"><name>Obtaining a Refresh Token</name>
<t>Following authorization, the client will obtain initial refresh and
access tokens by making a POST request to the token_endpoint URL. The following parameters MUST be present, using the &quot;application/x-www-form-urlencoded&quot; format with a character encoding of UTF-8 in the HTTP request entity-body:</t>

<ul>
<li><t>client_id</t>
<t>The client id as returned in the registration.</t>
</li>
<li><t>redirect_uri</t>
<t>The redirect_uri parameter sent with the authorization request from
  which the code was obtained.</t>
</li>
<li><t>grant_type</t>
<t>This MUST be &quot;authorization_code&quot;.</t>
</li>
<li><t>code</t>
<t>The code returned via the redirect back from authorization.</t>
</li>
<li><t>code_verifier</t>
<t>The code_verifier generated for the authorization (the random string generated in the authorization step, as per <xref target="RFC7636"></xref>).</t>
</li>
</ul>
<t>Other parameters MAY be supplied but will be ignored. If using DPoP, the client MUST also set a DPoP header in accordance with <xref target="RFC9449"></xref>, Section 5.</t>
<t>The server will verify the parameters and if successful, return a <tt>200 OK</tt>
response with a content type of application/json. The body will be a JSON
object with the following properties:</t>

<ul>
<li><t>access_token</t>
<t>A bearer token used to authenticate API requests. This will be valid for a fixed, limited time.</t>
</li>
<li><t>token_type</t>
<t>The type of the access token. This MUST be &quot;bearer&quot;.</t>
</li>
<li><t>expires_in</t>
<t>The lifetime in seconds of the access token. For example, the value <tt>3600</tt> denotes that the access token will expire in one hour from the time the response was generated.</t>
</li>
<li><t>scope</t>
<t>The space delimited set of scopes that this access token may use.</t>
</li>
<li><t>refresh_token</t>
<t>The refresh token to use next time the client needs to get a new access token.</t>
</li>
</ul>
</section>

<section anchor="using-the-access-token"><name>Using the access_token</name>
<t>The client is now authenticated. It can connect to the servers given in the discovered auto config with the Bearer scheme <xref target="RFC6750"></xref>. For HTTP based protocols, this means setting an <tt>Authorization</tt> header with the value <tt>Bearer {access_token}</tt>.</t>
<t>If using DPoP, the client must also set a DPoP header in accordance with <xref target="RFC9449"></xref>, Section 7.</t>
</section>

<section anchor="getting-a-new-access-token"><name>Getting a New Access Token</name>
<t>Client should keep using an access token they have been issued until it expires,
which will result in getting a <tt>401</tt> error back.</t>
<t>When the access token expires, the client must get a new one by making another POST request to the authorization server token endpoint. The following parameters MUST be present, using the &quot;application/x-www-form-urlencoded&quot; format with a character encoding of UTF-8 in the HTTP request entity-body:</t>

<ul>
<li><t>client_id</t>
<t>The client id as returned in the registration.</t>
</li>
<li><t>grant_type</t>
<t>This MUST be &quot;refresh_token&quot;.</t>
</li>
<li><t>refresh_token</t>
<t>The refresh token returned last time the client obtained a new access
  token.</t>
</li>
</ul>
<t>The success and failures responses are identical to those documented in
&quot;Obtaining a refresh token&quot; (Section XXX).</t>
<t>A new refresh token SHOULD be returned in the response and the client MUST replace their previous refresh token with this if given. The client MUST NOT try to use an old refresh token again; this SHOULD result in the authorization being revoked as a protection against leaked refresh tokens.</t>
<t>If a user has multiple devices with a client installed, each instance of the client MUST obtain separate authorization. You cannot share a refresh token between devices.</t>
</section>
</section>

<section anchor="security-considerations"><name>Security Considerations</name>
<t>This profile mandates OAuth best practices, as defined in [draft-ietf-oauth-security-topics]. Implementors are encouraged to read this document for a more thorough consideration of the specific threats and mitigations with OAuth.</t>
<t>The choices made for this profile are intended to mitigate as far as possible the inherent risks that come from allowing arbitrary clients to talk to arbitrary servers.</t>
<t>The key restriction of this profile is that the redirect_uri MUST be something only a native client can access. If the user has downloaded and run a malicious native app, it could already indetectably spoof the user's browser to phish them, or in unsandboxed environments install malware, so supporting the OAuth flow from an unknown client is not increasing risks. Indeed, it is more secure than the current alternative, which is legitimate clients storing the user's password.</t>
<t>The dynamic registration part of this document is not a security component, as there is no way to verify any of the data. The data in the registration may be shown to the user as part of the authorisation flow, which may help with phishing, but as noted above the redirect_uri can only be used by a native app, which could already phish the user. However, the registration gives the server more information to detect suspicious behaviour, which can help it to detect compromised users and devices more easily.</t>
<t>The issuer is expected to be autodetected from the user's email address. A threat scenario that must be considered is the user making a small typo in the domain (especially for a common email service), and an attacker controlling this domain. In this scenario the client will fetch the OAuth metadata from the attacker's server, and has no way to know it is not the real server the user wishes to connect to. This leads to a number of threats:</t>

<ol>
<li><t>The attacker defines a malicious authorization_endpoint under their control.
They attempt to phish the user's credentials with this. This is not something that can be specifically mitigated by the requirements of this document, however requiring origin-bound authentication such as passkeys for authentication will mitigate this, and most browsers have a block list of known phishing sites that can also help mitigate this.</t>
</li>
<li><t>The attacker defines the real authorization_endpoint and token_endpoint, but
their own resource servers. This is protected against by the use of Resource Indicators (<xref target="RFC8707"></xref>) - the client must send the list of all resource endpoints it intends to connect to with the authorization request. If an unknown resource server is present, the server can reject the request.</t>
<t>It is also protected against via the issuer identifier. The authorization response will include an &quot;iss&quot; parameter which will be the legitimate issuer identifier. However, the issuer for the metadata will not match, as this must be at the attacker's domain (if it were not, the client will have aborted the flow after fetching the metadata, as it would not match the domain it was fetched from). Therefore a client following this specification will abort the flow and not send the authorization code to the token endpoint.</t>
</li>
<li><t>The attacker defines the real authorization_endpoint and resource servers,
but their own token_endpoint. The issuer identifier check above will also protect against this.</t>
</li>
</ol>
</section>

<section anchor="iana-considerations"><name>IANA Considerations</name>
<t>This document does not introduce any IANA considerations.</t>
</section>

</middle>

<back>
<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.3986.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.7009.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.7628.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.8174.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.8707.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9207.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9449.xml"/>
</references>

</back>

</rfc>
