Internet-Draft | OAuth Public | May 2024 |
Jenkins | Expires 18 November 2024 | [Page] |
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.¶
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 18 November 2024.¶
Copyright (c) 2024 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 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.¶
This OAuth flow presumes you have an email address that is used to identify the user, along with:¶
https://api.example.com/jmap/session
, or an IMAP endpoint imaps://imap.example.com:993
).¶
https://auth.example.com
.¶
Ideally, the client may use an autodiscovery mechanism to find these given the email address. Such a mechanism is out of scope of this document.¶
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.¶
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 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]). When it expires, a new one can be requested using the refresh token (as per [RFC6749], Section 6).¶
The rest of this document describes each for the above steps in detail.¶
To register, the client or developer 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:¶
com.example:/
. Such a scheme MUST have at
least one dot in it.¶
/../
).¶
#
).¶
The URI may include a path and query parameters. Clients MUST generate a unqiue 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.)¶
client_name¶
Human-readable string name of the client to be presented to the end-user during authorization.¶
client_uri¶
A URL string of 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 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 SHOULD 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:¶
(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 — (U+2014) 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.¶
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 XXX).¶
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 will obtain initial refresh tokens 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 given to the developer.¶
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 [RFC9449], Section 5.¶
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 will always 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.¶
refresh_token¶
The refresh token to use next time the client needs to get a new 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}
.¶
If using DPoP, the client must also set a DPoP header in accordance with [RFC9449], Section 7.¶
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 given to the developer.¶
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 XXX).¶
A new refresh token will be returned in the response and the client MUST replace their previous refresh token with this. 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 the user has multiple devices, each client MUST obtain separate authorization. You cannot share a refresh token between devices.¶
Yes, there are security considerations. They will be added in due course.¶
This document does not introduce any IANA considerations.¶