RFC 5849
The OAuth 1.0 Protocol
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 Notice โจ
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 ๐ฆ:
- 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.
- The resource owner authorizes the server to grant the client's access request (identified by the temporary credentials).
- 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:
- 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 โจ
- 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 ๐ซ
- 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 ๐๏ธ - 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_signatureparameter. ๐ - If using the
HMAC-SHA1orRSA-SHA1signature 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_versionparameter is present, ensuring its value is1.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
Hostrequest 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:
- 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). โจ - An
&character (ASCII code 38). - The base string URI from Section 3.4.1.2, after being encoded (Section 3.6).
- An
&character (ASCII code 38). - 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:
- The scheme and host MUST be in lowercase. ๐ก
- The host and port values MUST match the content of the HTTP request
Hostheader field. ๐ฏ - 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:
- First, the name and value of each parameter get encoded (Section 3.6). ๐
- 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. ๐
- 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. ๐ฆ
- 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:
- The client shared-secret, after being encoded (Section 3.6).
- An "&" character (ASCII code 38), which MUST be included even when either secret is empty. ๐จ
- 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:
- The client shared-secret, after being encoded (Section 3.6).
- An "&" character (ASCII code 38), which MUST be included even when either secret is empty. ๐จ
- 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: ๐
- The HTTP "Authorization" header field, as described in Section 3.5.1. ๐
- The HTTP request entity-body, as described in Section 3.5.2. ๐
- 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 ๐
- Parameter names and values are encoded per Parameter Encoding (Section 3.6).
- 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).
- Parameters are separated by a "," character (ASCII code 44) and OPTIONAL linear whitespace per [RFC2617].
- 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:
- 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 ๐
- 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
- ietf: rfc5849 2010-04
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms