RFC 5849

The OAuth 1.0 Protocol

๐Ÿ“… published April 2010, from ietf

RFC 5849: The OAuth 1.0 Protocol ๐ŸŽ€

Okay bestie, first things first, the paperwork. This is an IETF RFC, number 5849, written by E. Hammer-Lahav, Ed. and dated April 2010. It's filed as Informational ๐Ÿ“„, so it's a "here's how this works" doc and not a mandatory Internet Standards Track spec. The ISSN is 2070-1721. Its header doesn't list anything it obsoletes or updates, so it just stands on its own ๐Ÿ’…


Internet Engineering Task Force (IETF)              E. Hammer-Lahav, Ed.
Request for Comments: 5849                                    April 2010
Category: Informational
ISSN: 2070-1721

Abstract โœจ

OAuth lets clients get into server resources on behalf of a resource owner (like a different client or an end-user) ๐Ÿ”‘ It also gives end-users a way to let third parties into their server resources without handing over their credentials, which is usually a username and password pair. It does this with user-agent redirections. Iconic behaviour, honestly ๐Ÿ˜ญ

Status of This Memo โœจ

This document is not an Internet Standards Track specification. It's published for informational purposes ๐Ÿฆ‹

It's a product of the Internet Engineering Task Force (IETF) and represents consensus from the IETF community. It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG). Not every document the IESG approves is a candidate for any level of Internet Standard, so check Section 2 of RFC 5741 if you want the details ๐Ÿง

For the current status of this document, any errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc5849 ๐ŸŒธ

Copyright (c) 2010 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 they stood on the publication date. Please actually read these, because they spell out your rights and restrictions for this document ๐Ÿ‘€ Code components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as the Simplified BSD License describes ๐Ÿซถ


Table of Contents ๐Ÿ—บ๏ธ

   1. Introduction ....................................................3
      1.1. Terminology ................................................4
      1.2. Example ....................................................5
      1.3. Notational Conventions .....................................7
   2. Redirection-Based Authorization .................................8
      2.1. Temporary Credentials ......................................9
      2.2. Resource Owner Authorization ..............................10
      2.3. Token Credentials .........................................12
   3. Authenticated Requests .........................................14
      3.1. Making Requests ...........................................14
      3.2. Verifying Requests ........................................16
      3.3. Nonce and Timestamp .......................................17
      3.4. Signature .................................................18
           3.4.1. Signature Base String ..............................18
           3.4.2. HMAC-SHA1 ..........................................25
           3.4.3. RSA-SHA1 ...........................................25
           3.4.4. PLAINTEXT ..........................................26
      3.5. Parameter Transmission ....................................26
           3.5.1. Authorization Header ...............................27
           3.5.2. Form-Encoded Body ..................................28
           3.5.3. Request URI Query ..................................28
      3.6. Percent Encoding ..........................................29
   4. Security Considerations ........................................29
      4.1. RSA-SHA1 Signature Method .................................29
      4.2. Confidentiality of Requests ...............................30
      4.3. Spoofing by Counterfeit Servers ...........................30
      4.4. Proxying and Caching of Authenticated Content .............30
      4.5. Plaintext Storage of Credentials ..........................30
      4.6. Secrecy of the Client Credentials .........................31
      4.7. Phishing Attacks ..........................................31
      4.8. Scoping of Access Requests ................................31
      4.9. Entropy of Secrets ........................................32
      4.10. Denial-of-Service / Resource-Exhaustion Attacks ..........32
      4.11. SHA-1 Cryptographic Attacks ..............................33
      4.12. Signature Base String Limitations ........................33
      4.13. Cross-Site Request Forgery (CSRF) ........................33
      4.14. User Interface Redress ...................................34
      4.15. Automatic Processing of Repeat Authorizations ............34
   5. Acknowledgments ................................................35
   Appendix A.  Differences from the Community Edition ...............36
   6. References .....................................................37
      6.1. Normative References ......................................37
      6.2. Informative References ....................................38

1. Introduction ๐ŸŒˆ

OAuth started out as a small crew of web developers from a bunch of different websites and internet services. They wanted to fix a very common problem: letting someone else use protected resources without giving away the keys ๐Ÿ—๏ธ That version was stabilised at version 1.0 in October 2007, then revised in June 2009 as Revision A, which you can find at <http://oauth.net/core/1.0a> โœจ

This specification is an informational write-up of OAuth Core 1.0 Revision A. It also fixes several errata reported since then and makes a bunch of editorial clarifications ๐Ÿงน It isn't an item from the IETF's OAuth Working Group. That group, at the time of writing, was working on an OAuth version that could be suitable for the standards track. Instead, the authors of the original work transferred this one to the IETF for change control ๐Ÿฆ‹

In the traditional client-server authentication model, the client uses its own credentials to access its own resources hosted on the server. But with distributed web services and cloud computing blowing up, third-party apps now need access to those server-hosted resources too ๐ŸŒ

OAuth adds a third role to that traditional model: the resource owner ๐Ÿ‘‘ In OAuth, the client isn't the resource owner. It's acting on the owner's behalf, requesting access to resources the owner controls but the server hosts. OAuth also lets the server check not only that the resource owner authorised the access, but also who the client making the request actually is ๐Ÿซถ

OAuth gives clients a way to access server resources on behalf of a resource owner (like a different client or an end-user). It also gives end-users a process for authorising third-party access to their server resources without sharing their credentials (usually a username and password pair), using user-agent redirections ๐Ÿ’–

Here's an example. A web user (the resource owner) wants a printing service (the client) to print her private photos, which are stored at a photo sharing service (the server). She doesn't have to share her username and password with the printing service. Instead, she logs in directly with the photo sharing service, which hands the printing service delegation-specific credentials ๐Ÿ“ธโœจ

Before the client can touch any resources, it has to get permission from the resource owner first. That permission comes in the form of a token and a matching shared secret ๐ŸŽŸ๏ธ The token exists so the resource owner never has to give the client their actual credentials. Unlike resource owner credentials, tokens can be issued with a restricted scope and a limited lifetime, and they can be revoked independently ๐Ÿ”ฅ

This specification has two parts. The first defines a redirection-based user-agent process where end-users authorise client access to their resources. They authenticate directly with the server, and the server provisions tokens to the client for use with the authentication method ๐Ÿฆ‹ The second part defines how to make authenticated HTTP [RFC2616] requests using two sets of credentials: one identifies the client making the request, and the other identifies the resource owner the request is being made for ๐Ÿ’…

OAuth with any transport protocol other than [RFC2616] is undefined. So, HTTP only, babe ๐Ÿ™ˆ

1.1. Terminology ๐Ÿ“š

client : An HTTP client (per [RFC2616]) that can make OAuth-authenticated requests (Section 3) ๐Ÿ’œ

server : An HTTP server (per [RFC2616]) that can accept OAuth-authenticated requests (Section 3) ๐ŸŒธ

protected resource : An access-restricted resource that you can get from the server using an OAuth-authenticated request (Section 3) ๐Ÿ”’

resource owner : An entity that can access and control protected resources by using credentials to authenticate with the server ๐Ÿ‘‘

credentials : Credentials are a pair of a unique identifier and a matching shared secret. OAuth defines three classes of credentials: client, temporary, and token. They're used to identify and authenticate the client making the request, the authorization request, and the access grant, respectively ๐Ÿงพ

token : A unique identifier issued by the server. The client uses it to link authenticated requests to the resource owner whose authorization the client has requested or already obtained. Tokens have a matching shared secret, which the client uses to prove it owns the token and that it has authority to represent the resource owner ๐ŸŽ€

The original community specification used slightly different terminology, which maps to this specification like so (original community terms on the left) ๐Ÿ“

  • Consumer: client
  • Service Provider: server
  • User: resource owner
  • Consumer Key and Secret: client credentials
  • Request Token and Secret: temporary credentials
  • Access Token and Secret: token credentials

1.2. Example โœจ

Okay so picture this, bestie ๐Ÿฆ‹. Jane (the resource owner) just uploaded a bunch of private vacation photos (the protected resources) to her photo sharing site, 'photos.example.net' (the server). ๐ŸŒธ She wants to use the 'printer.example.com' website (the client) to print one of them. Normally she'd just sign into 'photos.example.net' with her username and password.

BUT Jane is NOT about to hand her password to 'printer.example.com' ๐Ÿ™…โ€โ™€๏ธ, and that website needs to access the photo in order to print it. So to give its users a smoother experience, 'printer.example.com' signed up for a set of 'photos.example.net' client credentials ahead of time ๐Ÿ’…:

Client Identifier
         dpf43f3p2l4k3l03

Client Shared-Secret:
         kd94hf93k423kf44

The 'printer.example.com' website also set up its app to use the protocol endpoints listed in the 'photos.example.net' API documentation, which use the "HMAC-SHA1" signature method ๐Ÿ”:

Temporary Credential Request
         https://photos.example.net/initiate

Resource Owner Authorization URI:
         https://photos.example.net/authorize

Token Request URI:
         https://photos.example.net/token

Before 'printer.example.com' can ask Jane to grant access to her photos, it has to first get a set of temporary credentials from 'photos.example.net' to identify the delegation request ๐Ÿงš. To do that, the client sends this HTTPS [RFC2818] request to the server:

  POST /initiate HTTP/1.1
  Host: photos.example.net
  Authorization: OAuth realm="Photos",
     oauth_consumer_key="dpf43f3p2l4k3l03",
     oauth_signature_method="HMAC-SHA1",
     oauth_timestamp="137131200",
     oauth_nonce="wIjqoS",
     oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready",
     oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D"

The server checks the request and replies with temporary credentials in the body of the HTTP response (line breaks are just for display ๐Ÿ’–):

  HTTP/1.1 200 OK
  Content-Type: application/x-www-form-urlencoded

  oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&
  oauth_callback_confirmed=true

Next, the client redirects Jane's user-agent to the server's Resource Owner Authorization endpoint so Jane can approve access to her private photos ๐ŸŒˆ:

  https://photos.example.net/authorize?oauth_token=hh5s93j4hdidpola

The server asks Jane to sign in with her username and password, and if that works, asks her to approve giving 'printer.example.com' access to her private photos. Jane says yes ๐Ÿ™Œ, and her user-agent gets redirected to the callback URI the client gave in the previous request (line breaks are for display purposes only):

  http://printer.example.com/ready?
  oauth_token=hh5s93j4hdidpola&oauth_verifier=hfdp7dh39dks9884

That callback tells the client Jane finished the authorization process. Now the client asks for a set of token credentials using its temporary credentials, over a secure Transport Layer Security (TLS) channel ๐Ÿ”’:

  POST /token HTTP/1.1
  Host: photos.example.net
  Authorization: OAuth realm="Photos",
     oauth_consumer_key="dpf43f3p2l4k3l03",
     oauth_token="hh5s93j4hdidpola",
     oauth_signature_method="HMAC-SHA1",
     oauth_timestamp="137131201",
     oauth_nonce="walatlh",
     oauth_verifier="hfdp7dh39dks9884",
     oauth_signature="gKgrFCywp7rO0OXSjdot%2FIHF7IU%3D"

The server checks the request and replies with token credentials in the body of the HTTP response:

  HTTP/1.1 200 OK
  Content-Type: application/x-www-form-urlencoded

  oauth_token=nnch734d00sl2jdk&oauth_token_secret=pfkkdhi9sl3r4s00

With token credentials in hand, the client is finally ready to request the private photo ๐Ÿ“ธ:

  GET /photos?file=vacation.jpg&size=original HTTP/1.1
  Host: photos.example.net
  Authorization: OAuth realm="Photos",
     oauth_consumer_key="dpf43f3p2l4k3l03",
     oauth_token="nnch734d00sl2jdk",
     oauth_signature_method="HMAC-SHA1",
     oauth_timestamp="137131202",
     oauth_nonce="chapoH",
     oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D"

The 'photos.example.net' server checks the request and sends back the photo. 'printer.example.com' can keep accessing Jane's private photos with that same set of token credentials for as long as Jane's authorization lasts, or until Jane revokes access ๐Ÿ‘‘.

1.3. Notational Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. ๐Ÿค“

2. Redirection-Based Authorization ๐ŸŽ€

OAuth uses tokens to represent the authorization the resource owner grants to the client. Usually, the server issues token credentials at the resource owner's request, after confirming who the resource owner is (usually with a username and password) ๐Ÿ”‘.

There are lots of ways a server can set up token credentials, and this section defines one of them, which uses HTTP redirections and the resource owner's user-agent. This redirection-based authorization method has three steps ๐Ÿฆ‹:

  1. The client gets a set of temporary credentials from the server (as an identifier and shared-secret). The temporary credentials are used to identify the access request throughout the authorization process.
  2. The resource owner authorizes the server to grant the client's access request (identified by the temporary credentials).
  3. The client uses the temporary credentials to request a set of token credentials from the server, which will let it access the resource owner's protected resources.

The server MUST revoke the temporary credentials after they've been used once to get the token credentials. It is RECOMMENDED that the temporary credentials have a limited lifetime โณ. Servers SHOULD let resource owners revoke token credentials after they've been issued to clients.

For the client to pull all this off, the server needs to advertise the URIs of these three endpoints ๐Ÿ“ฃ:

  • Temporary Credential Request: The endpoint the client uses to get a set of temporary credentials, as described in Section 2.1.
  • Resource Owner Authorization: The endpoint the resource owner is redirected to in order to grant authorization, as described in Section 2.2.
  • Token Request: The endpoint the client uses to request a set of token credentials using the temporary credentials, as described in Section 2.3.

The three URIs the server advertises MAY include a query component as defined by [RFC3986], Section 3. But if there is one, the query MUST NOT contain any parameters starting with the "oauth_" prefix, so it doesn't clash with the protocol parameters that get added to the URIs when they're used ๐Ÿ™…โ€โ™€๏ธ.

How the server advertises and documents those three endpoints is beyond the scope of this specification. Clients should avoid making assumptions about the size of tokens and other server-generated values, which this specification leaves undefined ๐Ÿ™ˆ. Also, protocol parameters MAY include values that need encoding when they're transmitted. Clients and servers should not make assumptions about the possible range of their values.

Heads up, bestie: the lowercase "should" lines above are just regular wording, not the capitalized BCP 14 key words, so don't read them as stronger requirements than the original intended. ๐Ÿ’€

2.1. Temporary Credentials ๐Ÿง

The client gets a set of temporary credentials from the server by making an authenticated (Section 3) HTTP "POST" request to the Temporary Credential Request endpoint. The exception is when the server advertises a different HTTP request method for the client to use. The client builds a request URI by adding the following REQUIRED parameter to the request (on top of the other protocol parameters, using the same parameter transmission method) ๐Ÿ“:

oauth_callback: An absolute URI the server will redirect the resource owner back to once the Resource Owner Authorization step (Section 2.2) is done. If the client can't receive callbacks, or a callback URI has been set up some other way, the parameter value MUST be set to "oob" (case sensitive), which signals an out-of-band configuration.

Servers MAY specify additional parameters โœจ.

When making the request, the client authenticates using only the client credentials. The client MAY leave out the empty "oauth_token" protocol parameter from the request, and it MUST use the empty string as the token secret value ๐Ÿซถ.

Because this request sends plain text credentials back in the HTTP response, the server MUST require the use of a transport-layer mechanism such as TLS or Secure Socket Layer (SSL) (or a secure channel with equivalent protections) ๐Ÿ”๐Ÿ˜ญ.

For example, the client makes this HTTPS request:

  POST /request_temp_credentials HTTP/1.1
  Host: server.example.com
  Authorization: OAuth realm="Example",
     oauth_consumer_key="jd83jd92dhsh93js",
     oauth_signature_method="PLAINTEXT",
     oauth_callback="http%3A%2F%2Fclient.example.net%2Fcb%3Fx%3D1",
     oauth_signature="ja893SD9%26"

