RFC 7628

A Set of Simple Authentication and Security Layer (SASL) Mechanisms for OAuth

πŸ“… published August 2015, from ietf

RFC 7628: A Set of Simple Authentication and Security Layer (SASL) Mechanisms for OAuth πŸŽ€

Okay bestie, the title block is giving official paperwork energy πŸ“œ but here's the tea. This is RFC 7628 from the Internet Engineering Task Force (IETF), a Request for Comments with the number 7628. It was written by W. Mills (Microsoft), T. Showalter, and H. Tschofenig (ARM Ltd.). It's a Standards Track document, the ISSN is 2070-1721, and it's dated August 2015. The title block doesn't list anything it obsoletes or updates, so there's no drama with older RFCs here πŸ™Œ

Abstract

OAuth lets a third-party app get limited access to a protected resource πŸ”‘ either on behalf of a resource owner (through an approval interaction) or by letting the third-party app get access for itself.

This document explains how an application client uses credentials it got through OAuth over the Simple Authentication and Security Layer (SASL) to access a protected resource at a resource server πŸ’– So basically, it makes OAuth schemes from the OAuth framework work for non-HTTP-based application protocols. Iconic ✨

Clients usually hold on to the user's long-term credential, and ngl, that's a huge security risk. Like, if that credential leaks, it's a whole disaster 😭 The big win of OAuth for these clients is that the password gets swapped for a shared secret with higher entropy, which is the token. Tokens usually give limited access rights and can be managed and revoked separately from the user's long-term password. No cap, that's way safer πŸ›‘οΈ

Status of This Memo

This is an Internet Standards Track document 🌸

It's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community. It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG). For more info on Internet Standards, check Section 2 of RFC 5741 πŸ“š

You can find the current status of this document, any errata, and how to give feedback at http://www.rfc-editor.org/info/rfc7628 πŸ¦‹

Copyright (c) 2015 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 (http://trustee.ietf.org/license-info) as in effect on the date of publication of this document. Please read these carefully, because they spell out your rights and restrictions for this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Simplified BSD License βš–οΈ

Table of Contents

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
2.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   5
3.  OAuth SASL Mechanism Specifications . . . . . . . . . . . . .   6
  3.1.  Initial Client Response . . . . . . . . . . . . . . . . .   7
    3.1.1.  Reserved Key/Values . . . . . . . . . . . . . . . . .   8
  3.2.  Server's Response . . . . . . . . . . . . . . . . . . . .   8
    3.2.1.  OAuth Identifiers in the SASL Context . . . . . . . .   9
    3.2.2.  Server Response to Failed Authentication  . . . . . .   9
    3.2.3.  Completing an Error Message Sequence  . . . . . . . .  10
  3.3.  OAuth Access Token Types using Keyed Message Digests  . .  11
4.  Examples  . . . . . . . . . . . . . . . . . . . . . . . . . .  12
  4.1.  Successful Bearer Token Exchange  . . . . . . . . . . . .  12
  4.2.  Successful OAuth 1.0a Token Exchange  . . . . . . . . . .  13
  4.3.  Failed Exchange . . . . . . . . . . . . . . . . . . . . .  14
  4.4.  SMTP Example of a Failed Negotiation  . . . . . . . . . .  15
5.  Security Considerations . . . . . . . . . . . . . . . . . . .  16
6.  Internationalization Considerations . . . . . . . . . . . . .  17
7.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  18
  7.1.  SASL Registration . . . . . . . . . . . . . . . . . . . .  18
8.  References  . . . . . . . . . . . . . . . . . . . . . . . . .  19
  8.1.  Normative References  . . . . . . . . . . . . . . . . . .  19
  8.2.  Informative References  . . . . . . . . . . . . . . . . .  20
Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . .  21
Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  21

1. Introduction ✨

OAuth 1.0a [RFC5849] and OAuth 2.0 [RFC6749] are protocol frameworks that let a third-party app get limited access to a protected resource 🌈 either by running an approval interaction on behalf of a resource owner, or by letting the third-party app get access on its own behalf.

The core OAuth 2.0 spec [RFC6749] covers the interaction between the OAuth client and the authorization server. It does not define how the OAuth client talks to the resource server to access a protected resource with an access token πŸ™ˆ That client-to-resource-server part lives in separate specs, like the bearer token spec [RFC6750]. OAuth 1.0a includes its own protocol spec for the conversation between the OAuth client and the resource server, in [RFC5849].

The main use cases for OAuth 1.0a and OAuth 2.0 have mostly focused on HTTP-based [RFC7230] environments so far. This document brings OAuth 1.0a and OAuth 2.0 into non-HTTP-based apps by plugging into the Simple Authentication and Security Layer (SASL) [RFC4422]. So it takes advantage of OAuth and the deployment base it already has, to let you use SASL to get to resources over non-HTTP-based protocols, like the Internet Message Access Protocol (IMAP) [RFC3501] and the Simple Mail Transfer Protocol (SMTP) [RFC5321]. This document gives examples in IMAP and SMTP πŸ’Œ

To show how this spec affects an OAuth-enabled app setup, Figure 1 shows the abstract message flow of OAuth 2.0 [RFC6749]. As the figure shows, this document changes the messages (E) and (F), since SASL is used between the client and the resource server instead of HTTP πŸ’…

                                                              ----+
   +--------+                                  +---------------+  |
   |        |--(A)-- Authorization Request --->|   Resource    |  |
   |        |                                  |    Owner      |  |Plain
   |        |<-(B)------ Access Grant ---------|               |  |OAuth
   |        |                                  +---------------+  |2.0
   |        |                                                     |
   |        |         Client Credentials &     +---------------+  |
   |        |--(C)------ Access Grant -------->| Authorization |  |
   | Client |                                  |    Server     |  |
   |        |<-(D)------ Access Token ---------|               |  |
   |        |      (w/ Optional Refresh Token) +---------------+  |
   |        |                                                 ----+
   |        |                                                 ----+
   |        |                                  +---------------+  |
   |        |                                  |               |  |OAuth
   |        |--(E)------ Access Token -------->|   Resource    |  |over
   |        |                                  |    Server     |  |SASL
   |        |<-(F)---- Protected Resource -----|               |  |
   |        |                                  |               |  |
   +--------+                                  +---------------+  |
                                                              ----+

                     Figure 1: OAuth 2.0 Protocol Flow

SASL is a framework that gives you authentication and data security services in connection-oriented protocols, using replaceable authentication mechanisms πŸ” It sets up a structured interface between protocols and mechanisms. This means new protocols can reuse existing authentication mechanisms, and old protocols can use new ones. The framework also has a protocol for securing later exchanges within a data security layer 🫢

When OAuth gets plugged into SASL, the high-level steps go like this:

  • (A) The client requests authorization from the resource owner. The authorization request can go straight to the resource owner (as shown) or indirectly through the authorization server as an intermediary πŸ“¨
  • (B) The client receives an authorization grant, which is a credential representing the resource owner's authorization. It's expressed using one of the grant types defined in [RFC6749] or [RFC5849], or using an extension grant type. The grant type depends on how the client asked for authorization and which types the authorization server supports 🎟️
  • (C) The client requests an access token by authenticating with the authorization server and presenting the authorization grant πŸ™‹β€β™€οΈ
  • (D) The authorization server authenticates the client and validates the authorization grant. If it's valid, the server issues an access token βœ…
  • (E) The client requests the protected resource from the resource server and authenticates by presenting the access token πŸšͺ
  • (F) The resource server validates the access token. If it's valid, it indicates a successful authentication πŸŽ‰

Okay so steps (E) and (F) aren't defined in [RFC6749] (they're described in, for example, [RFC6750] for the OAuth bearer token instead). They're the main stuff this document specifies! So the message exchange in Figure 1 is the result of this spec πŸ¦‹ The client will usually need to figure out the authentication endpoints (and maybe the service endpoints) before the OAuth 2.0 messages in steps (A)-(D) happen. Discovering the resource owner, the authorization server endpoints, and client registration are all outside the scope of this spec. The client must discover the authorization endpoints using a discovery mechanism like OpenID Connect Discovery (OIDCD) [OpenID.Discovery] or WebFinger using host-meta [RFC7033]. Once the client has its credentials, it moves on to steps (E) and (F) defined in this spec πŸ—οΈ Authorization endpoints MAY require client registration, and generic clients SHOULD support the Dynamic Client Registration protocol [RFC7591] πŸ’œ

