Internet-Draft | OAuth Public | January 2025 |
Jenkins | Expires 11 July 2025 | [Page] |
- Workgroup:
- Mail Maintenance
- Internet-Draft:
- draft-ietf-mailmaint-oauth-public-00
- Published:
- Intended Status:
- Informational
- Expires:
OAuth Profile for Open Public Clients
Abstract
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.¶
Status of This Memo
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 11 July 2025.¶
Copyright Notice
Copyright (c) 2025 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.¶
1. Introduction
This document pulls together several existing standards and uses them to specifiy a specific OAuth profile, allowing interoperable modern authentication for native 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 has many deficiences from a security standpoint.¶
1.1. Presumptions
This OAuth flow presumes you have a username that is used to identify the user, along with:¶
- The set of services that may be available for this username (e.g., JMAP/IMAP/SMTP/POP/CardDAV/CalDAV);¶
- The Application Server endpoint to connect to in order to access them;
(e.g., a JMAP session endpoint
https://api.example.com/jmap/session
, or an IMAP endpointimaps://imap.example.com:993
).¶ - The authorization server issuer identifier, needed to do OAuth, e.g.,
https://auth.example.com
.¶
Ideally, the client may use an autodiscovery mechanism to find these given the username. Servers supporting this OAuth profile MUST support [TODO:RFC-To-Be-Defined] for autodiscovery.¶
1.2. Scopes
To work interoperably, clients and server must use a standard set of scopes for access. This document creates a new IANA registry for such scopes (see Section 4), and registers scopes to cover IMAP, SMTP, CardDAV, CalDAV, WebDAV, and JMAP.¶
1.3. Notational Conventions
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.¶
2. The Open Public Client OAuth Profile
2.1. Overview
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 OAuth 2.0 Authorization Server Metadata [RFC8414] is fetched.¶
- The client registers with the authorization server to get a client id using the OAuth 2.0 Dynamic Client Registration Protocol [RFC7591].¶
- The client authorizes using the Authorization Code Grant flow [RFC6749], Section 4.1) with PKCE [RFC7636], Issuer Identification [RFC9207] and Resource Indicators [RFC8707].¶
- The client gets an access token and refresh token, as per Section 5 of [RFC6749].¶
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.¶
2.3. Dynamic Client Registration
To register, the client 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_uris
-
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:¶
-
The URI MUST start with one of the following:¶
- The URI MUST NOT include two consecutive dots (e.g.,
/../
).¶ - The URI MUST NOT include a fragment part (
#
).¶
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).¶
-
token_endpoint_auth_method
- This MUST be "none".¶
grant_types
- This is an array of strings that MUST include "authorization_code" and "refresh_token".¶
response_types
- This is an array of strings that MUST include "code".¶
scope
-
A 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-connect], if the server advertised the offline_access scope in the "scopes_supported" property of the Authorization Server Data, the client MUST also register for this scope.¶
client_name
- The name of the client to be presented to the end-user during authorization.¶
client_uri
- A URL for a web page providing information about the client. This MUST use HTTPS.¶
logo_uri
- 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.¶
tos_uri
- A URL that points to a human-readable terms of service or license document for the client. This MUST use HTTPS.¶
policy_uri
- A URL that points to a human-readable privacy policy document for the client. This MUST use HTTPS.¶
software_id
- 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 "client_id", which is issued by the authorization server and may vary between instances, the "software_id" SHOULD remain the same for all instances of the client software. The "software_id" 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.¶
software_version
- A version identifier string for the client software identified by "software_id". The value of the "software_version" SHOULD change on any update to the client software identified by the same "software_id". The value of this field is intended to be compared using string equality matching and no other comparison semantics are defined by this specification.¶
If the server indicated in its metadata that it supports DPoP [RFC9449] and the client is intending to authenticate all requests using DPoP, the client SHOULD also include the following property:¶
dpop_bound_access_tokens
- true¶
(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.)¶
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.¶
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. These ensure the OAuth flow can only be completed by native clients — 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.¶
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_id
- The OAuth 2.0 client identifier string, used in the authorization flow (see Section 2.4).¶
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.¶
2.5. Obtaining a Refresh Token
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 "application/x-www-form-urlencoded" format with a character encoding of UTF-8 in the HTTP request entity-body:¶
client_id
- The client id as returned in the registration.¶
redirect_uri
- The redirect_uri parameter sent with the authorization request from which the code was obtained.¶
grant_type
- This MUST be "authorization_code".¶
code
- The code returned via the redirect back from authorization.¶
code_verifier
- The code_verifier generated for the authorization (the random string generated in the authorization step, as per [RFC7636]).¶
Other parameters MAY be supplied but will be ignored. If using DPoP, the client MUST also set a DPoP header in accordance with Section 5 of [RFC9449].¶
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_token
- A bearer token used to authenticate API requests. This will be valid for a fixed, limited time.¶
token_type
- The type of the access token. This MUST be "bearer".¶
expires_in
- The lifetime in seconds of the access token. For example, the value
3600
denotes that the access token will expire in one hour from the time the response was generated.¶ scope
-
The space delimited set of scopes that this access token may use.¶
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. The server MAY also return scopes beyond those requested, for example a server that adds JMAP support when previously it only supported IMAP may choose to give scopes that enable JMAP access to the same data, even if only the IMAP scope was requested, so the client can seamlessly upgrade protocols.¶
refresh_token
- The refresh token to use next time the client needs to get a new access token.¶
If the request fails, the server MUST return a 400 Bad Request
response with a content type of application/json. The body will be a JSON object with properties as described in Section 5.2 of [RFC6749]¶
2.6. Using the Access Token
The client is now authenticated. It can connect to the servers given in the discovered auto config 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 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.¶
2.7. Getting a New Access Token
Client should keep using an access token they have been issued until it expires,
which will result in getting a 401
error back.¶
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 "application/x-www-form-urlencoded" format with a character encoding of UTF-8 in the HTTP request entity-body:¶
client_id
- The client id as returned in the registration.¶
grant_type
- This MUST be "refresh_token".¶
refresh_token
- The refresh token returned last time the client obtained a new access token.¶
The success and failures responses are identical to those documented in "Obtaining a refresh token" (Section 2.5).¶
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.¶
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.¶
2.8. Token Expiry Times
To ensure a good user experience, access tokens MUST have a lifetime of at least 1 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.¶
If the refresh token is revoked, all existing stateful connections MUST immediately be closed.¶
2.9. Client Id Validity
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 2.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 has to reauthenticate, it MUST submit the dynamic client registration (Section 2.3) again and use the client id returned, which MAY be different to the previous time.¶
Servers that wish to store client registration information MUST be careful of resource exhaustion attacks. A RECOMMENDED approach is to:¶
- Normalize and securely hash the submitted registration data.¶
- Check if this hash already exists in the database, and if so return the existing client id issued for this registration.¶
- Otherwise, keep the registration in temporary storage and only insert it into the database upon successful authorization.¶
- Remove any client registrations from the database whenever there are no valid refresh tokens associated with that client id.¶
3. Security Considerations
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], as well as the security considerations (Section 10) of [RFC6749].¶
Implementors 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 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.¶
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.¶
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:¶
-
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.¶
-
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 ([RFC8707]) — 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.¶
It is also protected against via the issuer identifier. The authorization response will include an "iss" 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.¶
-
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.¶
4. IANA Considerations
4.1. Interoperable OAuth Scopes Registry
IANA shall add a new registry called "Interoperable OAuth Scopes" to the "OAuth Parameters" registry group. The registry records interoperable OAuth scope values. Each scope provides specific access rights to protected resources.¶
4.1.1. Registration Procedure
The "Specification Required" policy, as defined in Section 4.6 of [RFC8126], shall govern registrations in this registry. The Designated Expert shall verify that:¶
4.1.2. Registration Template
- Scope Name:
- The name of the OAuth scope value.¶
- Description:
- A clear description of what access rights this scope grants to the client, with reference to publicly available and stable documentation sufficient for interoperability.¶
- Change Controller:
- The name of the person, organization, or entity controlling changes to the scope definition.¶
4.1.3. Initial Registry Contents
- Scope Name:
-
carddav
¶ - Description:
- Grants the right to use the CardDAV protocol [RFC6352].¶
- Change Controller
- IETF¶
- Scope Name:
-
caldav
¶ - Description:
- Grants the right to use the CalDAV protocol [RFC4791].¶
- Change Controller
- IETF¶
- Scope Name:
-
imap
¶ - Description:
- Grants the right to use the IMAP protocol [RFC9051].¶
- Change Controller
- IETF¶
- Scope Name:
-
pop
¶ - Description:
- Grants the right to use the POP protocol [RFC1939].¶
- Change Controller
- IETF¶
- Scope Name:
-
smtp
¶ - Description:
- Grants the right to use the SMTP submission protocol [RFC6409].¶
- Change Controller
- IETF¶
5. Informative References
- [RFC1939]
- Myers, J. and M. Rose, "Post Office Protocol - Version 3", STD 53, RFC 1939, DOI 10.17487/RFC1939, , <https://www.rfc-editor.org/info/rfc1939>.
- [RFC4791]
- Daboo, C., Desruisseaux, B., and L. Dusseault, "Calendaring Extensions to WebDAV (CalDAV)", RFC 4791, DOI 10.17487/RFC4791, , <https://www.rfc-editor.org/info/rfc4791>.
- [RFC6352]
- Daboo, C., "CardDAV: vCard Extensions to Web Distributed Authoring and Versioning (WebDAV)", RFC 6352, DOI 10.17487/RFC6352, , <https://www.rfc-editor.org/info/rfc6352>.
- [RFC6409]
- Gellens, R. and J. Klensin, "Message Submission for Mail", STD 72, RFC 6409, DOI 10.17487/RFC6409, , <https://www.rfc-editor.org/info/rfc6409>.
- [RFC8620]
- Jenkins, N. and C. Newman, "The JSON Meta Application Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, , <https://www.rfc-editor.org/info/rfc8620>.
- [RFC9051]
- Melnikov, A., Ed. and B. Leiba, Ed., "Internet Message Access Protocol (IMAP) - Version 4rev2", RFC 9051, DOI 10.17487/RFC9051, , <https://www.rfc-editor.org/info/rfc9051>.
- [openid-connect]
- OpenID Foundation, "OpenID Connect", <https://openid.net/developers/specs/>.
6. Normative References
- [RFC2119]
- Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
- [RFC3986]
- Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/info/rfc3986>.
- [RFC6749]
- Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, , <https://www.rfc-editor.org/info/rfc6749>.
- [RFC6750]
- Jones, M. and D. Hardt, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", RFC 6750, DOI 10.17487/RFC6750, , <https://www.rfc-editor.org/info/rfc6750>.
- [RFC6819]
- Lodderstedt, T., Ed., McGloin, M., and P. Hunt, "OAuth 2.0 Threat Model and Security Considerations", RFC 6819, DOI 10.17487/RFC6819, , <https://www.rfc-editor.org/info/rfc6819>.
- [RFC7009]
- Lodderstedt, T., Ed., Dronia, S., and M. Scurtescu, "OAuth 2.0 Token Revocation", RFC 7009, DOI 10.17487/RFC7009, , <https://www.rfc-editor.org/info/rfc7009>.
- [RFC7591]
- Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol", RFC 7591, DOI 10.17487/RFC7591, , <https://www.rfc-editor.org/info/rfc7591>.
- [RFC7628]
- Mills, W., Showalter, T., and H. Tschofenig, "A Set of Simple Authentication and Security Layer (SASL) Mechanisms for OAuth", RFC 7628, DOI 10.17487/RFC7628, , <https://www.rfc-editor.org/info/rfc7628>.
- [RFC7636]
- Sakimura, N., Ed., Bradley, J., and N. Agarwal, "Proof Key for Code Exchange by OAuth Public Clients", RFC 7636, DOI 10.17487/RFC7636, , <https://www.rfc-editor.org/info/rfc7636>.
- [RFC8126]
- Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/info/rfc8126>.
- [RFC8174]
- Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
- [RFC8252]
- Denniss, W. and J. Bradley, "OAuth 2.0 for Native Apps", BCP 212, RFC 8252, DOI 10.17487/RFC8252, , <https://www.rfc-editor.org/info/rfc8252>.
- [RFC8414]
- Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 Authorization Server Metadata", RFC 8414, DOI 10.17487/RFC8414, , <https://www.rfc-editor.org/info/rfc8414>.
- [RFC8707]
- Campbell, B., Bradley, J., and H. Tschofenig, "Resource Indicators for OAuth 2.0", RFC 8707, DOI 10.17487/RFC8707, , <https://www.rfc-editor.org/info/rfc8707>.
- [RFC9207]
- Meyer zu Selhausen, K. and D. Fett, "OAuth 2.0 Authorization Server Issuer Identification", RFC 9207, DOI 10.17487/RFC9207, , <https://www.rfc-editor.org/info/rfc9207>.
- [RFC9449]
- Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449, , <https://www.rfc-editor.org/info/rfc9449>.
- [webauthn]
- W3C, "Web Authentication: An API for accessing Public Key Credentials, Level 2", <https://www.w3.org/TR/webauthn/>.