The server MUST verify (Section 3.2) the request. If it's valid, the server responds to the client with a set of temporary credentials (as an identifier and shared-secret). The temporary credentials go in the HTTP response body using the "application/x-www-form-urlencoded" content type, as defined by [W3C.REC-html40-19980424], with a 200 status code (OK) ๐Ÿ’–.

The response contains the following REQUIRED parameters:

  • oauth_token: The temporary credentials identifier.
  • oauth_token_secret: The temporary credentials shared-secret.
  • oauth_callback_confirmed: MUST be present and set to "true". This parameter is used to tell this version of the protocol apart from previous versions.

Note that even though the parameter names include the word 'token', these credentials are NOT token credentials. They get used in the next two steps in a similar way to token credentials ๐Ÿงš.

For example (line breaks are for display purposes only):

  HTTP/1.1 200 OK
  Content-Type: application/x-www-form-urlencoded

  oauth_token=hdk48Djdsa&oauth_token_secret=xyz4992k83j47x0b&
  oauth_callback_confirmed=true

2.2. Resource Owner Authorization ๐Ÿ’Œ

okay so before the client can ask for token credentials, it MUST send the user over to the server so they can say yes to the request ๐Ÿซถ the client builds a request URI by tacking on this REQUIRED query parameter to the Resource Owner Authorization endpoint URI:

  • oauth_token: this is the temporary credentials identifier from Section 2.1, sent in the "oauth_token" parameter. Servers MAY declare this parameter as OPTIONAL ๐Ÿคทโ€โ™€๏ธ but if they do, they MUST give the resource owner some other way to pass along the identifier.

servers MAY add extra parameters too, no cap ๐ŸŒธ

the client sends the resource owner to that URI with an HTTP redirection response, or by any other means its user-agent can handle. the request MUST use the HTTP "GET" method, periodt ๐Ÿ’…

here's what it looks like:

GET /authorize_access?oauth_token=hdk48Djdsa HTTP/1.1
Host: server.example.com

how the server handles the authorization request is out of scope for this spec, including whether it uses a secure channel like TLS/SSL ๐Ÿ™ˆ BUT the server MUST first verify the identity of the resource owner. no skipping that step, bestie ๐Ÿ˜ญ

when the server asks the resource owner to approve access, it SHOULD show them info about the client asking, based on the link between the temporary credentials and the client identity โœจ and if it shows that info, it SHOULD say whether the info has been verified. honesty is lowkey everything ๐Ÿฆ‹

once the resource owner makes a decision, the server redirects them to the callback URI from the "oauth_callback" parameter (or some other way) ๐ŸŽ€

now here's the iconic part ๐Ÿ‘‘ to make sure the person who said yes is the same person coming back to finish up, the server MUST generate a verification code. it's an unguessable value that gets passed to the client through the resource owner, and it's REQUIRED to finish the process. the server builds the request URI by adding these REQUIRED parameters to the callback URI query component:

  • oauth_token: the temporary credentials identifier the client sent over.
  • oauth_verifier: the verification code.

if the callback URI already has a query component, the server MUST append the OAuth parameters to the end of that existing query ๐Ÿงš

for example, the server redirects the resource owner's user-agent to make this HTTP request:

GET /cb?x=1&oauth_token=hdk48Djdsa&oauth_verifier=473f82d3 HTTP/1.1
Host: client.example.net

if the client didn't give a callback URI, the server SHOULD show the verification code and tell the resource owner to manually tell the client that authorization is done ๐Ÿ“ and if the server knows the client is running on a limited device, it SHOULD make sure the verifier is easy to type in by hand. that's so thoughtful, I'm obsessed ๐Ÿฅน


2.3. Token Credentials ๐Ÿ”‘

the client gets a set of token credentials from the server by making an authenticated (Section 3) HTTP "POST" request to the Token Request endpoint. the exception is if the server advertises a different HTTP request method for the client to use โœจ the client builds a request URI by adding this REQUIRED parameter to the request (on top of the other protocol parameters, sent using the same parameter transmission method):

  • oauth_verifier: the verification code the server gave the client in the previous step.

when making the request, the client authenticates with its client credentials AND the temporary credentials. the temporary credentials stand in for token credentials in the authenticated request and get sent using the "oauth_token" parameter ๐Ÿ’œ

this next part is a big deal ๐Ÿšจ the request sends plain text credentials back in the HTTP response, so the server MUST require a transport-layer mechanism like TLS or SSL (or a secure channel with equivalent protections). no shortcuts, not even a little ๐Ÿ’€

here's the request:

POST /request_token HTTP/1.1
Host: server.example.com
Authorization: OAuth realm="Example",
   oauth_consumer_key="jd83jd92dhsh93js",
   oauth_token="hdk48Djdsa",
   oauth_signature_method="PLAINTEXT",
   oauth_verifier="473f82d3",
   oauth_signature="ja893SD9%26xyz4992k83j47x0b"

the server MUST verify (Section 3.2) that the request is valid, make sure the resource owner actually approved giving token credentials to the client, and make sure the temporary credentials haven't expired or already been used. it MUST also verify the verification code the client sent ๐Ÿซฃ if the request is valid and authorized, the token credentials go in the HTTP response body using the "application/x-www-form-urlencoded" content type defined by [W3C.REC-html40-19980424], with a 200 status code (OK) ๐ŸŽ‰

the response has these REQUIRED parameters:

  • oauth_token: the token identifier.
  • oauth_token_secret: the token shared-secret.

for example:

HTTP/1.1 200 OK
Content-Type: application/x-www-form-urlencoded

oauth_token=j49ddk933skd9dks&oauth_token_secret=ll399dj47dskfjdk

the server must keep the scope, duration, and other attributes the resource owner approved, and enforce those restrictions whenever it gets a client request made with the token credentials it issued ๐Ÿงฑ

once the client has the token credentials saved, it can access protected resources for the resource owner by making authenticated requests (Section 3) with its client credentials plus the token credentials it received. main character energy ๐Ÿ‘‘๐ŸŒˆ


3. Authenticated Requests ๐Ÿ”

the HTTP authentication methods from [RFC2617] let clients make authenticated HTTP requests. clients using those methods get into protected resources by using their credentials (usually a username and password pair), which lets the server check they're legit. using those methods for delegation means the client has to pretend to be the resource owner, which is kinda sus ๐Ÿ™ˆ

OAuth has a method built to send two sets of credentials with each request: one to identify the client, and one to identify the resource owner ๐Ÿซถ before a client can make authenticated requests for the resource owner, it has to get a token the resource owner authorized. Section 2 gives one such method for the client to get that token.

the client credentials are a unique identifier plus a shared-secret or RSA key pair. before making authenticated requests, the client sets up its credentials with the server. how that gets set up is out of scope for this spec. implementers are urged to think hard about the security stuff that comes with client credentials, some of which is covered in Section 4.6 โš ๏ธ

making authenticated requests means you need to know the server's config beforehand. OAuth has multiple ways to send protocol parameters with requests (Section 3.5), and multiple ways for the client to prove it really owns the credentials it's using (Section 3.4). how clients discover the config they need is also out of scope for this spec ๐Ÿงš


3.1. Making Requests ๐Ÿ“ฌ