OAuth 1.0a follows a similar model, but it uses different terminology and doesn't separate the resource server from the authorization server 🌸

2. Terminology πŸ“–

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 [RFC2119]. Yes, that's the official BCP 14 vibe πŸ’…

The reader is assumed to already know the terms used in the OAuth 2.0 spec [RFC6749] and SASL [RFC4422]. So if you're lost, go re-read those first 🧚

In examples, "C:" and "S:" mark lines sent by the client and server, respectively. Line breaks have been added for readability πŸ“

Note that the IMAP SASL spec requires base64 encoding, as specified in Section 4 of [RFC4648]. Don't skip this one, bestie 🫢

3. OAuth SASL Mechanism Specifications ✨

okay so SASL is basically the authentication toolkit that a bunch of application-layer protocols reach for 🧰 this doc defines the SASL mechanisms you use with OAuth, and there are two of them:

  • OAUTHBEARER: OAuth 2.0 bearer tokens, as described in [RFC6750]. RFC 6750 uses Transport Layer Security (TLS) [RFC5246] to secure the protocol interaction between the client and the resource server πŸ”
  • OAUTH10A: OAuth 1.0a Message Authentication Code (MAC) tokens (using the HMAC-SHA1 keyed message digest), as described in Section 3.4.2 of [RFC5849] 🧁

new OAuth Access Token Types can be added later through extensions. a new SASL OAuth mechanism gets added by registering its new name(s) with IANA in the SASL Mechanisms registry, and citing this spec for the rest of the definition πŸ“

⚠️ bestie, read this part carefully. SASL mechanisms built on this document do NOT give you a data security layer. after the initial authentication, they can't provide integrity or confidentiality protection for application messages. if you need that protection, use TLS or something similar. and for these two mechanisms, TLS MUST be used with OAUTHBEARER to protect the bearer token. for OAUTH10A, TLS is RECOMMENDED. πŸ’€

these mechanisms are client initiated and lockstep, which means the server always replies to a client message 🀝 when the client has a valid token and uses it correctly, the flow goes like this:

  1. Client sends a valid and correct initial client response.
  2. Server responds with a successful authentication.

when authentication fails, the server sends an error result, and then the client MUST send one more message so the server can finish the exchange 😀 some protocols and common SASL implementations can't do both sending a SASL message and finalizing a SASL negotiation, and that extra client message is the fix for exactly that problem. the failure exchange looks like this:

  1. Client sends an invalid initial client response.
  2. Server responds with an error message.
  3. Client sends a dummy client response.
  4. Server fails the authentication.

3.1. Initial Client Response

okay the client response is a GS2 [RFC5801] header followed by zero or more key/value pairs, or it can be empty πŸŽ€ the gs2-header rule is only here as a placeholder, so things stay compatible with GS2 if a GS2 mechanism ever gets formally defined. this doc doesn't define one though. the key/value pairs take the spot of the matching HTTP headers and values, carrying the info needed to finish an OAuth-style HTTP authorization. unknown key/value pairs MUST be ignored by the server, so the server just skips anything it doesn't recognise πŸ™ƒ here's the ABNF [RFC5234] syntax:

kvsep          = %x01
key            = 1*(ALPHA)
value          = *(VCHAR / SP / HTAB / CR / LF )
kvpair         = key "=" value kvsep
;;gs2-header     = See RFC 5801
client-resp    = (gs2-header kvsep *kvpair kvsep) / kvsep

the GS2 header MAY include the username tied to the resource being accessed, which is the authzid πŸ‘‘ it's worth knowing that application protocols are allowed to require an authzid, and so are specific server implementations.

a client response that's only a single kvsep is used only when authentication fails, and it's only valid in that context πŸ™ˆ if it shows up as the very first message from the client, the server MAY just fail the authentication without sending back discovery info, since there's no user or server name indication to work with.

these are the keys and values defined in the client response:

  • auth (REQUIRED): the payload that would sit in the HTTP Authorization header if this OAuth exchange were happening over HTTP πŸ’–
  • host: the hostname the client connected to. in an HTTP context, this is the value of the HTTP Host header.
  • port: the destination port the client connected to, written as a decimal positive integer string with no leading zeros.

for OAuth token types like OAuth 1.0a that use keyed message digests, the client MUST send the host and port key/values. and the server MUST fail any authorization request that needs keyed message digests but doesn't come with host and port values. 🚫 in OAuth 1.0a, for example, the "signature base string calculation" includes the reconstructed HTTP URL, so those values really matter.

3.1.1. Reserved Key/Values

in these mechanisms, the path, query string and post body get default values 🧩 OAuth authorization schemes MAY define usage of these in the SASL context and extend this spec. for OAuth Access Token Types that include a keyed message digest of the request, the default values MUST be used unless explicit values are given in the client response. these key values are reserved for future use:

  • mthd (RESERVED): HTTP method; the default value is "POST".
  • path (RESERVED): HTTP path data; the default value is "/".
  • post (RESERVED): HTTP post data; the default value is the empty string ("").
  • qs (RESERVED): the HTTP query string; the default value is the empty string ("").

3.2. Server's Response

the server checks the response against the spec for whichever OAuth Access Token Type is being used πŸ” if that token type uses a keyed message digest of the request parameters, the client must send a client response that meets the data requirements for the scheme in use.

the server fully validates the client response before it generates a server response πŸ›‘οΈ that includes the validation steps listed in the spec for the OAuth Access Token Type in use. there might be extra validation steps too, depending on which application protocol is using SASL. especially, values sent as kvpairs in the client response (like host and port) that match values the application server already knows by another route (like an application protocol data unit or preconfigured values) MUST be checked to match between the initial client response and those other sources. for example, when SASL runs over IMAP to an IMAP server for a single domain, the hostname can come from configuration, and that hostname must be checked to match the value sent in the 'host' kvpair πŸ•΅οΈβ€β™€οΈ

the server completes the SASL negotiation when the client message checks out βœ… the authenticated identity the SASL mechanism reports is the identity securely established for the client with the OAuth credential. the application (not the SASL mechanism) decides, based on its local access policy, whether that identity is allowed to reach the requested resource πŸšͺ also, the authzid's semantics are specified by the SASL framework [RFC4422].

3.2.1. OAuth Identifiers in the SASL Context

in the OAuth framework, the client may be authenticated by the authorization server, and the resource owner is authenticated to the authorization server 🌸 OAuth access tokens may contain info about how the resource owner and the client were authenticated, so they can make that info available to the resource server.

if an application needs both identifiers, the developer has to provide a way to pass them from the SASL mechanism back up to the application 🧚

3.2.2. Server Response to Failed Authentication

when authentication fails, the server sends back an error result in JSON [RFC7159] format and fails the authentication πŸ’… the error result has these values:

  • status (REQUIRED): the authorization error code. valid error codes are defined in the IANA "OAuth Extensions Error Registry", as specified in the OAuth 2.0 core specification.
  • scope (OPTIONAL): an OAuth scope that's valid for accessing the service. this can be left out, which implies that unscoped tokens are required. if a scope is given, a single scope is preferred. at the time this doc was written, several implementations didn't properly support space-separated lists of scopes, so using a space-separated list of scopes is NOT RECOMMENDED πŸ™…β€β™€οΈ
  • openid-configuration (OPTIONAL): the URL for a document that follows the OpenID Provider Configuration Information schema described in OIDCD [OpenID.Discovery], Section 3, and that's right for the user. as OIDCD specifies, this will have the "https" URL scheme. this document MUST have all OAuth-related data elements populated. the server MAY return different URLs for users in different domains, and the client SHOULD NOT cache a single returned value and assume it applies to all users and domains the server supports. the returned discovery document SHOULD have all the data elements the OpenID Connect Discovery specification requires. also, the discovery document SHOULD contain the 'registration_endpoint' element, which identifies the endpoint for the Dynamic Client Registration protocol [RFC7591], so you can get the minimum number of parameters the OAuth exchange needs to work πŸ—ΊοΈ another comparable discovery or client registration mechanism MAY be used if one is available.

using the 'offline_access' scope, as defined in [OpenID.Core], is RECOMMENDED so clients can explicitly ask for a refresh token πŸ”

if the resource server provides a scope, the client MUST always request scoped tokens from the token endpoint 🎯 if the resource server doesn't return a scope, the client SHOULD presume an unscoped token is needed to access the resource.

