| Internet-Draft | OAuth Public | September 2026 |
| Jenkins & Bucksch | Expires 20 March 2027 | [Page] |
This document specifies a profile of the OAuth authorization protocol to allow for interoperability between native clients and servers using open protocols, such as JMAP, IMAP, SMTP, POP, CalDAV, and CardDAV. The profile is restricted to native clients, that is, applications installed and run on the end user's device. It deliberately does not support web-based clients, which cannot complete the flow as specified.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 20 March 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
This document pulls together several existing standards and uses them to specify a specific OAuth profile, allowing interoperable modern authentication for native clients of open protocols, such as JMAP, IMAP, 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 has many deficiencies from a security standpoint.¶
This profile applies only to native clients: applications that are installed and executed on the end user's device, as described in [RFC8252]. Web-based clients, that is, clients that run in a web browser or on a web server, are out of scope for this document.¶
This restriction is deliberate. The profile allows any client to register with any server without a pre-existing relationship (see Section 3.3), and there is no way for the server to verify any of the information supplied during that registration. For a native client, this does not introduce a new risk: a malicious application that the user has already installed and run could spoof the user's browser to phish their credentials, or install malware in unsandboxed environments, so allowing it to complete an OAuth flow makes the user no worse off. Indeed, it is more secure, as the alternative is a legitimate client storing the user's password.¶
Just navigating to a web page, however, is a different security scenario. Allowing arbitrary web-based clients to seamlessly register and obtain authorization would make it substantially easier for phishing sites to gain access to a user's account, by sending the user through a legitimate OAuth flow at the real authorization server and then receiving the resulting tokens.¶
The profile therefore enforces this restriction by limiting the redirect URIs that may be registered to loopback addresses and private-use URI schemes, which can only be received by software running on the user's device. See Section 3.3 for the specific requirements and Section 4 for further discussion.¶
This profile presumes a deployment has a set of one or more resource server endpoints (e.g., for JMAP/IMAP/SMTP/POP/CardDAV/CalDAV), and a common authorization server issuer identifier for all of them. For example, a deployment might have a JMAP session endpoint https://api.example.com/jmap/session, an IMAP endpoint imap.example.com, and an issuer identifier https://auth.example.com/acmeinc.¶
The endpoints may be discovered via an autoconfiguration mechanism, such as [I-D.ietf-mailmaint-pacc], or via manual user input. Autoconfiguration may also include the issuer identifier. To allow OAuth configuration for manual input or when the issuer identifier is not included in the autoconfiguration data, HTTP endpoints that support this profile MUST support Protected Resource Metadata [RFC9728], accessible via the oauth-protected-resource well-known path, as specified in Section 3 of [RFC9728]. The authorization_servers property MUST be present in the resource metadata. Servers SHOULD list exactly one issuer identifier, that of the authorization server to be used with this profile; if more than one is listed, the client instance MUST use the first. HTTP requests made without valid authentication to the resource endpoints MUST indicate the protected resource metadata URL in the resource_metadata parameter of the WWW-Authenticate HTTP response header field, as described in Section 5.1 of [RFC9728].¶
A client instance that needs the issuer identifier for an HTTP endpoint SHOULD obtain the metadata URL by making a request to the endpoint without credentials and reading the resource_metadata parameter from the WWW-Authenticate header field of the response. This works for endpoints whose own path is a well-known path, such as https://caldav.example.com/.well-known/caldav, and for endpoints that redirect during service discovery, as is common for CalDAV and CardDAV: the client instance follows the redirects as it normally would and reads the header field from the final response. If the header field is absent, the client instance MAY instead construct the metadata URL from the endpoint URL as described in Section 3.1 of [RFC9728]. The client instance MUST NOT follow HTTP redirects when fetching the metadata document itself.¶
In either case, the client instance MUST validate the metadata as required by Section 3.3 of [RFC9728]: the resource property MUST be identical to the URL of the request that returned the WWW-Authenticate header field, or, for a constructed URL, to the endpoint URL into which the well-known path was inserted. If it is not, the metadata MUST NOT be used. This check ensures that a redirect or a misconfigured server cannot cause the client instance to use metadata that describes some other resource.¶
Protected Resource Metadata is only available for HTTP-based endpoints. For IMAP, POP, and SMTP, the equivalent in-protocol mechanism is the openid-configuration field of the OAUTHBEARER failed-authentication response (Section 3.2.2 of [RFC7628]). Servers offering these protocols under this profile MUST include this field in every failed OAUTHBEARER response, with the URL of the authorization server metadata document (in either of the forms described in Section 3.2). A client instance that has not obtained the issuer identifier from autoconfiguration or the user MAY discover it by connecting to the endpoint over TLS, attempting OAUTHBEARER authentication with a syntactically valid but deliberately invalid token, and reading this field from the response. The client instance MUST then fetch the document at that URL (without following redirects, as in Section 3.2), take its issuer property as the issuer identifier, and proceed as described in that section from the issuer identifier alone, discarding the document it fetched. This ensures the metadata used is subject to every check in this document, regardless of the URL from which the field pointed. As with autoconfiguration data and protected resource metadata, the URL is supplied by a server that may itself be counterfeit, and the protections of Section 3.6 apply.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
OAuth 2 [RFC6749] 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.¶
The general flow works like this:¶
The access token can now be used as a Bearer token to authenticate requests to the application servers as per [RFC6750] for HTTP requests, or [RFC7628] for SASL authentication. When it expires, a new one can be requested using the refresh token as per Section 6 of [RFC6749].¶
The rest of this document describes in detail each of the above steps.¶
The client registration endpoint MUST accept registration requests that carry no initial access token or other form of authentication (open registration, see Section 3 of [RFC7591]), since a client instance following this profile has no pre-existing relationship with the server.¶
To register, the client instance sends an HTTP POST to the client registration endpoint (as found in the metadata) with a content type of "application/json", and a body consisting of a JSON document with the following properties:¶
redirect_urisAn array of URIs the client instance may use to receive back information at the end of the authorization flow. Each URI MUST satisfy all of these conditions:¶
The URI MUST start with one of the following:¶
/../).¶
#).¶
The URI may include a path and query parameters.¶
Claimed "https" scheme redirect URIs (Section 7.2 of [RFC8252]) are deliberately not permitted, even though they are otherwise the most secure option for native clients. An authorization server cannot distinguish a claimed https URI from an ordinary web URL, so permitting them would permit web-based clients to complete the flow. See Section 1.1 and Section 4.¶
token_endpoint_auth_methodgrant_typesresponse_typesscopeA string containing a space-separated list of scope values the client may request access for. (Note! This is not a JSON array.)¶
For compatibility with servers implementing OpenID Connect [OpenID.Core], if the server advertised the offline_access scope in the "scopes_supported" property of the authorization server metadata, the client instance MUST also register for this scope.¶
client_nameclient_urilogo_uritos_uripolicy_urisoftware_idsoftware_versionIf the server indicated in its metadata that it supports DPoP [RFC9449] and the client instance is intending to authenticate all requests using DPoP, the client instance SHOULD also include the following property:¶
dpop_bound_access_tokensIf set, the server MUST require every token request for the issued client id to include a DPoP proof, and MUST issue only DPoP-bound access tokens, as specified in Section 5.2 of [RFC9449]. DPoP is only defined for HTTP, so a client instance that uses non-HTTP protocols such as IMAP, POP, or SMTP MUST NOT set this property. See Section 3.8 for how such a client instance can still make use of DPoP.¶
The server will check that all required properties are present and have valid values. Any unknown properties supplied by the client instance 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.¶
The client instance MUST use the values returned in the registration response (see below) in preference to those it requested, in particular for the redirect_uris, scope, and dpop_bound_access_tokens properties. If the returned redirect_uris or scope omit a value the client instance requires, it MUST abort the flow and inform the user. If the server has omitted dpop_bound_access_tokens or returned it as false, for example because it returns a static client id to all requests, the client instance MUST NOT assume that access tokens will be DPoP-bound and MUST check the token_type of each token response (see Section 3.8).¶
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.¶
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.¶
The redirect URI restrictions MUST be enforced: a registration request containing a redirect URI that does not satisfy them MUST be rejected with an invalid_redirect_uri error (Section 3.2.2 of [RFC7591]). These ensure the OAuth flow can only be completed by native clients — not web clients — as discussed in Section 1.1. 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.¶
If successful, the server responds with an HTTP 201 Created status code and a body of type "application/json", 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:¶
client_idClients following this profile are public clients (see Section 2.1 of [RFC6749]): they register with a token_endpoint_auth_method of "none" and do not authenticate to the token endpoint, instead proving possession of the authorization code using PKCE. The server MUST NOT issue a client secret in the registration response, so the client_secret and client_secret_expires_at properties defined in Section 3.2.1 of [RFC7591] MUST NOT be present. A native client cannot keep a secret confidential, so a secret would offer no security benefit, and a client that expected to use one would not be interoperable with servers that correctly omit it. If a server nonetheless returns a client_secret, the client instance MUST ignore it and continue as a public client.¶
If the registration fails, the server will respond with an HTTP 400 status code and a JSON body as described in [RFC7591], section 3.2.2.¶
Following authorization, the client instance 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 "application/x-www-form-urlencoded" format with a character encoding of UTF-8 in the HTTP request entity-body:¶
client_idredirect_urigrant_typecodecode_verifierThe code_verifier generated for the authorization (the random string generated in the authorization step, as per [RFC7636]).¶
The server MUST reject a request that omits this parameter, or whose value does not verify against the code_challenge sent with the authorization request, as specified in Section 4.6 of [RFC7636]. An authorization code issued to a client registered under this profile MUST NOT be exchangeable without it: PKCE is the only protection against an authorization code intercepted via a loopback or private-use scheme redirect.¶
resource (optional)resource values sent in the authorization request. If omitted, the access token is issued for all of the authorized resources. See Section 3.8 for when a client instance needs to use this.¶
The client instance MAY include additional parameters defined by other OAuth extensions. The server MUST ignore any parameter it does not recognise, as required by Section 3.2 of [RFC6749], and clients MUST NOT depend on such parameters being understood for interoperability. If using DPoP, the client instance MUST also set a DPoP header in accordance with Section 5 of [RFC9449]. A client instance using DPoP MUST support the authorization server-provided nonce (Section 8 of [RFC9449]) and resource server-provided nonce (Section 9 of [RFC9449]) mechanisms, retrying a request that fails with a use_dpop_nonce error using the nonce supplied, as servers MAY require a nonce in every proof.¶
The server will verify the parameters and if successful, return a 200 OK response with a content type of application/json. The body will be a JSON
object with the following properties:¶
access_tokentoken_typeexpires_in3600 denotes that the access token will expire in one hour from the time the response was generated. Servers MUST include this property in every token response (it is only RECOMMENDED in Section 5.1 of [RFC6749]), as clients rely on it to obtain a new access token before the current one expires (see Section 3.10).¶
scopeThe space delimited set of scopes that this access token may use. Servers MUST include this property in every token response, even where it is identical to the set of scopes requested (in which case it is OPTIONAL in Section 5.1 of [RFC6749]).¶
Note, this MAY be different to the set of scopes requested. Servers MAY allow users to choose to authorize only a subset of the requested scopes. Clients MUST check the set of scopes granted is sufficient for its needs.¶
refresh_tokenusernameThe username of the account that was authenticated and granted this authorization, in the form the user would enter it to log in to this deployment (typically the user's email address). Servers MUST include this property in every token response, and the value MUST be the same in every token response issued under the same authorization.¶
The user may have started the flow by giving the client instance one username (which the client instance may have passed as the login_hint, see Section 3.4) and then authenticated at the authorization server as a different user. Without this property the client instance has no interoperable way to discover this, and may label the account, or associate the tokens with a local account, incorrectly. The client instance MUST use this value, rather than the username originally supplied by the user, as the identity of the account the tokens belong to. If it differs from the username the user supplied, the client instance SHOULD make this visible to the user.¶
OpenID Connect [OpenID.Core] can convey the authenticated user's identity in an ID Token, but this profile does not require OpenID Connect support, and the sub claim it guarantees is an opaque identifier rather than a username the user would recognise. This document therefore registers "token response" as an additional usage location for the existing username parameter (see Section 5.2).¶
If the request fails, the server MUST return an error response as described in Section 5.2 of [RFC6749]: a 400 Bad Request status code (or 401 Unauthorized for an invalid_client error) with a content type of application/json, and a JSON object body with the properties defined there. A client id that is no longer valid (see Section 3.12) is reported with the invalid_client error code. An authorization code or refresh token that is invalid, expired, or revoked is reported with the invalid_grant error code.¶
An access token obtained from an authorization server MUST only be sent to a resource server that the client instance has determined to be associated with that authorization server, as described in this section. This protects against a counterfeit resource server that has been named in autoconfiguration data or protected resource metadata under the attacker's control (see Section 4.9.1 of [RFC9700] and Section 4).¶
The client instance MUST make this determination for every host to which it sends an access token. This includes any host reached by following an HTTP redirect, such as those commonly used in CalDAV and CardDAV service discovery: the determination is made against the URL actually being requested, not only the endpoint URL the client instance started from. A client instance MUST NOT send an access token to a host for which the determination fails. If the client instance cannot function without that resource server, it MUST abort and inform the user.¶
The determination is made in one of two ways, depending on whether the authorization server metadata includes the protected_resources property (see Section 3.2):¶
resource parameter in Section 3.4.¶
The registrable domain of a host name is its public suffix plus the DNS label immediately preceding that suffix, where the public suffix is determined using the Public Suffix List [PSL]. For example, the registrable domain of imap.example.com is example.com, and the registrable domain of auth.example.co.uk is example.co.uk. Host names MUST be compared case-insensitively, and internationalized host names MUST be converted to A-labels [RFC5890] before comparison. A host that is an IP address literal, or that has no registrable domain (for example, a single-label host name, or a host name that is itself a public suffix), is never permitted under this rule.¶
The registrable domain rule allows deployments that host their authorization server and resource servers within a single domain, for example auth.example.com and imap.example.com, to be secure without further configuration. Deployments whose resource servers are not all within the registrable domain of the issuer identifier, including providers that use a separate identity provider domain and multi-tenant authorization servers whose issuer identifier includes a path component, MUST publish protected_resources (see Section 3.2), as clients following this profile will otherwise refuse to use their resource servers.¶
The client instance is now authenticated. It can connect to the resource servers permitted under Section 3.6 with the Bearer scheme [RFC6750]. For HTTP-based protocols, this means setting an Authorization header with the value Bearer {access_token} (where {access_token} is replaced with the value of the access_token). If using DPoP, the client instance MUST also set a DPoP header in accordance with Section 7 of [RFC9449].¶
For protocols that use SASL authentication, such as IMAP, POP, and SMTP, the access token is used in accordance with the OAUTHBEARER mechanism defined in [RFC7628]. Servers MUST NOT require the username associated with the resource (the "authzid") be included in the GS2 header. The client instance MUST include the host attribute in its initial client response (Section 3.1 of [RFC7628]), set to the host name it connected to, and SHOULD include the port attribute. [RFC7628] makes these attributes optional for bearer tokens; this profile requires host because it is the value the client instance used as the Resource Indicator for the endpoint (see Section 3.4), which allows a server to check that the access token was issued for the host it is being presented to.¶
DPoP [RFC9449] is only defined for HTTP. The proof JWT (Section 4.2 of [RFC9449]) is bound to the HTTP method and URI of the request it protects and is carried in an HTTP header field, and the OAUTHBEARER SASL mechanism [RFC7628] has no means of carrying such a proof. A DPoP-bound access token therefore cannot be used to authenticate to an IMAP, POP, or SMTP server. Sender-constraining access tokens for SASL-based protocols would require a new SASL mechanism, or an extension to OAUTHBEARER, together with a means for the resource server to verify the proof. That is out of scope for this document.¶
A client instance that uses only HTTP-based protocols and wishes to use DPoP SHOULD register with dpop_bound_access_tokens set to true (see Section 3.3), include a DPoP proof in every token request, and use the resulting DPoP-bound access tokens as described in Section 7 of [RFC9449].¶
A client instance that uses non-HTTP protocols, whether exclusively or alongside HTTP-based protocols, has two choices. The simplest is not to use DPoP at all, in which case all tokens are bearer tokens. Alternatively, it MAY use DPoP for the token endpoint and for HTTP-based resources while still obtaining bearer tokens for non-HTTP resources, as follows:¶
dpop_bound_access_tokens to true when registering, as the server would then be required to issue only DPoP-bound access tokens.¶
resource parameters in the token request (see Section 3.5 and Section 3.10): one request listing only its HTTP-based resources, and a second listing only its non-HTTP resources (that is, hostnames, see Section 3.4). The initial token request exchanging the authorization code can be made for either set, and the other set is then obtained by a refresh request.¶
resource parameter is a hostname for a non-HTTP resource, a server that supports both DPoP and Resource Indicators MUST issue an access token that is not bound to the DPoP key, with a token_type of "Bearer". For any other token request that includes a DPoP proof, the server issues a DPoP-bound access token with a token_type of "DPoP", as normal. Servers that support DPoP SHOULD therefore also support Resource Indicators, so that client instances using non-HTTP protocols are not prevented from using DPoP.¶
token_type of each response and use the token accordingly: a "DPoP" token with the DPoP authentication scheme for HTTP requests, and a "Bearer" token with the Bearer scheme or OAUTHBEARER. If the client instance receives a "DPoP" token in response to a request that listed only non-HTTP resources, the server does not support this arrangement (for example, because it does not support Resource Indicators and ignored the parameters). The client instance MUST NOT attempt to use that token with a non-HTTP server, and MUST obtain a new authorization without using DPoP if it is to continue.¶
A client instance can avoid the last failure case in most deployments by only attempting this arrangement when the authorization server metadata includes protected_resources, which indicates the server acts on Resource Indicators.¶
To work interoperably, clients and servers must use a common set of scopes for access. This document creates a new IANA registry for such scopes (see Section 5.1), and registers scopes to cover IMAP, SMTP, POP, CardDAV, CalDAV, and JMAP.¶
Registration of a scope in that registry does not by itself impose any requirement on OAuth implementations in general (see Section 5.1). This profile, however, does require support: a server implementing this profile MUST support each of the scopes registered by this document (Section 5.1.5) whose definition covers a protocol or type of data that the server offers. For example, a server that offers IMAP and SMTP MUST support urn:ietf:params:oauth:scope:mail, and a server that offers CalDAV MUST support urn:ietf:params:oauth:scope:calendars. Supporting a scope means advertising it in the scopes_supported metadata property, accepting it in registration and authorization requests, and granting the access described in its registration when it is authorized.¶
Servers MAY additionally support other scopes, for example finer-grained or vendor-specific scopes, but clients following this profile can only rely on the registered scopes being available.¶
Clients SHOULD keep using an access token they have been issued until it expires. The client instance knows when this will happen from the expires_in property returned with the token, and, while it has an active need for the token (for example, open connections it expects to re-establish), SHOULD proactively obtain a new access token shortly before the current one expires, rather than waiting for a request to fail. A client instance with no such need SHOULD NOT refresh merely to keep a token current. This is particularly important for stateful protocols such as IMAP and SMTP, where the token is needed at connection time and a round trip to the token endpoint would otherwise delay every reconnection. Clients MUST nonetheless be prepared for an access token to be rejected at any time (for HTTP-based protocols, with a 401 response), as the server may invalidate it early, and MUST handle this by obtaining a new one.¶
When the access token expires, the client instance MUST get a new one by making another POST request to the authorization server token endpoint. The following parameters MUST be present, using the "application/x-www-form-urlencoded" format with a character encoding of UTF-8 in the HTTP request entity-body:¶
client_idgrant_typerefresh_tokenresource (optional)The success and failures responses are identical to those documented in "Obtaining a refresh token" (Section 3.5).¶
Because clients following this profile are public clients, the server MUST protect against refresh token replay using one of the two methods required by Section 4.14.2 of [RFC9700]. If the refresh token is sender-constrained, because the client instance presented a DPoP proof when it was issued and the server bound it to the client instance's key (Section 5 of [RFC9449]), the server MAY omit the refresh_token property from the response or return the same refresh token, in which case the client instance continues to use the refresh token it holds. Otherwise, the server MUST return a new refresh token in the response (refresh token rotation). In either case, the client instance MUST replace its previous refresh token with the one returned if one is returned and it differs, and MUST persist the new refresh token before making any use of the access token returned alongside it.¶
When the server issues a new refresh token, it MUST NOT invalidate the previous refresh token immediately. Instead, the previous refresh token MUST remain valid until the server first sees either the new refresh token or the new access token issued in the same response being used. The response may not reach the client instance: the connection may drop, or the client may crash before it can persist the new token. In either case the client instance will legitimately retry with the refresh token it still holds, and the flow must succeed. A request presenting the previous refresh token during this window MUST be answered with the same new refresh token that was issued in the original response, together with either the same access token (with expires_in adjusted for the time elapsed) or a freshly issued one. The server MUST NOT issue a further new refresh token in response to the previous one. If it did, an attacker who had obtained a copy of the previous refresh token and used it during the window would obtain a refresh token chain of their own, independent of the client instance's, and the detection described below would never catch it. Returning the same new refresh token instead means the attacker and the legitimate client instance hold the same token, and the next rotation reveals the duplicate. Once the new refresh token or the new access token has been used, however, the server knows the client instance received the response, so any subsequent use of the previous refresh token can only come from a copy that has been leaked or stolen. Note that an authorization server may not observe access token use at all, for example when access tokens are self-contained and validated locally by the resource server, or are presented to a separate IMAP or SMTP server. Use of the new refresh token is therefore the trigger that every server can rely upon; use of the new access token allows a server that does observe it to close the window sooner. At that point the server MUST treat the previous refresh token as invalid, and SHOULD revoke the entire authorization, including the current refresh token and all associated access tokens, as a protection against leaked refresh tokens.¶
This deviates from Section 4.14.2 of [RFC9700], which invalidates the previous refresh token as soon as the new one is issued. The deviation is limited to the window between issuance and the client instance's first use of the new tokens, during which the previous token can obtain nothing beyond what the response already granted, and is necessary to allow a client instance that did not receive the response to recover without user interaction.¶
The client instance MUST ensure that only one token request is in flight at a time for a given refresh token, for example by serialising refresh operations across all connections that share the authorization. Concurrent refreshes would otherwise race, with one of them presenting a refresh token that has just been superseded.¶
If a user has multiple devices with the same client software installed, each instance of the client MUST obtain separate authorization. A refresh token MUST NOT be shared between devices.¶
Access tokens MUST have a lifetime of at least 10 minutes, and SHOULD have a lifetime of at least 1 hour.¶
The hard minimum exists so that a client instance can rely on an access token it has just obtained surviving a single operation, especially in the face of poor network conditions where it may have to retry several times before it can connect to the resource server. It also bounds the rate at which a client instance must contact the token endpoint, making the client more efficient with its network usage.¶
The recommended lifetime of one hour further reduces load on the token endpoint and, more importantly, loosens the coupling between the authorization server and the resource servers: with hour-long tokens a brief outage of the authorization server, or a period on a network where it is unreachable, is invisible to the user. The trade-off is that a longer lifetime extends the window during which a leaked bearer token can be misused. Servers that consider this window too long are encouraged to support DPoP ([RFC9449]), which prevents a stolen access token from being used by anyone other than the client instance it was issued to, rather than to shorten the lifetime below one hour.¶
Refresh tokens SHOULD NOT expire, unless the user explicitly revokes the token or it has been unused for a considerable period of time (at least 30 days).¶
For stateful connection-based protocols such as SMTP and IMAP the access token is only presented on first connection. Expiry of the access token SHOULD NOT affect current IMAP/SMTP etc. sessions that have already authenticated. However, should the server choose to force reauthorization it MUST do so by unilaterally closing the connection, as there is no way to reauthenticate an existing session in these protocols and all clients have to be able to handle reconnection in the case of dropped connections.¶
When the server revokes a refresh token (for example, because the user has revoked the client's authorization, or because the token has been detected as leaked), it MUST close any existing stateful connections that were authenticated using access tokens issued under that refresh token.¶
A client instance cannot detect that its refresh token has been revoked until it next attempts to use it. Once a client instance does detect revocation (by receiving an invalid_grant error from the token endpoint, or an invalid_client error indicating that the client id is no longer valid, see Section 3.12), it MUST discard the refresh token and any associated access tokens, MUST close any stateful connections it still has open that were authenticated with them, and MUST obtain new authorization before reconnecting (see Section 3.12).¶
The client id MUST remain valid for as long as there is a valid refresh token associated with that client id.¶
To ensure a good user experience, the client id assigned upon dynamic registration SHOULD be valid for use in the authorization flow (Section 3.4) for at least one hour after issuance.¶
Clients MUST associate a client id with each refresh token it has. If the refresh token is invalidated and the client instance has to reauthenticate, it MUST submit the dynamic client registration (Section 3.3) again and use the client id returned, which MAY be different than the previous client id. A client instance that receives an invalid_client error from the token endpoint MUST likewise treat the client id as no longer valid and re-register before obtaining new authorization.¶
Servers that wish to store client registration information MUST be careful of resource exhaustion attacks. A RECOMMENDED approach is to:¶
This profile mandates best practices for OAuth with native clients, as defined in [RFC8252]. A thorough discussion of the security considerations generally applicable to OAuth is out of scope for this document, but can be found in [RFC6819] and in the OAuth 2.0 Security Best Current Practice [RFC9700] (BCP 240), as well as the security considerations (Section 10) of [RFC6749].¶
Implementers are encouraged to read all of the above documents for a more thorough consideration of the specific threats and mitigations with OAuth.¶
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.¶
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 undetectably 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. This is also why claimed "https" scheme redirect URIs (Section 7.2 of [RFC8252]) are excluded: although they are the most secure redirect option on platforms that support them, an authorization server has no way to tell one from an ordinary web URL, and permitting them would permit web-based clients.¶
Access tokens, refresh tokens, and authorization codes are bearer credentials: anyone who obtains one can use it. Clients MUST only send them over connections secured with TLS, and MUST verify the server's certificate as described in [RFC9525]. This applies to the token endpoint, to HTTP-based resource servers as required by Section 5.3 of [RFC6750], and to protocols using SASL: for IMAP, POP, and SMTP, the client MUST negotiate TLS (either Implicit TLS or STARTTLS, see [RFC8314]) before sending the OAUTHBEARER authentication exchange. Servers MUST NOT accept access tokens over connections that are not protected by TLS. The one exception is the redirect back to a loopback redirect URI (Section 3.3), which uses the "http" scheme. This carries only the authorization code, and the connection never leaves the user's device. The code is additionally protected by PKCE, so it is useless to anyone other than the client instance that holds the corresponding code verifier.¶
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 authorization 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.¶
All metadata supplied in a dynamic client registration is attacker-controlled from the authorization server's point of view. The client_name, client_uri, logo_uri, tos_uri, and policy_uri values MAY be shown to the user, but the authorization server MUST treat them as untrusted content. It MUST escape them appropriately when rendering them, and MUST NOT fetch logo_uri or any other supplied URL from the server side without the protections appropriate to fetching an untrusted URL, since such a fetch can otherwise be used to reach resources on the server's internal network. Any such URL may also point at malicious content, as discussed in Section 5 of [RFC7591]. A logo loaded by the user's browser additionally discloses the user's IP address, and the fact that an authorization is taking place, to whoever controls the URL. Because the identity of the client cannot be verified, the authorization server SHOULD make clear on the consent page that the client is unverified, SHOULD display the requested scopes in plain language, and MUST NOT present the registration metadata in a way that suggests it has been vetted. Servers that prefer not to display unverified metadata MAY show only the requested scopes and a generic description of the client.¶
Refresh tokens are long-lived credentials, and DPoP private keys are equivalent in value to the tokens they protect. Client instances SHOULD store both using the most secure storage the platform provides, such as an operating system keychain or keystore, with hardware-backed storage where available, and MUST NOT write them to logs or, where the platform offers protected storage, to storage accessible to other applications. Access tokens SHOULD be handled the same way, but MAY be held only in memory. When the user removes an account from the client, or the client is being uninstalled, the client instance SHOULD revoke its refresh token via the revocation_endpoint if the server advertises one, so that the server can discard the authorization rather than waiting for the token to expire through inactivity.¶
Both kinds of redirect URI permitted by this profile can be claimed by software other than the client instance. Another application on the device may register the same private-use URI scheme (Section 8.1 of [RFC8252]), and another process may bind the loopback port the client instance intends to use before it does (Section 8.3 of [RFC8252]). In either case the authorization code may be delivered to the wrong recipient. This profile mitigates this in two ways. The code is useless without the PKCE code verifier, which never leaves the client instance, so an intercepted code cannot be exchanged (Section 4.5.3.1 of [RFC9700]). The state parameter binds a response to a request the client instance made, so an attacker cannot inject a code of their own into the client instance's flow (Section 4.7 of [RFC9700]). Client instances MUST bind a loopback listener to the loopback interface only, MUST accept at most one authorization response per listener, and MUST close the listener once the response has been received or the flow abandoned.¶
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 instance 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:¶
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 [WebAuthn] for authentication will mitigate this, and most browsers have a block list of known phishing sites that can also help mitigate this.¶
The attacker publishes their own authorization server metadata, copying the real authorization_endpoint and token_endpoint values but naming their own resource servers. This is a mix-up attack (Section 4.4 of [RFC9700]) and is protected against by the issuer identifier check. The authorization response will include an iss parameter carrying the legitimate issuer identifier, but the issuer property of the attacker's metadata must name the attacker's own domain (if it did not, the client instance would have aborted after fetching the metadata, as the property would not match the identifier from which the metadata URL was derived). The two therefore differ, and a client instance following this specification will abort the flow and not send the authorization code to the token endpoint.¶
The attacker publishes no authorization server metadata of their own. Instead, the autoconfiguration data or protected resource metadata under their control names the real authorization server's issuer identifier alongside the attacker's own resource servers. The client instance fetches the genuine metadata, and the issuer property matches. The user authenticates and grants consent at the genuine authorization server, and the iss parameter in the authorization response matches. Every check in the flow passes, because nothing has been mixed up: the client instance then presents a valid access token to the attacker's resource server, and the attacker replays it against the real one. This is the counterfeit resource server attack described in Section 4.9.1 of [RFC9700], and the issuer identifier check offers no protection against it.¶
The protection is the rule in Section 3.6: the authorization server vouches for its resource servers, either explicitly by publishing protected_resources, or implicitly through the resource servers sharing the registrable domain of the issuer identifier. In the example above, the attacker's host is under the mistyped domain while the issuer identifier is under the provider's domain, so the client instance refuses to send the token. Servers that support Resource Indicators [RFC8707] add a second, server-side layer: the client instance sends a resource value for every resource server it intends to use, and the authorization server rejects the request if any is not one of its own. Sender-constrained access tokens ([RFC9449]) further prevent a captured HTTP access token from being replayed, but offer no protection for non-HTTP protocols, so they are not a substitute for the rule above.¶
The registrable domain rule has two limitations. First, it relies on the Public Suffix List [PSL], which is maintained outside the IETF and changes over time; a client instance with a stale copy may classify a host differently from an up-to-date one. Clients SHOULD keep their copy current and MUST fail closed where a host cannot be classified. Second, an attacker that controls any host within the registrable domain of the issuer identifier (for example, on a shared hosting platform or under an institution's domain) is not excluded by it. Such an attacker must also control the autoconfiguration for the domain the user entered, so the exposure is narrow, but deployments in which untrusted parties can obtain host names under the issuer's registrable domain SHOULD publish protected_resources to close it.¶
The attacker uses the real authorization_endpoint value and the real resource servers in its metadata, but uses their own token_endpoint. The issuer identifier check described in item 2 will also protect against this.¶
This specification allows clients to fall back to the OpenID Connect Discovery metadata path if the RFC 8414 metadata path fails. Implementers should be aware that these two paths have different security properties when the issuer identifier contains a path component. The RFC 8414 path inserts the well-known component at the host root (e.g., https://auth.example.com/.well-known/oauth-authorization-server/acmeinc), meaning only an entity with control over the host can serve this document. The OpenID Connect Discovery path appends the well-known component to the issuer (e.g., https://auth.example.com/acmeinc/.well-known/openid-configuration), meaning any entity that controls the path can serve this document. In multi-tenant environments where different entities control different paths on the same host, the OpenID Connect Discovery fallback allows a tenant to serve their own metadata without host-level control. The issuer identifier verification remains the primary defence against mix-up attacks in all cases, but operators of shared hosts should be aware that the RFC 8414 path provides an additional layer of host-level vetting that the OpenID Connect Discovery path does not.¶
IANA is requested to add a new registry called "Interoperable OAuth Scopes" to the "OAuth Parameters" registry group [IANA.OAuth.Parameters]. The registry records OAuth scope values that have a standardised, interoperable meaning, such that a client and a server with no pre-existing relationship can agree on the access a scope grants. Each scope provides specific access rights to protected resources, and the registry records a reference to the specification that defines those rights.¶
Registration of a scope in this registry does not, by itself, impose any requirement on OAuth authorization servers, resource servers, or clients in general. An OAuth implementation is not required to recognise, support, or grant any scope in this registry merely because it is registered. In this respect the registry is a coordination mechanism, ensuring a given scope value has a single well-defined meaning wherever it is used, rather than a statement of what OAuth implementations must support.¶
Support for a registered scope is required only where a profile or other specification that references this registry mandates it. Such a specification MUST clearly identify which implementations are required to support which scopes. This document is one such profile: the scopes that servers implementing it MUST support are specified in Section 3.9. Other profiles MAY reference scopes in this registry and define their own support requirements, and the same scope MAY be required by more than one profile.¶
Scope names in this registry are case sensitive. Names MUST NOT match other registered names in a case-insensitive manner unless the designated experts state that there is a compelling reason to allow an exception.¶
A newly defined scope registered in this registry MUST be a URN in the urn:ietf:params:oauth:scope: sub-namespace of the OAuth URN namespace [RFC6755], of the form urn:ietf:params:oauth:scope:<name>, for example urn:ietf:params:oauth:scope:mail. The <name> component SHOULD be a short, lowercase, descriptive identifier for the class of data or resources to which the scope grants access. Using this namespace guarantees the value cannot collide with scope strings defined elsewhere, and makes clear to implementers that the value has a standardised meaning. Any such URN MUST also be registered in the IANA "OAuth URI" registry [IANA.OAuth.Parameters] established by [RFC6755], referencing the same specification document(s).¶
An unstructured scope string, that is, one that is not a URN in the above sub-namespace, MAY be registered only where all of the following apply:¶
Unstructured strings MUST NOT be registered for newly defined scopes. Where a specification wishes to register a scope with an unstructured name, the designated experts MUST verify that the referenced specification defines the value with the meaning given in the registration request.¶
Values are registered via Specification Required [RFC8126]. Registration requests should be sent to the oauth-ext-review@ietf.org mailing list to initiate a two-week review period. However, to allow for the allocation of values prior to publication of the final version of a specification, the designated experts may approve registration once they are satisfied that the specification will be completed and published. However, if the specification is not completed and published in a timely manner, as determined by the designated experts, the designated experts may request that IANA withdraw the registration.¶
Registration requests sent to the mailing list for review should use an appropriate subject (e.g., "Request to register Interoperable OAuth Scope: example").¶
Within the review period, the designated experts will either approve or deny the registration request, communicating this decision to the review list and IANA. Denials should include an explanation and, if applicable, suggestions as to how to make the request successful. If the designated experts are not responsive, the registration requesters should contact IANA to escalate the process.¶
Designated experts should apply the following criteria when reviewing proposed registrations:¶
IANA must only accept registry updates from the designated experts and should direct all requests for registration to the review mailing list.¶
In order to enable broadly informed review of registration decisions, there should be multiple designated experts to represent the perspectives of different applications using this specification. In cases where registration may be perceived as a conflict of interest for a particular expert, that expert should defer to the judgment of the other experts.¶
The mailing list is used to enable public review of registration requests, which enables both designated experts and other interested parties to provide feedback on proposed registrations. Designated experts may allocate values prior to publication of the final specification. This allows authors to receive guidance from the designated experts early, so any identified issues can be fixed before the final specification is published.¶
urn:ietf:params:oauth:scope:mail). This name is case sensitive and MUST conform to Section 5.1.2.¶
urn:ietf:params:oauth:scope:mail¶
Requests access for a client to manage the user's email. This MUST include full access via all of the following protocols that the server supports:¶
urn:ietf:params:oauth:scope:mail is included in the Interoperable OAuth Scopes column of the JMAP capabilities registry.¶
urn:ietf:params:oauth:scope:contacts¶
urn:ietf:params:oauth:scope:contacts is included in the Interoperable OAuth Scopes column of the JMAP capabilities registry.¶
urn:ietf:params:oauth:scope:calendars¶
urn:ietf:params:oauth:scope:calendars is included in the Interoperable OAuth Scopes column of the JMAP capabilities registry.¶
IANA is requested to update the registration of the username parameter in the "OAuth Parameters" registry [IANA.OAuth.Parameters] established by Section 11.2 of [RFC6749], adding "token response" to its parameter usage location and adding this document to its specification document(s). The updated registration is as follows:¶
username¶
The use of the username parameter in a token response is defined in Section 3.5. Its use in a token request, defined by Section 4.3.2 of [RFC6749], is unchanged.¶
This section registers the following values in the IANA "OAuth URI" registry [IANA.OAuth.Parameters] established by [RFC6755]. They are the scope values defined by this document within the urn:ietf:params:oauth:scope: sub-namespace, as required by Section 5.1.2.¶
urn:ietf:params:oauth:scope:mail¶
urn:ietf:params:oauth:scope:contacts¶
urn:ietf:params:oauth:scope:calendars¶
IANA is requested to update the "JMAP Capabilities" registry established in [RFC8620] to add a new column called "Interoperable OAuth Scopes". For each capability, this column shall contain a list of zero or more scopes registered in the Interoperable OAuth Scopes Registry. Authorization for any scope in the list will grant access to use that JMAP capability, if the capability is supported by the server.¶
Future registrations in the "JMAP Capabilities" registry SHOULD specify a value for the Interoperable OAuth Scopes column in addition to the fields established in the registration template by Section 9.4.5 of [RFC8620]. If omitted, registrations will be added with no value for this column (i.e., no interoperable scopes are available to grant access to this capability via OAuth).¶
IANA is requested to update the existing JMAP Capabilities registrations with the following values for the Interoperable OAuth Scopes column.¶