an authenticated request has several protocol parameters. each parameter name starts with the "oauth_" prefix, and parameter names and values are case sensitive ๐Ÿ”ก clients make authenticated requests by working out the values of a set of protocol parameters and adding them to the HTTP request like this:

  1. the client assigns a value to each of these REQUIRED (unless specified otherwise) protocol parameters:
    • oauth_consumer_key: the identifier part of the client credentials (basically a username). this name is a leftover from an older version of the spec where it was called "Consumer Key", and it's been kept so older stuff still works ๐Ÿ•ฐ๏ธ
    • oauth_token: the token value that links the request to the resource owner. if the request isn't tied to a resource owner (no token available), clients MAY leave this parameter out.
    • oauth_signature_method: the name of the signature method the client used to sign the request, as defined in Section 3.4.
    • oauth_timestamp: the timestamp value from Section 3.3. this parameter MAY be left out when using the "PLAINTEXT" signature method.
    • oauth_nonce: the nonce value from Section 3.3. this parameter MAY be left out when using the "PLAINTEXT" signature method.
    • oauth_version: OPTIONAL. if it's there, it MUST be set to "1.0". it tells you which version of this authentication process is being used โœจ
  2. the protocol parameters get added to the request using one of the transmission methods in Section 3.5. each parameter MUST NOT appear more than once per request ๐Ÿšซ
  3. the client works out the value of "oauth_signature" as described in Section 3.4 and adds that parameter to the request using the same method as the previous step ๐Ÿ–Š๏ธ
  4. the client sends the authenticated HTTP request to the server ๐Ÿš€

here's an example of making this HTTP request authenticated. the "c2&a3=2+q" string in the examples shows how a form-encoded entity-body affects things ๐Ÿ“

POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

c2&a3=2+q

the client sets these protocol parameter values using its client credentials, token credentials, the current timestamp, a uniquely generated nonce, and says it'll use the "HMAC-SHA1" signature method ๐Ÿ’–

oauth_consumer_key:     9djdj82h48djs9d2
oauth_token:            kkk9d7dh3k39sjv7
oauth_signature_method: HMAC-SHA1
oauth_timestamp:        137131201
oauth_nonce:            7d8f3e4a

then the client adds those protocol parameters to the request using the OAuth HTTP "Authorization" header field:

Authorization: OAuth realm="Example",
               oauth_consumer_key="9djdj82h48djs9d2",
               oauth_token="kkk9d7dh3k39sjv7",
               oauth_signature_method="HMAC-SHA1",
               oauth_timestamp="137131201",
               oauth_nonce="7d8f3e4a"

next, it works out the "oauth_signature" value (using client secret "j49sk3j29djd" and token secret "dh893hdasih9"), adds it to the request, and sends the HTTP request to the server ๐ŸŽ€

POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth realm="Example",
               oauth_consumer_key="9djdj82h48djs9d2",
               oauth_token="kkk9d7dh3k39sjv7",
               oauth_signature_method="HMAC-SHA1",
               oauth_timestamp="137131201",
               oauth_nonce="7d8f3e4a",
               oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"

c2&a3=2+q

3.2. Verifying Requests โœจ

okay so when a server gets an authenticated request, it's got homework to do ๐Ÿ“š it MUST validate the request by:

  • Recalculating the request signature independently as described in Section 3.4 and comparing it to the value received from the client via the oauth_signature parameter. ๐Ÿ”
  • If using the HMAC-SHA1 or RSA-SHA1 signature methods, ensuring that the combination of nonce/timestamp/token (if present) received from the client has not been used before in a previous request (the server MAY reject requests with stale timestamps as described in Section 3.3). ๐Ÿ•ฐ๏ธ
  • If a token is present, verifying the scope and status of the client authorization as represented by the token (the server MAY choose to restrict token usage to the client to which it was issued). ๐ŸŽŸ๏ธ
  • If the oauth_version parameter is present, ensuring its value is 1.0. ๐Ÿ’…

if the request fails verification, the server SHOULD respond with the appropriate HTTP response status code ๐Ÿ™ˆ it MAY also include further details about why the request was rejected in the response body. bestie, that's a nice little hint for debugging ๐Ÿซถ

the server SHOULD return a 400 (Bad Request) status code when it gets a request with unsupported parameters, an unsupported signature method, missing parameters, or duplicated protocol parameters. and the server SHOULD return a 401 (Unauthorized) status code when it gets a request with invalid client credentials, an invalid or expired token, an invalid signature, or an invalid or used nonce. the vibes are very "don't let the wrong one in" ๐Ÿšชโœจ

3.3. Nonce and Timestamp โฐ

the timestamp value MUST be a positive integer ๐Ÿ”ข unless the server's docs say otherwise, the timestamp is the number of seconds since January 1, 1970 00:00:00 GMT. that's the Unix epoch, and it's giving old-school classic ๐Ÿ•ฐ๏ธ

a nonce is a random string that the client generates uniquely ๐ŸŽฒ it lets the server check that a request has never been made before, and it helps prevent replay attacks when requests go over a non-secure channel. the nonce value MUST be unique across all requests with the same timestamp, client credentials, and token combinations. no copy-pasting nonces, babe ๐Ÿ™…โ€โ™€๏ธ

to avoid needing to keep an infinite pile of nonce values for future checks ๐Ÿ—„๏ธ servers MAY choose to limit how old a timestamp can be before the request gets rejected. just know this kind of limit means the client's and server's clocks have to be somewhat in sync โฑ๏ธ servers that use this limit MAY give the client a way to sync with the server's clock. or, both systems could sync with a trusted time service. the nitty-gritty of clock sync strategies is beyond the scope of this spec, so that's a whole other episode ๐Ÿ“บ

3.4. Signature ๐Ÿ–‹๏ธ

OAuth-authenticated requests can carry two sets of credentials: the ones passed via the oauth_consumer_key parameter and the ones in the oauth_token parameter ๐ŸŽ€ for the server to check the request is legit and keep out unauthorized folks, the client has to prove it's the rightful owner of those credentials. this is done using the shared-secret (or RSA key) part of each set of credentials ๐Ÿ”

OAuth gives the client three ways to prove ownership: HMAC-SHA1, RSA-SHA1, and PLAINTEXT. these are usually called signature methods, even though PLAINTEXT doesn't actually involve a signature ๐Ÿคทโ€โ™€๏ธ also, RSA-SHA1 uses an RSA key instead of the shared secrets tied to the client credentials.

OAuth doesn't mandate one particular signature method, since every implementation can have its own unique needs ๐ŸŒˆ servers are totally free to build and document their own custom methods. recommending any particular method is beyond the scope of this spec, so implementers should check out the Security Considerations section (Section 4) before picking which method to support. read it, it's serious stuff ๐Ÿ˜ญ

the client declares which signature method it's using via the oauth_signature_method parameter. then it generates a signature (or a string of equivalent value) and puts it in the oauth_signature parameter ๐Ÿ’Œ the server verifies the signature as specified for each method.

the signature process doesn't change the request or its parameters, except for the oauth_signature parameter itself. so chill, nothing else gets touched ๐Ÿงš

3.4.1. Signature Base String ๐Ÿง

the signature base string is a consistent, reproducible concatenation of several HTTP request elements, all smooshed into one string ๐Ÿ“ it's the input for the HMAC-SHA1 and RSA-SHA1 signature methods.

the signature base string includes these parts of the HTTP request:

  • The HTTP request method (e.g., GET, POST, etc.).
  • The authority as declared by the HTTP Host request header field.
  • The path and query components of the request resource URI.
  • The protocol parameters, excluding oauth_signature.
  • Parameters included in the request entity-body, if they follow the strict restrictions defined in Section 3.4.1.3.

the signature base string does NOT cover the whole HTTP request, which is kind of a plot twist ๐Ÿ‘€ most notably, it doesn't include the entity-body in most requests, and it doesn't include most HTTP entity-headers. the server can't verify the authenticity of those excluded parts unless you add more protection, like SSL/TLS or other methods. so keep that in mind, bestie ๐Ÿ”’

3.4.1.1. String Construction ๐Ÿ› ๏ธ

the signature base string gets built by concatenating these HTTP request elements, in this order:

  1. The HTTP request method in uppercase. For example: HEAD, GET, POST, etc. If the request uses a custom HTTP method, it MUST be encoded (Section 3.6). โœจ
  2. An & character (ASCII code 38).
  3. The base string URI from Section 3.4.1.2, after being encoded (Section 3.6).
  4. An & character (ASCII code 38).
  5. The request parameters as normalized in Section 3.4.1.3.2, after being encoded (Section 3.6).

let's look at an example request, because examples are everything ๐Ÿฅฐ this HTTP request:

POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth realm="Example",
               oauth_consumer_key="9djdj82h48djs9d2",
               oauth_token="kkk9d7dh3k39sjv7",
               oauth_signature_method="HMAC-SHA1",
               oauth_timestamp="137131201",
               oauth_nonce="7d8f3e4a",
               oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"

c2&a3=2+q

is represented by this signature base string (the line breaks are just for display, so it fits on your screen ๐Ÿ“ฑ):

POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q
%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_
key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m
ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk
9d7dh3k39sjv7

3.4.1.2. Base String URI ๐ŸŒ

the scheme, authority, and path of the request resource URI [RFC3986] are included by building an http or https URI that represents the request resource (without the query or fragment), like this:

  1. The scheme and host MUST be in lowercase. ๐Ÿ”ก
  2. The host and port values MUST match the content of the HTTP request Host header field. ๐ŸŽฏ
  3. The port MUST be included if it's not the default port for the scheme, and MUST be excluded if it IS the default. Specifically, the port MUST be excluded when making an HTTP request [RFC2616] to port 80, or when making an HTTPS request [RFC2818] to port 443. All other non-default port numbers MUST be included. ๐Ÿšช

for example, this HTTP request:

GET /r%20v/X?id=123 HTTP/1.1
Host: EXAMPLE.COM:80

is represented by the base string URI: http://example.com/r%20v/X. the uppercase host got lowercased, and the default port 80 got dropped. that's the glow-up we like to see โœจ

and in another example, this HTTPS request:

GET /?q=1 HTTP/1.1
Host: www.example.net:8080

is represented by the base string URI:

https://www.example.net:8080/

the 8080 stays because it's not the default port for HTTPS, so it has to be included ๐Ÿ’…

3.4.1.3. Request Parameters ๐Ÿ“ฆ

to guarantee a consistent, reproducible representation of the request parameters, the parameters get collected and decoded back to their original decoded form ๐Ÿ”“ then they're sorted, encoded in a particular way that's often different from their original encoding, and concatenated into a single string. it's giving organized closet energy ๐Ÿงบ๐ŸŽ€

3.4.1.3.1. Parameter Sources โœจ

okay so bestie, this is where we gather up ALL the parameters that go into the signature. ๐Ÿงš Every parameter comes from one of three places, and they all get dumped into one big list of name/value pairs. ๐Ÿ’–

  • The query component of the HTTP request URI, as defined by [RFC3986], Section 3.4. ๐Ÿ”— We parse it as an "application/x-www-form-urlencoded" string, separating the names and values and decoding them as defined by [W3C.REC-html40-19980424], Section 17.13.4. ๐ŸŽ€
  • The OAuth HTTP "Authorization" header field (Section 3.5.1), if one is present. ๐ŸŒธ We parse its content into name/value pairs, excluding the "realm" parameter if it's there. The parameter values get decoded as defined in Section 3.5.1. ๐Ÿ’…
  • The HTTP request entity-body, but ONLY if all of these conditions are met: ๐Ÿ‘‘
    • The entity-body is single-part. ๐Ÿฆ‹
    • The entity-body follows the encoding requirements of the "application/x-www-form-urlencoded" content-type, as defined by [W3C.REC-html40-19980424]. ๐Ÿ“
    • The HTTP request entity-header includes the "Content-Type" header field set to "application/x-www-form-urlencoded". ๐Ÿ’œ

If all that checks out, the entity-body gets parsed into a list of decoded name/value pairs, as described in [W3C.REC-html40-19980424], Section 17.13.4. ๐Ÿซถ

Now the rules for what gets thrown out: the "oauth_signature" parameter MUST be excluded from the signature base string if it's present. ๐Ÿšซ And any parameter that wasn't explicitly included in the request MUST be excluded too. Like, if "oauth_version" is left out, it does NOT sneak into the base string. Not me being strict, it's just the rule. ๐Ÿ˜ญ

Here's an example. Check out this HTTP request:

POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth realm="Example",
               oauth_consumer_key="9djdj82h48djs9d2",
               oauth_token="kkk9d7dh3k39sjv7",
               oauth_signature_method="HMAC-SHA1",
               oauth_timestamp="137131201",
               oauth_nonce="7d8f3e4a",
               oauth_signature="djosJKDKJSD8743243%2Fjdk33klY%3D"

c2&a3=2+q

It contains the following (fully decoded) parameters used in the signature base sting:

        +------------------------+------------------+
        |          Name          |       Value      |
        +------------------------+------------------+
        |           b5           |       =%3D       |
        |           a3           |         a        |
        |           c@           |                  |
        |           a2           |        r b       |
        |   oauth_consumer_key   | 9djdj82h48djs9d2 |
        |       oauth_token      | kkk9d7dh3k39sjv7 |
        | oauth_signature_method |     HMAC-SHA1    |
        |     oauth_timestamp    |     137131201    |
        |       oauth_nonce      |     7d8f3e4a     |
        |           c2           |                  |
        |           a3           |        2 q       |
        +------------------------+------------------+

Look at that "b5" value! It's "=%3D" and NOT "==". ๐Ÿ™ˆ And both "c@" and "c2" have empty values, so they're just vibing with nothing. ๐Ÿซง

Here's a plot twist: the encoding rules in this spec don't use a "+" (ASCII code 43) to stand in for an encoded space (ASCII code 32). But that "+" trick is SUPER common in "application/x-www-form-urlencoded" values, so it MUST be properly decoded. ๐Ÿ”ฅ You can see it in action with the "a3" parameter, which shows up twice in this request. Iconic. ๐Ÿ‘‘

3.4.1.3.2. Parameters Normalization ๐Ÿ’–

okay now that we've got our list, we have to normalize it into one single string. ๐Ÿง Here's the recipe:

  1. First, the name and value of each parameter get encoded (Section 3.6). ๐ŸŽ€
  2. The parameters get sorted by name, using ascending byte value ordering. If two or more parameters share the same name, they get sorted by their value. ๐ŸŒˆ
  3. The name of each parameter gets concatenated to its matching value using an "=" character (ASCII code 61) as a separator, even if the value is empty. ๐Ÿฆ‹
  4. The sorted name/value pairs get concatenated into one single string, using an "&" character (ASCII code 38) as the separator. ๐Ÿ’…

Let's walk through the example from the last section. First, the encoding step:

                             Encoded:

        +------------------------+------------------+
        |          Name          |       Value      |
        +------------------------+------------------+
        |           b5           |     %3D%253D     |
        |           a3           |         a        |
        |          c%40          |                  |
        |           a2           |       r%20b      |
        |   oauth_consumer_key   | 9djdj82h48djs9d2 |
        |       oauth_token      | kkk9d7dh3k39sjv7 |
        | oauth_signature_method |     HMAC-SHA1    |
        |     oauth_timestamp    |     137131201    |
        |       oauth_nonce      |     7d8f3e4a     |
        |           c2           |                  |
        |           a3           |       2%20q      |
        +------------------------+------------------+

Next, we sort it:

                              Sorted:

        +------------------------+------------------+
        |          Name          |       Value      |
        +------------------------+------------------+
        |           a2           |       r%20b      |
        |           a3           |       2%20q      |
        |           a3           |         a        |
        |           b5           |     %3D%253D     |
        |          c%40          |                  |
        |           c2           |                  |
        |   oauth_consumer_key   | 9djdj82h48djs9d2 |
        |       oauth_nonce      |     7d8f3e4a     |
        | oauth_signature_method |     HMAC-SHA1    |
        |     oauth_timestamp    |     137131201    |
        |       oauth_token      | kkk9d7dh3k39sjv7 |
        +------------------------+------------------+

Then we mash each pair together with "=":

                  Concatenated Pairs:

      +-------------------------------------+
      |              Name=Value             |
      +-------------------------------------+
      |               a2=r%20b              |
      |               a3=2%20q              |
      |                 a3=a                |
      |             b5=%3D%253D             |
      |                c%40=                |
      |                 c2=                 |
      | oauth_consumer_key=9djdj82h48djs9d2 |
      |         oauth_nonce=7d8f3e4a        |
      |   oauth_signature_method=HMAC-SHA1  |
      |      oauth_timestamp=137131201      |
      |     oauth_token=kkk9d7dh3k39sjv7    |
      +-------------------------------------+

And finally, everything gets joined into a single string. (The line breaks are just for display, so ignore them! ๐Ÿ™ƒ)

a2=r%20b&a3=2%20q&a3=a&b5=%3D%253D&c%40=&c2=&oauth_consumer_key=9dj
dj82h48djs9d2&oauth_nonce=7d8f3e4a&oauth_signature_method=HMAC-SHA1
&oauth_timestamp=137131201&oauth_token=kkk9d7dh3k39sjv7

3.4.2. HMAC-SHA1 ๐Ÿ”

The "HMAC-SHA1" signature method uses the HMAC-SHA1 signature algorithm, as defined in [RFC2104]:

  digest = HMAC-SHA1 (key, text)

Here's how the HMAC-SHA1 function variables get filled in: ๐Ÿงฉ

text is set to the value of the signature base string from Section 3.4.1.1.

key is set to the concatenated values of:

  1. The client shared-secret, after being encoded (Section 3.6).
  2. An "&" character (ASCII code 38), which MUST be included even when either secret is empty. ๐Ÿšจ
  3. The token shared-secret, after being encoded (Section 3.6).

digest is used to set the value of the "oauth_signature" protocol parameter, after the result octet string is base64-encoded per [RFC2045], Section 6.8. ๐ŸŒธ

3.4.3. RSA-SHA1 ๐Ÿ—๏ธ