clients might talk to a bunch of application servers, like email servers and Extensible Messaging and Presence Protocol (XMPP) [RFC6120] servers, so they need a way to figure out whether dynamic client registration has already been done 🌈 they also need to know whether an existing refresh token can be reused to get an access token for the resource server they want. this spec recommends that a client uses the info in the 'iss' element defined in OpenID Connect Core [OpenID.Core] to make that call πŸ’œ

3.2.3. Completing an Error Message Sequence

Section 3.6 of SASL [RFC4422] explicitly forbids additional info in an unsuccessful authentication outcome πŸ™… so the error message gets sent as a normal message. then the client MUST send either an additional client response made of a single %x01 (control A) character, so the server can finish the exchange, or a SASL abort message as generally defined in Section 3.5 of SASL [RFC4422]. a specific example of an abort message is the "BAD" response to an AUTHENTICATE in IMAP [RFC3501], Section 6.2.2 🧁

3.3. OAuth Access Token Types using Keyed Message Digests ✨

okay so OAuth access token types can use keyed message digests πŸ”, which means the client and the resource server might have to do a cryptographic computation for integrity protection and data origin authentication. it's giving security nerd energy and i'm obsessed πŸ’œ

here's the tea: OAuth is built for getting access to resources that are identified by URIs 🌐. SASL is built for user authentication and has zero facility for fine-grained access control πŸ™ˆ so in this spec, we require or define default values for the data elements from an HTTP request so the signature base string can be built properly. the default HTTP path is "/", and the default post body is empty πŸŽ€. these atoms are defined as extension points, so nothing has to change if a future revision of SASL supports more specific resource authorization, like IMAP access to a specific folder or FTP access limited to a specific directory πŸ“βœ¨

using the example from the OAuth 1.0a specification as a starting point, here's the authorization request in OAuth 1.0a style (with %x01 shown as ^A and line breaks added so it's readable), assuming it's on an IMAP server running on port 143 πŸ¦‹

n,a=user@example.com,^A
host=example.com^A
port=143^A
auth=OAuth realm="Example",
           oauth_consumer_key="9djdj82h48djs9d2",
           oauth_token="kkk9d7dh3k39sjv7",
           oauth_signature_method="HMAC-SHA1",
           oauth_timestamp="137131201",
           oauth_nonce="7d8f3e4a",
           oauth_signature="Tm90IGEgcmVhbCBzaWduYXR1cmU"^A^A

the signature base string gets built per the OAuth 1.0a specification [RFC5849], with a few things noted:

  • the method value is defaulted to POST πŸ’…
  • the scheme defaults to "http", and any port number other than 80 is included 🌸
  • the path defaults to "/" πŸ“
  • the query string defaults to "" 🧚

in this example, the signature base string (with line breaks added for readability) would be:

POST&http%3A%2F%2Fexample.com:143%2F&oauth_consumer_key%3D9djdj82h4
8djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_method%3DHMAC-SH
A1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk9d7dh3k39sjv7

4. Examples πŸŽ€

these examples show exchanges between IMAP and SMTP clients and servers πŸ’Œ all the IMAP examples use SASL-IR [RFC4959] and send the payload in the initial client response. the bearer token examples assume encrypted transport. if the underlying connection isn't already TLS, then STARTTLS MUST be used, because TLS is required in the bearer token specification πŸ”’

note to implementers: the SASL OAuth method names are case insensitive 🫢 one example uses "Bearer", but that could just as easily be "bearer", "BEARER", or "BeArEr". iconic behaviour from the whole method name family πŸ’…

4.1. Successful Bearer Token Exchange ✨

this example shows a successful OAuth 2.0 bearer token exchange in IMAP 🌈 line breaks are inserted for readability.

[Initial connection and TLS establishment...]
S: * OK IMAP4rev1 Server Ready
C: t0 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=OAUTHBEARER SASL-IR
S: t0 OK Completed
C: t1 AUTHENTICATE OAUTHBEARER bixhPXVzZXJAZXhhbXBsZS5jb20sAWhv
      c3Q9c2VydmVyLmV4YW1wbGUuY29tAXBvcnQ9MTQzAWF1dGg9QmVhcmVyI
      HZGOWRmdDRxbVRjMk52YjNSbGNrQmhiSFJoZG1semRHRXVZMjl0Q2c9PQ
      EB
S: t1 OK SASL authentication succeeded

as required by IMAP [RFC3501], the payloads are base64 encoded πŸ“ the decoded initial client response (with %x01 shown as ^A and long lines wrapped for readability) is:

n,a=user@example.com,^Ahost=server.example.com^Aport=143^A
auth=Bearer vF9dft4qmTc2Nvb3RlckBhbHRhdmlzdGEuY29tCg==^A^A

the same credential used in an SMTP exchange is shown below πŸ“¨ again, this one assumes TLS is already established, per the bearer token spec requirements.

[connection begins]
S: 220 mx.example.com ESMTP 12sm2095603fks.9
C: EHLO sender.example.com
S: 250-mx.example.com at your service,[172.31.135.47]
S: 250-SIZE 35651584
S: 250-8BITMIME
S: 250-AUTH LOGIN PLAIN OAUTHBEARER
S: 250-ENHANCEDSTATUSCODES
S: 250-STARTTLS
S: 250 PIPELINING
[Negotiate TLS...]
C: t1 AUTH OAUTHBEARER bixhPXVzZXJAZXhhbXBsZS5jb20sAWhvc3Q9c2Vy
      dmVyLmV4YW1wbGUuY29tAXBvcnQ9NTg3AWF1dGg9QmVhcmVyIHZGOWRmd
      DRxbVRjMk52YjNSbGNrQmhiSFJoZG1semRHRXVZMjl0Q2c9PQEB
S: 235 Authentication successful.
[connection continues...]

the decoded initial client response is:

n,a=user@example.com,^Ahost=server.example.com^Aport=587^A
auth=Bearer vF9dft4qmTc2Nvb3RlckBhbHRhdmlzdGEuY29tCg==^A^A

4.2. Successful OAuth 1.0a Token Exchange πŸ¦‹

this IMAP example shows a successful OAuth 1.0a token exchange πŸ’– line breaks are inserted for readability. this example assumes TLS is already established. signature computation is discussed in Section 3.3.

S: * OK IMAP4rev1 Server Ready
C: t0 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=OAUTHBEARER AUTH=OAUTH10A SASL-IR
S: t0 OK Completed
C: t1 AUTHENTICATE OAUTH10A bixhPXVzZXJAZXhhbXBsZS5jb20sAWhvc3Q9ZXhhb
      XBsZS5jb20BcG9ydD0xNDMBYXV0aD1PQXV0aCByZWFsbT0iRXhhbXBsZSIsb2F1
      dGhfY29uc3VtZXJfa2V5PSI5ZGpkajgyaDQ4ZGpzOWQyIixvYXV0aF90b2tlbj0
      ia2trOWQ3ZGgzazM5c2p2NyIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy
      1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNzEzMTIwMSIsb2F1dGhfbm9uY2U9I
      jdkOGYzZTRhIixvYXV0aF9zaWduYXR1cmU9IlRtOTBJR0VnY21WaGJDQnphV2R1
      WVhSMWNtVSUzRCIBAQ==
S: t1 OK SASL authentication succeeded

as required by IMAP [RFC3501], the payloads are base64 encoded 🌸 the decoded initial client response (with %x01 shown as ^A and lines wrapped for readability) is:

n,a=user@example.com,^A
host=example.com^A
port=143^A
auth=OAuth realm="Example",
           oauth_consumer_key="9djdj82h48djs9d2",
           oauth_token="kkk9d7dh3k39sjv7",
           oauth_signature_method="HMAC-SHA1",
           oauth_timestamp="137131201",
           oauth_nonce="7d8f3e4a",
           oauth_signature="SSdtIGEgbGl0dGxlIHRlYSBwb3Qu"^A^A

4.3. Failed Exchange πŸ™ˆ

this IMAP example shows a failed exchange because of the empty Authorization header, which is how a client can query for the scope it needs 🧚 line breaks are inserted for readability.

S: * OK IMAP4rev1 Server Ready
C: t0 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=OAUTHBEARER SASL-IR
S: t0 OK Completed
C: t1 AUTHENTICATE OAUTHBEARER bixhPXVzZXJAZXhhbXBsZS5jb20sAW
      hvc3Q9c2VydmVyLmV4YW1wbGUuY29tAXBvcnQ9MTQzAWF1dGg9AQE=
S: + eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxl
     X3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4
     YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9u
     In0=
C: AQ==
S: t1 NO SASL authentication failed

the decoded initial client response is:

n,a=user@example.com,^Ahost=server.example.com^A
port=143^Aauth=^A^A

the decoded server error response is:

{
"status":"invalid_token",
"scope":"example_scope",
"openid-configuration":"https://example.com/.well-known/openid-config"
}

the client responds with the required dummy response. "AQ==" is the base64 encoding of the ASCII value 0x01 πŸ€“ the same exchange using the IMAP-specific method of canceling an AUTHENTICATE command sends "*", and it's shown below.

S: * OK IMAP4rev1 Server Ready
C: t0 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=OAUTHBEARER SASL-IR IMAP4rev1
S: t0 OK Completed
C: t1 AUTHENTICATE OAUTHBEARER bixhPXVzZXJAZXhhbXBsZS5jb20sAW
     hvc3Q9c2VydmVyLmV4YW1wbGUuY29tAXBvcnQ9MTQzAWF1dGg9AQE=
S: + eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NvcGUiOiJleGFtcGxl
     X3Njb3BlIiwib3BlbmlkLWNvbmZpZ3VyYXRpb24iOiJodHRwczovL2V4
     YW1wbGUuY29tLy53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9u
     In0=
C: *
S: t1 NO SASL authentication failed

4.4. SMTP Example of a Failed Negotiation πŸ’€

this example shows an authorization failure in an SMTP exchange 😭 TLS negotiation isn't shown, but as noted above, it's required for the use of bearer tokens πŸ”

[connection begins]
S: 220 mx.example.com ESMTP 12sm2095603fks.9
C: EHLO sender.example.com
S: 250-mx.example.com at your service,[172.31.135.47]
S: 250-SIZE 35651584
S: 250-8BITMIME
S: 250-AUTH LOGIN PLAIN OAUTHBEARER
S: 250-ENHANCEDSTATUSCODES
S: 250 PIPELINING
[Negotiate TLS...]
C: AUTH OAUTHBEARER bix1c2VyPXNvbWV1c2VyQGV4YW1wbGUuY29tLAFhdXRoPUJlYXJl
       ciB2RjlkZnQ0cW1UYzJOdmIzUmxja0JoZEhSaGRtbHpkR0V1WTI5dENnPT0BAQ==
S: 334 eyJzdGF0dXMiOiJpbnZhbGlkX3Rva2VuIiwic2NoZW1lcyI6ImJlYXJlciBtYWMiL
       CJzY29wZSI6Imh0dHBzOi8vbWFpbC5leGFtcGxlLmNvbS8ifQ==
C: AQ==
S: 535-5.7.1 Username and Password not accepted. Learn more at
S: 535 5.7.1 http://support.example.com/mail/oauth
[connection continues...]

the initial client response is:

n,user=someuser@example.com,^A
auth=Bearer vF9dft4qmTc2Nvb3RlckBhdHRhdmlzdGEuY29tCg==^A^A

the server returned an error message in the 334 SASL message 🚨 the client responds with the required dummy response, and then the server finalizes the negotiation.

{
    "status":"invalid_token",
    "schemes":"bearer mac",
    "scope":"https://mail.example.com/"
}

5. Security Considerations πŸ”₯

okay bestie, this is the part where we talk about what can go wrong 😭. OAuth 1.0a and OAuth 2.0 can be deployed in a bunch of different ways, and the security properties change depending on the profile. As shown in Figure 1, this spec is meant to slot into a bigger OAuth setup. So app developers need to do a threat assessment for their own situation before picking a SASL OAuth mechanism. For OAuth 2.0, the detailed security doc [RFC6819] helps you choose which OAuth 2.0 pieces actually mitigate the threats in your deployment. For OAuth 1.0a, Section 4 of [RFC5849] has the OAuth 1.0a-specific guidance. 🧠

This document specifies two SASL Mechanisms for OAuth, and each one comes with its own security vibe πŸ’….