The "RSA-SHA1" signature method uses the RSASSA-PKCS1-v1_5 signature algorithm, as defined in [RFC3447], Section 8.2 (also known as PKCS#1), using SHA-1 as the hash function for EMSA-PKCS1-v1_5. To use this method, the client MUST have established client credentials with the server that included its RSA public key. (How that happens is beyond the scope of this spec, so don't come for me about it. ๐Ÿ’€)

The signature base string gets signed with the client's RSA private key, per [RFC3447], Section 8.2.1:

  S = RSASSA-PKCS1-V1_5-SIGN (K, M)

Where:

K is set to the client's RSA private key. ๐Ÿ”‘

M is set to the value of the signature base string from Section 3.4.1.1. ๐Ÿ“

S is the result signature, used to set the value of the "oauth_signature" protocol parameter, after the result octet string is base64-encoded per [RFC2045] section 6.8. โœจ

The server verifies the signature per [RFC3447] section 8.2.2:

  RSASSA-PKCS1-V1_5-VERIFY ((n, e), M, S)

Where:

(n, e) is set to the client's RSA public key. ๐Ÿชช

M is set to the value of the signature base string from Section 3.4.1.1. ๐Ÿ“

S is set to the octet string value of the "oauth_signature" protocol parameter received from the client. ๐Ÿซถ

3.4.4. PLAINTEXT ๐Ÿ™Š

The "PLAINTEXT" method does NOT use a signature algorithm, so it's giving "trust me bro." ๐Ÿ˜ญ It MUST be used with a transport-layer mechanism such as TLS or SSL (or sent over a secure channel with equivalent protections). > Seriously, don't skip the secure channel! Your secrets will be out there for everyone to read. ๐Ÿ’€ PLAINTEXT doesn't use the signature base string or the "oauth_timestamp" and "oauth_nonce" parameters either.

The "oauth_signature" protocol parameter is set to the concatenated value of:

  1. The client shared-secret, after being encoded (Section 3.6).
  2. An "&" character (ASCII code 38), which MUST be included even when either secret is empty. ๐Ÿšจ
  3. The token shared-secret, after being encoded (Section 3.6).

3.5. Parameter Transmission ๐Ÿš€

When you make an OAuth-authenticated request, the protocol parameters AND any other parameter using the "oauth_" prefix SHALL be included in the request using one and only one of these locations, listed in order of decreasing preference: ๐ŸŽ€

  1. The HTTP "Authorization" header field, as described in Section 3.5.1. ๐Ÿ‘‘
  2. The HTTP request entity-body, as described in Section 3.5.2. ๐Ÿ“
  3. The HTTP request URI query, as described in Section 3.5.3. ๐ŸŒˆ

In addition to these three methods, future extensions MAY define other methods for including protocol parameters in the request. ๐Ÿ”ฎ

3.5.1. Authorization Header

okay bestie, so protocol params can ride in the HTTP "Authorization" header field, as defined by [RFC2617], with the auth-scheme name set to "OAuth" (case insensitive) ๐Ÿ’…

For example:

Authorization: OAuth realm="Example",
   oauth_consumer_key="0685bd9184jfhq22",
   oauth_token="ad180jjd733klru7",
   oauth_signature_method="HMAC-SHA1",
   oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
   oauth_timestamp="137131200",
   oauth_nonce="4572616e48616d6d65724c61686176",
   oauth_version="1.0"

Protocol parameters SHALL be included in the "Authorization" header field like this ๐ŸŽ€

  1. Parameter names and values are encoded per Parameter Encoding (Section 3.6).
  2. Each parameter's name is immediately followed by an "=" character (ASCII code 61), a """ character (ASCII code 34), the parameter value (MAY be empty), and another """ character (ASCII code 34).
  3. Parameters are separated by a "," character (ASCII code 44) and OPTIONAL linear whitespace per [RFC2617].
  4. The OPTIONAL "realm" parameter MAY be added and interpreted per [RFC2617] section 1.2.

Servers MAY show that they support the "OAuth" auth-scheme by returning the HTTP "WWW-Authenticate" response header field when clients ask for protected resources ๐Ÿงš As per [RFC2617], that response MAY include additional HTTP "WWW-Authenticate" header fields:

For example:

WWW-Authenticate: OAuth realm="http://server.example.com/"

The realm parameter defines a protection realm per [RFC2617], Section 1.2. realm is giving main character energy, fr fr ๐Ÿ‘‘

3.5.2. Form-Encoded Body

so params can also go in the HTTP request entity-body, but ONLY if these REQUIRED conditions are met ๐Ÿซถ

  • The entity-body is single-part.
  • The entity-body follows the encoding requirements of the "application/x-www-form-urlencoded" content-type as defined by [W3C.REC-html40-19980424].
  • The HTTP request entity-header includes the "Content-Type" header field set to "application/x-www-form-urlencoded".

For example (line breaks are for display purposes only):

oauth_consumer_key=0685bd9184jfhq22&oauth_token=ad180jjd733klr
u7&oauth_signature_method=HMAC-SHA1&oauth_signature=wOJIO9A2W5
mFwDgiDvZbTSMK%2FPY%3D&oauth_timestamp=137131200&oauth_nonce=4
572616e48616d6d65724c61686176&oauth_version=1.0

The entity-body MAY include other request-specific params ๐ŸŒธ If it does, the protocol params SHOULD be added after those request-specific params, separated properly by an "&" character (ASCII code 38). lowkey the ordering is everything ๐Ÿ˜ญ

3.5.3. Request URI Query

params can also be tucked into the HTTP request URI as a query parameter, as defined by [RFC3986], Section 3 ๐Ÿฆ‹

For example (line breaks are for display purposes only):

GET /example/path?oauth_consumer_key=0685bd9184jfhq22&
oauth_token=ad180jjd733klru7&oauth_signature_method=HM
AC-SHA1&oauth_signature=wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%
3D&oauth_timestamp=137131200&oauth_nonce=4572616e48616
d6d65724c61686176&oauth_version=1.0 HTTP/1.1

The request URI MAY include other request-specific query params, and if it does, the protocol params SHOULD be added after those, properly separated by an "&" character (ASCII code 38) ๐Ÿ“

3.6. Percent Encoding

ngl, existing percent-encoding methods don't guarantee a consistent signature base string, so this spec brings its own method ๐Ÿ’– It is NOT meant to replace the encoding methods already defined by [RFC3986] and [W3C.REC-html40-19980424]. It's only used when building the signature base string and the "Authorization" header field โœจ

This spec defines the following method for percent-encoding strings:

  1. Text values are first encoded as UTF-8 octets per [RFC3629] if they aren't already. This doesn't include binary values that aren't meant for human consumption ๐ŸŒˆ
  2. The values are then escaped using the [RFC3986] percent-encoding (%XX) mechanism, like this:
    • Characters in the unreserved character set as defined by [RFC3986], Section 2.3 (ALPHA, DIGIT, "-", ".", "_", "~") MUST NOT be encoded.
    • All other characters MUST be encoded.
    • The two hexadecimal characters used to represent encoded characters MUST be uppercase.

This method is different from the encoding scheme used by the "application/x-www-form-urlencoded" content-type (for example, it encodes space characters as "%20" and NOT with the "+" character). It MAY be different from the percent-encoding functions that web-development frameworks provide (e.g., it might encode different characters, or use lowercase hexadecimal characters). frameworks be doing their own thing, bestie ๐Ÿ’…


4. Security Considerations โœจ

okay this part is SERIOUS, bestie ๐Ÿ˜ญ As stated in [RFC2617], the biggest risks are usually not in the core protocol itself but in the policies and procedures around how it's used. Implementers are strongly encouraged to check how this protocol covers their security requirements ๐Ÿ”ฅ

4.1. RSA-SHA1 Signature Method

authenticated requests made with "RSA-SHA1" signatures don't use the token shared-secret, or any provisioned client shared-secret. That means the request totally depends on the private key the client uses to sign requests staying secret ๐Ÿ” no cap, that's the whole thing ๐Ÿ’€

4.2. Confidentiality of Requests

this protocol gives you a way to check that requests haven't been messed with (integrity), but it gives NO guarantee of request confidentiality ๐Ÿ™ˆ Unless you take extra precautions, eavesdroppers will have full access to request content. Servers should carefully think about what kinds of data get sent in these requests, and should use transport-layer security mechanisms to protect sensitive resources ๐Ÿ›ก๏ธ

4.3. Spoofing by Counterfeit Servers

this protocol makes NO attempt to verify that the server is authentic. A hostile party could intercept the client's requests and send back misleading or otherwise incorrect responses, and that's a whole mess ๐Ÿ˜ฑ Service providers should consider these attacks when building services with this protocol, and should require transport-layer security for any requests where the server's authenticity, or the authenticity of responses, is an issue.

4.4. Proxying and Caching of Authenticated Content

The HTTP Authorization scheme (Section 3.5.1) is optional. However, [RFC2616] relies on the "Authorization" and "WWW-Authenticate" header fields to tell authenticated content apart so it can be protected. Proxies and caches, in particular, may fail to adequately protect requests that don't use these header fields ๐Ÿซฃ

For example, private authenticated content may get stored in (and thus be retrievable from) publicly accessible caches. Servers that don't use the HTTP "Authorization" header field should take care to use other mechanisms, such as the "Cache-Control" header field, so authenticated content stays protected ๐ŸงŠ

4.5. Plaintext Storage of Credentials

the client shared-secret and token shared-secret work the same way passwords do in traditional authentication systems ๐Ÿ”‘ To compute the signatures used in methods other than "RSA-SHA1", the server must have access to these secrets in plaintext form. This is different from modern operating systems, which store only a one-way hash of user credentials.

If an attacker got access to these secrets, or worse, to the server's database of all such secrets, he or she would be able to do ANY action on behalf of ANY resource owner ๐Ÿ˜จ So it is critical that servers protect these secrets from unauthorized access. Non-negotiable, bestie ๐Ÿšจ

4.6. Secrecy of the Client Credentials

in lots of cases, the client application is under the control of potentially untrusted parties. For example, if the client is a desktop app with freely available source code or an executable binary, an attacker may be able to download a copy and analyze it. In those cases, attackers will be able to recover the client credentials ๐Ÿ•ต๏ธ

So servers should not use the client credentials alone to verify the identity of the client. Where possible, other factors, such as IP address, should be used as well ๐Ÿง 

4.7. Phishing Attacks

wide deployment of this protocol and similar ones may cause resource owners to get numb to being redirected to websites where they're asked to enter their passwords ๐Ÿฅฒ If resource owners aren't careful to verify that these websites are authentic before entering their credentials, attackers can exploit that habit to steal resource owners' passwords.

Servers should try to educate resource owners about the risks phishing attacks pose, and should provide mechanisms that make it easy for resource owners to confirm that their sites are authentic. Client developers should think hard about the security implications of how they interact with a user-agent (e.g., separate window, embedded), and about whether the end-user can verify the authenticity of the server website ๐Ÿ‘€

4.8. Scoping of Access Requests

by itself, this protocol doesn't provide any method for scoping the access rights granted to a client. But most apps do need more granularity of access rights. For example, servers may want to let people grant access to some protected resources but not others, or to grant only limited access (such as read-only access) to those resources ๐Ÿ“–

When implementing this protocol, servers should think about the types of access resource owners may want to grant clients, and should provide mechanisms to do that. Servers should also make sure resource owners understand the access they're granting, as well as any risks that may be involved ๐Ÿง

4.9. Entropy of Secrets

unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and signatures, and will be able to run offline brute-force attacks to recover the credentials used ๐Ÿ˜ต Servers should be careful to assign shared-secrets that are long enough, and random enough, to resist such attacks for at least as long as the shared-secrets are valid.

For example, if shared-secrets are valid for two weeks, servers should make sure it's NOT possible to run a brute force attack that recovers the shared-secret in less than two weeks. Servers are urged to err on the side of caution and use the longest secrets that are reasonable ๐Ÿ’ช

It's equally important that the pseudo-random number generator (PRNG) used to make these secrets is high quality. Lots of PRNG implementations generate number sequences that look random but still have patterns or other weaknesses that make cryptanalysis or brute force attacks easier ๐Ÿคฏ Implementers should be careful to use cryptographically secure PRNGs to avoid these problems ๐Ÿซถ

4.10. Denial-of-Service / Resource-Exhaustion Attacks ๐Ÿงจ

okay so this protocol has a few features that could make resource exhaustion attacks against servers possible ๐Ÿ˜ญ. For example, servers have to keep track of nonces that were already used. If an attacker can throw out a ton of nonces really fast, the memory needed to track them could run out ๐Ÿ’€. Verifying the signature on incoming requests can also make servers do expensive computations, so an attacker could launch a denial-of-service attack just by sending a huge pile of invalid requests ๐Ÿ™ˆ.

Resource exhaustion attacks are not unique to this spec, obviously. Still, implementers should think about the extra attack paths this protocol opens up and build their implementations with those in mind ๐ŸŽ€. Entropy starvation is a good example: it usually ends up as either a total denial of service while the system waits for fresh entropy, or as weak secrets that are easy to guess ๐Ÿ˜ฑ. When implementing this protocol, servers should figure out which of those two is the bigger risk for their application and design around it ๐Ÿ’….

4.11. SHA-1 Cryptographic Attacks ๐Ÿ”

SHA-1 is the hash algorithm used by the "HMAC-SHA1" and "RSA-SHA1" signature methods, and it has a bunch of cryptographic weaknesses that seriously cut down its resistance to collision attacks ๐Ÿ’”. The weaknesses don't seem to touch SHA-1 when it's used with the Hash-based Message Authentication Code (HMAC), so "HMAC-SHA1" shouldn't be affected. The "RSA-SHA1" signature method, though, might be. NIST announced that it would phase out SHA-1 in digital signatures by 2010 [NIST_SHA-1Comments] ๐Ÿ“….

Honestly, these weaknesses are hard to exploit, and on their own they aren't a major risk for users of this protocol ๐Ÿคทโ€โ™€๏ธ. They could still make more efficient attacks possible, so servers should factor that in when deciding whether SHA-1 gives their applications an adequate level of security โœจ.

4.12. Signature Base String Limitations ๐Ÿ“

The signature base string was designed to support the signature methods defined in this spec ๐Ÿ’•. Anyone designing extra signature methods should check whether the signature base string is compatible with their own security requirements, bestie ๐Ÿซถ.

The signature base string doesn't cover the entire HTTP request. It skips things like most of the request entity-body, most entity-headers, and the order in which parameters are sent ๐Ÿ‘€. So servers should use extra mechanisms to protect those parts ๐Ÿ›ก๏ธ.

4.13. Cross-Site Request Forgery (CSRF) ๐Ÿ•ธ๏ธ

Cross-Site Request Forgery (CSRF) is a web attack where HTTP requests get sent from a user that a website trusts or has already authenticated ๐Ÿ˜ค. CSRF attacks on authorization approvals can let an attacker get authorization to protected resources without the User's consent, which is literally the worst ๐Ÿ’€. Servers SHOULD strongly consider CSRF prevention best practices at every protocol authorization endpoint ๐Ÿ”’.

CSRF attacks can also target OAuth callback URIs that clients host ๐Ÿ™…โ€โ™€๏ธ. Clients should prevent these by checking that the resource owner at the client site actually meant to finish the OAuth negotiation with the server ๐Ÿ‘‘. The methods for stopping these CSRF attacks are out of scope for this spec ๐Ÿงš.

4.14. User Interface Redress ๐Ÿ–ผ๏ธ

Servers should protect the authorization process against user interface (UI) redress attacks, which are also called "clickjacking" ๐Ÿ˜ญ. As of writing, there are no complete defenses against UI redress yet. Servers can lower the risk with the following techniques:

  • JavaScript frame busting.
  • JavaScript frame busting, and requiring that browsers have JavaScript enabled on the authorization page.
  • Browser-specific anti-framing techniques.
  • Requiring password reentry before issuing OAuth tokens.

4.15. Automatic Processing of Repeat Authorizations โฉ

Servers may want to automatically process authorization requests (Section 2.2) from clients that the resource owner already authorized before ๐Ÿ’–. When the resource owner gets redirected to the server to grant access, the server notices that they already approved that particular client. Instead of asking for approval again, the server just sends the resource owner straight back to the client โœจ.

If the client credentials get compromised, though, automatic processing adds new security risks ๐Ÿ˜ฌ. An attacker can use the stolen client credentials to redirect the resource owner to the server with an authorization request. The server will then grant access to the resource owner's data without their explicit approval, or even without them knowing an attack is happening ๐Ÿ™€. Without automatic approval, an attacker would need social engineering to trick the resource owner into approving access ๐ŸŽญ.

Servers can reduce the risks of automatic processing by limiting the scope of token credentials obtained through automated approvals ๐Ÿง . Token credentials obtained through explicit resource owner consent can stay as they are ๐Ÿ’…. Clients can reduce the risks of automatic processing by protecting their client credentials ๐Ÿ”‘.


5. Acknowledgments ๐Ÿซถ

This specification is directly based on the OAuth Core 1.0 Revision A community specification ๐ŸŒŸ. That community spec was itself modeled on existing proprietary protocols and best practices that various companies had already implemented independently ๐Ÿ’œ.

The community specification was edited by Eran Hammer-Lahav and authored by: Mark Atwood, Dirk Balfanz, Darren Bounds, Richard M. Conlan, Blaine Cook, Leah Culver, Breno de Medeiros, Brian Eaton, Kellan Elliott-McCrea, Larry Halff, Eran Hammer-Lahav, Ben Laurie, Chris Messina, John Panzer, Sam Quigley, David Recordon, Eran Sandler, Jonathan Sergent, Todd Sieling, Brian Slesinsky, and Andy Smith ๐Ÿ‘‘.

The editor would like to thank the following people for their invaluable contribution to publishing this edition of the protocol: Lisa Dusseault, Justin Hart, Avshalom Houri, Chris Messina, Mark Nottingham, Tim Polk, Peter Saint-Andre, Joseph Smarr, and Paul Walker ๐ŸŒธ.


Appendix A. Differences from the Community Edition ๐Ÿ“‹

This specification includes the following changes made to the original community document [OAuthCore1.0_RevisionA] to fix mistakes and omissions that were found after the document was first published at <http://oauth.net> ๐Ÿ”ง.

  • Changed using TLS/SSL when sending or requesting plain text credentials from SHOULD to MUST. This change affects any use of the "PLAINTEXT" signature method, as well as requesting temporary credentials (Section 2.1) and obtaining token credentials (Section 2.3) ๐Ÿ”.
  • Adjusted the nonce language to say it is unique per token/timestamp/client combination ๐ŸŽฏ.
  • Removed the requirement for timestamps to be equal to or greater than the timestamp used in the previous request ๐Ÿ•ฐ๏ธ.
  • Changed the nonce and timestamp parameters to OPTIONAL when using the "PLAINTEXT" signature method โœจ.
  • Extended signature base string coverage to include "application/x-www-form-urlencoded" entity-body parameters when the HTTP method is other than "POST", and URI query parameters when the HTTP method is other than "GET" ๐Ÿช„.
  • Incorporated corrections to the instructions in each signature method so the signature value gets encoded before it's inserted into the "oauth_signature" parameter, which removes errors that caused double-encoded values ๐Ÿง.
  • Allowed omitting the "oauth_token" parameter when it's empty ๐Ÿซง.
  • Permitted sending requests for temporary credentials with an empty "oauth_token" parameter ๐Ÿ’ซ.
  • Removed the restrictions on defining additional "oauth_" parameters ๐Ÿฆ‹.

6. References ๐Ÿ“š

6.1. Normative References

[RFC2045]  Freed, N. and N. Borenstein, "Multipurpose Internet Mail
           Extensions (MIME) Part One: Format of Internet Message
           Bodies", RFC 2045, November 1996.

[RFC2104]  Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
           Hashing for Message Authentication", RFC 2104,
           February 1997.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2616]  Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
           Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
           Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.

[RFC2617]  Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
           Leach, P., Luotonen, A., and L. Stewart, "HTTP
           Authentication: Basic and Digest Access Authentication",
           RFC 2617, June 1999.

[RFC2818]  Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.

[RFC3447]  Jonsson, J. and B. Kaliski, "Public-Key Cryptography
           Standards (PKCS) #1: RSA Cryptography Specifications
           Version 2.1", RFC 3447, February 2003.

[RFC3629]  Yergeau, F., "UTF-8, a transformation format of ISO
           10646", STD 63, RFC 3629, November 2003.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, January 2005.

[W3C.REC-html40-19980424]
           Hors, A., Raggett, D., and I. Jacobs, "HTML 4.0
           Specification", World Wide Web Consortium
           Recommendation REC-html40-19980424, April 1998,
           <http://www.w3.org/TR/1998/REC-html40-19980424>.

6.2. Informative References

[NIST_SHA-1Comments]
           Burr, W., "NIST Comments on Cryptanalytic Attacks on
           SHA-1",
           <http://csrc.nist.gov/groups/ST/hash/statement.html>.

[OAuthCore1.0_RevisionA]
           OAuth Community, "OAuth Core 1.0 Revision A",
           <http://oauth.net/core/1.0a>.

Author's Address ๐Ÿ“ฎ

Eran Hammer-Lahav (editor)

EMail: eran@hueniverse.com
URI:   http://hueniverse.com

That's the whole spec, bestie! ๐ŸŒˆ๐Ÿ’– You made it through the entire thing ๐Ÿ˜ญ๐Ÿซถ

๐Ÿ“ฆ where this page comes from