OAUTHBEARER: This one borrows from OAuth 2.0 bearer tokens [RFC6750]. It depends on the application using TLS to protect the OAuth 2.0 bearer token exchange. Without TLS at the application layer, this method is completely insecure πŸ’€. So TLS MUST be provided by the application when you choose this authentication mechanism. non-negotiable, periodt πŸ”’.

OAUTH10A: This one reuses OAuth 1.0a MAC tokens (using the HMAC-SHA1 keyed message digest), as described in Section 3.4.2 of [RFC5849]. To compute the keyed message digest the same way as in RFC 5839, this spec sends some extra parameters between the client and the server. This SASL mechanism only supports client authentication. If you want server-side authentication, the application underneath the SASL layer must provide it. Using TLS is strongly RECOMMENDED 🫢.

Also, a few more things are worth pointing out πŸ‘€:

An access token is not equivalent to the user's long term password. Be careful when these OAuth credentials are used for things like changing passwords (which some protocols allow, e.g., XMPP [RFC6120]). The resource server should make sure that actions taken on the authenticated channel match the strength of the credential that was presented. not everything should be unlocked by a token, bestie πŸ™…β€β™€οΈ.

Lifetime of the application sessions. SASL might be used to authenticate a connection, and that connection can outlive the access token that opened it. This is a common problem in application protocols with long-lived connections, and it isn't really a problem with this mechanism per se πŸ€·β€β™€οΈ. Resource servers may unilaterally disconnect clients in accordance with the application protocol.

Access tokens have a lifetime. Shorter token lifetimes give you real security benefits ✨. OAuth 2.0 brings in refresh tokens so clients can grab new access tokens on the fly without any human interaction. Also, a previously obtained access token might be revoked or made invalid at any time, so don't assume it's forever πŸ₯². The client MAY request a new access token for each connection to a resource server, but it SHOULD cache and reuse valid credentials. That's the efficient glow-up 🌸.


6. Internationalization Considerations 🌈

The identifier that the OAuth authorization server asserts about the resource owner inside the access token may get shown to a human πŸ‘©β€πŸ’». For example, when SASL is used with IMAP, the client may assert the resource owner's email address to the IMAP server for use in an email-based app πŸ“§. That means the identifier may have internationalized characters, so an application needs to make sure the mapping between the OAuth-provided identifier and the application-layer protocol SASL is part of is actually suitable 🌍. One SASL-compatible container example is the JSON Web Token (JWT) [RFC7519]. It gives you a standardized format for exchanging authorization and identity info, and it supports internationalized characters πŸ’œ.


7. IANA Considerations πŸ¦‹

7.1. SASL Registration

IANA has registered the following entry in the SASL Mechanisms registry ✨:

SASL mechanism name: OAUTHBEARER

Security Considerations: See this document

Published Specification: See this document

For further information: Contact the authors of this document.

Intended usage: COMMON

Owner/Change controller: the IESG

Note: None

IANA has also registered this entry in the SASL Mechanisms registry πŸŽ€:

SASL mechanism name: OAUTH10A

Security Considerations: See this document

Published Specification: See this document

For further information: Contact the authors of this document.

Intended usage: COMMON

Owner/Change controller: the IESG

Note: None

8. References πŸ“š

8.1. Normative References

8.2. Informative References


Acknowledgements 🫢

The authors want to thank the members of the KITTEN working group πŸ’–, and especially these people: Simon Josefson, Torsten Lodderstadt, Ryan Troll, Alexey Melnikov, Jeffrey Hutzelman, Nico Williams, Matt Miller, and Benjamin Kaduk 🌷.

This document was produced under the chairmanship of Alexey Melnikov, Tom Yu, Shawn Emery, Josh Howlett, Sam Hartman, Matthew Miller, and Benjamin Kaduk. The supervising Area Director was Stephen Farrell πŸ‘‘.

Authors' Addresses πŸ’œ

William Mills
Microsoft

Email: wmills_92105@yahoo.com


Tim Showalter

Email: tjs@psaux.com


Hannes Tschofenig
ARM Ltd.
110 Fulbourn Rd
Cambridge  CB1 9NJ
United Kingdom

Email: Hannes.tschofenig@gmx.net
URI:   http://www.tschofenig.priv.at

That's the whole thing, bestie 🌈✨ RFC 7628 is a wrap!

πŸ“¦ where this page comes from