RFC 7636
Proof Key for Code Exchange by OAuth Public Clients
Proof Key for Code Exchange by OAuth Public Clients πβ¨
Okay bestie, this one is RFC 7636 π. It was written by N. Sakimura (Ed.) of Nomura Research Institute, J. Bradley of Ping Identity, and N. Agarwal of Google. It's a Standards Track document in the IETF stream, with ISSN 2070-1721, and it was published in September 2015 π . The title block doesn't list anything it obsoletes or updates, so it's not replacing or patching any older RFC π .
Abstract π
OAuth 2.0 public clients that use the Authorization Code Grant are open to the authorization code interception attack π. This spec explains how that attack works and gives you a way to shut it down using Proof Key for Code Exchange (PKCE, pronounced "pixy") π§.
Status of This Memo πΈ
This is an Internet Standards Track document, so no cap, it's official π.
This document comes from the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check out Section 2 of RFC 5741 π.
For the current status of this document, any errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc7636 π¦.
Copyright Notice π
Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stood on the publication date. Please read these carefully, because they spell out your rights and restrictions for this document π. Code Components pulled from this document must include the 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. Protocol Flow ..............................................5
2. Notational Conventions ..........................................6
3. Terminology .....................................................7
3.1. Abbreviations ..............................................7
4. Protocol ........................................................8
4.1. Client Creates a Code Verifier .............................8
4.2. Client Creates the Code Challenge ..........................8
4.3. Client Sends the Code Challenge with the
Authorization Request ......................................9
4.4. Server Returns the Code ....................................9
4.4.1. Error Response ......................................9
4.5. Client Sends the Authorization Code and the Code
Verifier to the Token Endpoint ............................10
4.6. Server Verifies code_verifier before Returning the
Tokens ....................................................10
5. Compatibility ..................................................11
6. IANA Considerations ............................................11
6.1. OAuth Parameters Registry .................................11
6.2. PKCE Code Challenge Method Registry .......................11
6.2.1. Registration Template ..............................12
6.2.2. Initial Registry Contents ..........................13
7. Security Considerations ........................................13
7.1. Entropy of the code_verifier ..............................13
7.2. Protection against Eavesdroppers ..........................13
7.3. Salting the code_challenge ................................14
7.4. OAuth Security Considerations .............................14
7.5. TLS Security Considerations ...............................15
8. References .....................................................15
8.1. Normative References ......................................15
8.2. Informative References ....................................16
Appendix A. Notes on Implementing Base64url Encoding without
Padding .............................................17
Appendix B. Example for the S256 code_challenge_method ...........17
Acknowledgements ..................................................19
Authors' Addresses ................................................20
1. Introduction β¨
OAuth 2.0 [RFC6749] public clients are open to the authorization code interception attack π.
In this attack, the attacker grabs the authorization code that the authorization endpoint sends back, over a communication path that isn't protected by Transport Layer Security (TLS). An example is inter-application communication inside the client's operating system π±.
Once the attacker has the authorization code, they can use it to get the access token π.
Figure 1 shows the attack visually π. In step (1), the native application on the end device, like a smartphone, sends an OAuth 2.0 Authorization Request through the browser or operating system. In this case the Redirection Endpoint URI usually uses a custom URI scheme π. Step (1) happens through a secure API that can't be intercepted, though in advanced attack scenarios it might be observed π. The request then gets forwarded to the OAuth 2.0 authorization server in step (2). Since OAuth requires TLS, this traffic is protected and can't be intercepted π. The authorization server sends back the authorization code in step (3). In step (4), the Authorization Code gets returned to the requester through the Redirection Endpoint URI that was given in step (1) π¦.
Here's the catch: a malicious app can register itself as a handler for the custom scheme, right alongside the legit OAuth 2.0 app π¬. Once it does, the malicious app can grab the authorization code in step (4). That lets the attacker request and get an access token in steps (5) and (6), in that order π.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| End Device (e.g., Smartphone) |
| |
| +-------------+ +----------+ | (6) Access Token +----------+
| |Legitimate | | Malicious|<--------------------| |
| |OAuth 2.0 App| | App |-------------------->| |
| +-------------+ +----------+ | (5) Authorization | |
| | ^ ^ | Grant | |
| | \ | | | |
| | \ (4) | | | |
| (1) | \ Authz| | | |
| Authz| \ Code | | | Authz |
| Request| \ | | | Server |
| | \ | | | |
| | \ | | | |
| v \ | | | |
| +----------------------------+ | | |
| | | | (3) Authz Code | |
| | Operating System/ |<--------------------| |
| | Browser |-------------------->| |
| | | | (2) Authz Request | |
| +----------------------------+ | +----------+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Figure 1: Authorization Code Interception Attack
A few pre-conditions have to line up for this attack to work π§©:
- The attacker gets a malicious app onto the client device and registers a custom URI scheme that another app also uses. The operating systems have to let multiple apps register the same custom URI scheme π².
- The OAuth 2.0 authorization code grant is being used π.
- The attacker has access to the OAuth 2.0 [RFC6749] "client_id" and "client_secret" (if one was provisioned). Every OAuth 2.0 native app client instance uses the same "client_id". Secrets provisioned inside client binary apps can't be treated as confidential π«£.
- One of the following conditions has to be met:
- 4a. The attacker (through the installed app) can only observe responses from the authorization endpoint. When the "code_challenge_method" value is "plain", only this attack gets mitigated π.
- 4b. A more sophisticated attack scenario lets the attacker observe requests (as well as responses) to the authorization endpoint. The attacker still can't act as a man in the middle. This happened because of leaked http log info in the OS πͺ΅. To mitigate it, the "code_challenge_method" value must be set to either "S256" or a value defined by a cryptographically secure "code_challenge_method" extension π‘οΈ.
It's a long list of pre-conditions, I know π , but this attack has been seen in the wild and has to be taken seriously in OAuth 2.0 deployments π¨. The OAuth 2.0 threat model (Section 4.4.1 of [RFC6819]) does describe mitigation techniques, but unfortunately they don't work here, because they depend on a per-client instance secret or a per-client instance redirect URI π.
So how does this extension fix it? β¨ It uses a dynamically created, cryptographically random key called the "code verifier". A unique code verifier is made for every authorization request. Its transformed value, called the "code challenge", goes to the authorization server to get the authorization code. The client then sends the authorization code to the token endpoint along with the "code verifier", and the server compares it against the code challenge it got earlier. That's how the client proves it holds the "code verifier" ποΈ. It works as a mitigation because the attacker won't know this one-time key, since it's sent over TLS and can't be intercepted π .
To be continued, bestie! π«Ά Part 2 is coming up next π
1.1. Protocol Flow π¦
okay so here's the big picture, bestie π§ Figure 2 shows the whole PKCE dance in abstract form, and it's lowkey so clean.
+-------------------+
| Authz Server |
+--------+ | +---------------+ |
| |--(A)- Authorization Request ---->| | |
| | + t(code_verifier), t_m | | Authorization | |
| | | | Endpoint | |
| |<-(B)---- Authorization Code -----| | |
| | | +---------------+ |
| Client | | |
| | | +---------------+ |
| |--(C)-- Access Token Request ---->| | |
| | + code_verifier | | Token | |
| | | | Endpoint | |
| |<-(D)------ Access Token ---------| | |
+--------+ | +---------------+ |
+-------------------+
Figure 2: Abstract Protocol Flow
This spec adds some extra parameters to the OAuth 2.0 Authorization and Access Token Requests, and Figure 2 shows the idea in abstract form β¨
Here's how it goes, step by step π
- A. The client makes and keeps a secret called the "code_verifier". Then it derives a transformed version, "t(code_verifier)" (we call that the "code_challenge"), and sends it in the OAuth 2.0 Authorization Request together with the transformation method "t_m". π
- B. The Authorization Endpoint responds like it normally does, but it also remembers "t(code_verifier)" and the transformation method. π§
- C. The client sends the authorization code in the Access Token Request like usual, except this time it includes the "code_verifier" secret from step (A). π
- D. The authorization server transforms "code_verifier" and checks whether the result matches the "t(code_verifier)" it saved in (B). If they don't match, access is denied. π ββοΈ
So here's the payoff π₯Ή Someone who sneaks the authorization code at (B) can't trade it in for an access token, because they don't have the "code_verifier" secret. Main character defense, honestly π
2. Notational Conventions π
okay the key words first π The words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are read the way "Key words for use in RFCs to Indicate Requirement Levels" [RFC2119] describes. If those words show up in lowercase, they just mean what they mean in normal English, no cap πΈ
This spec uses the Augmented Backus-Naur Form (ABNF) notation from [RFC5234] β¨
Here's the vocab π
STRINGis a sequence of zero or more ASCII [RFC20] characters.OCTETSis a sequence of zero or more octets.ASCII(STRING)is the octets you get from the ASCII [RFC20] representation ofSTRING, whereSTRINGis a sequence of zero or more ASCII characters.BASE64URL-ENCODE(OCTETS)is the base64url encoding ofOCTETS, done as described in Appendix A, and it produces aSTRING. π«ΆBASE64URL-DECODE(STRING)is the base64url decoding ofSTRING, done as described in Appendix A, and it produces a sequence of octets.SHA256(OCTETS)is a SHA2 256-bit hash [RFC6234] ofOCTETS. π₯
3. Terminology π§
Besides the terms already defined in OAuth 2.0 [RFC6749], this spec defines a few new ones. Let's go π
code verifier A cryptographically random string that links the authorization request to the token request. Think of it as the secret handshake π€«
code challenge A challenge that comes from the code verifier. It gets sent in the authorization request and gets checked later. π
code challenge method The method that was used to derive the code challenge. π¦
Base64url Encoding Base64 encoding that uses the URL- and filename-safe character set from Section 5 of [RFC4648]. All trailing '=' characters are dropped (which Section 3.2 of [RFC4648] allows), and there are no line breaks, whitespace, or other extra characters. (Appendix A has notes on doing base64url encoding without padding, if you're curious π)
3.1. Abbreviations π
- ABNF: Augmented Backus-Naur Form
- Authz: Authorization
- PKCE: Proof Key for Code Exchange
- MITM: Man-in-the-middle
- MTI: Mandatory To Implement
4. Protocol π
4.1. Client Creates a Code Verifier π
First up, the client makes a code verifier, code_verifier, for every OAuth 2.0 [RFC6749] Authorization Request. It's built like this:
code_verifier = high-entropy cryptographic random STRING using the
unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
from Section 2.3 of [RFC3986], with a minimum length of 43 characters
and a maximum length of 128 characters.
Here's the ABNF for code_verifier π€
code-verifier = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39
NOTE: The code verifier SHOULD have enough entropy to make it impractical to guess the value. It is RECOMMENDED that the output of a suitable random number generator be used to create a 32-octet sequence. The octet sequence is then base64url-encoded to produce a 43-octet URL safe string to use as the code verifier. π
4.2. Client Creates the Code Challenge πͺ
Next, the client turns the code verifier into a code challenge using one of these two transformations:
- plain:
code_challenge = code_verifier - S256:
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
If the client can use "S256", it MUST use "S256", because "S256" is Mandatory To Implement (MTI) on the server. Clients may use "plain" only when they can't support "S256" for some technical reason and they know, through out-of-band configuration, that the server supports "plain". π¨
The plain transformation is there for compatibility with existing deployments and for constrained environments that can't use the S256 transformation. π§Έ
Here's the ABNF for code_challenge π
code-challenge = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39
4.3. Client Sends the Code Challenge with the Authorization Request π¨
The client sends the code challenge as part of the OAuth 2.0 Authorization Request (Section 4.1.1 of [RFC6749]), along with these extra parameters:
code_challenge: REQUIRED. The code challenge.code_challenge_method: OPTIONAL. If it's not in the request, it defaults to "plain". The transformation method is either "S256" or "plain". π¦
4.4. Server Returns the Code π
When the server issues the authorization code in the authorization response, it MUST associate the code_challenge and code_challenge_method values with that code so it can verify things later. β
Usually the code_challenge and code_challenge_method values get stored in encrypted form inside the code itself, but the server could also keep them on its own side, linked to the code. The server MUST NOT include the code_challenge value in client requests in a form that other entities can extract. π
ββοΈ
How the server links the code_challenge to the issued code is out of scope for this spec, so that part's on the server's team π
4.4.1. Error Response π«
If the server requires Proof Key for Code Exchange (PKCE) from OAuth public clients, and the client doesn't send the code_challenge in the request, the authorization endpoint MUST return the authorization error response with the error value set to invalid_request. The error_description or the response of error_uri SHOULD explain what went wrong, e.g., code challenge required. π₯²
If the server supports PKCE but doesn't support the requested transformation, the authorization endpoint MUST return the authorization error response with the error value set to invalid_request. The error_description or the response of error_uri SHOULD explain what went wrong, e.g., transform algorithm not supported. π
4.5. Client Sends the Authorization Code and the Code Verifier to the Token Endpoint ποΈ
Once the client has the authorization code, it sends the Access Token Request to the token endpoint. On top of the parameters from the OAuth 2.0 Access Token Request (Section 4.1.3 of [RFC6749]), it also sends this one:
code_verifier: REQUIRED. The code verifier.
The code_challenge_method is bound to the authorization code when the code is issued. That's the method the token endpoint MUST use to verify the code_verifier. π
4.6. Server Verifies code_verifier before Returning the Tokens β
When the token endpoint gets the request, the server checks it by working out the code challenge from the received code_verifier, transforming it according to the code_challenge_method the client specified, and comparing the result with the code_challenge it saved earlier. π΅οΈββοΈ
If the code_challenge_method from Section 4.3 was "S256", the received code_verifier gets hashed with SHA-256, base64url-encoded, and then compared to the code_challenge, like this:
BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) == code_challenge
If the code_challenge_method from Section 4.3 was "plain", the two values get compared directly, like this:
code_verifier == code_challenge
If the values match, the token endpoint MUST keep processing as normal (as defined by OAuth 2.0 [RFC6749]). If they don't match, it MUST return an error response indicating "invalid_grant", as described in Section 5.2 of [RFC6749]. π ββοΈπ
5. Compatibility π
Server implementations of this spec MAY accept OAuth 2.0 clients that don't implement this extension. If the server doesn't receive a code_verifier from the client in the Authorization Request, servers that support backwards compatibility just go back to the plain OAuth 2.0 [RFC6749] protocol without this extension. π«Ά
Since this spec doesn't change the OAuth 2.0 [RFC6749] server responses, client implementations don't need to know whether the server has implemented this spec. They SHOULD send the additional parameters defined in Section 4 to all servers. β¨
6. IANA Considerations π§Ύ
IANA has made the following registrations under this document. π
6.1. OAuth Parameters Registry ποΈ
This spec registers the following parameters in the IANA "OAuth Parameters" registry defined in OAuth 2.0 [RFC6749]:
o Parameter name: code_verifier
o Parameter usage location: token request
o Change controller: IESG
o Specification document(s): RFC 7636 (this document)
o Parameter name: code_challenge
o Parameter usage location: authorization request
o Change controller: IESG
o Specification document(s): RFC 7636 (this document)
o Parameter name: code_challenge_method
o Parameter usage location: authorization request
o Change controller: IESG
o Specification document(s): RFC 7636 (this document)
6.2. PKCE Code Challenge Method Registry β¨
okay so this spec creates a brand new registry called "PKCE Code Challenge Methods" π, and it should be a sub-registry of the "OAuth Parameters" registry π
New code_challenge_method types for the authorization endpoint get registered under the Specification Required policy [RFC5226]. That means one or more Designated Experts (DEs) have to review the request π§ The DEs make sure there's at least a two-week review of the request on the oauth-ext-review@ietf.org mailing list, and that any discussion there converges before they respond π«Ά To allow values to be allocated before publication, the Designated Expert(s) may approve registration once they're satisfied that an acceptable specification will be published β¨
Registration requests and discussion on the oauth-ext-review@ietf.org mailing list should use an appropriate subject, such as "Request for PKCE code_challenge_method: example") π
The Designated Expert(s) should consider the discussion on the mailing list, as well as the overall security properties of the challenge method, when evaluating registration requests. New methods should not disclose the value of the code_verifier in the request to the Authorization endpoint π Denials should include an explanation and, if applicable, suggestions as to how to make the request successful πΈ
6.2.1. Registration Template π
- Code Challenge Method Parameter Name: The name requested (e.g., "example"). Because a core goal of this specification is for the resulting representations to be compact, it is RECOMMENDED that the name be short -- not to exceed 8 characters without a compelling reason to do so. This name is case-sensitive. Names may not match other registered names in a case-insensitive manner unless the Designated Expert(s) states that there is a compelling reason to allow an exception in this particular case. π
- Change Controller: For Standards Track RFCs, state "IESG". For others, give the name of the responsible party. Other details (e.g., postal address, email address, and home page URI) may also be included. π
- Specification Document(s): Reference to the document(s) that specifies the parameter, preferably including URI(s) that can be used to retrieve copies of the document(s). An indication of the relevant sections may also be included but is not required. π¦
6.2.2. Initial Registry Contents π§
Per this document, IANA has registered the Code Challenge Method Parameter Names defined in Section 4.2 in this registry.
- Code Challenge Method Parameter Name:
plain - Change Controller: IESG
- Specification Document(s): Section 4.2 of RFC 7636 (this document)
- Code Challenge Method Parameter Name:
S256 - Change Controller: IESG
- Specification Document(s): Section 4.2 of RFC 7636 (this document)
7. Security Considerations π
7.1. Entropy of the code_verifier π²
bestie, the whole security model relies on the attacker never learning or guessing the code verifier π It is vitally important to stick to this principle. So the code verifier has to be cryptographically random with high entropy, so it's not practical for an attacker to guess π₯
The client SHOULD create a "code_verifier" with a minimum of 256 bits of entropy. The easy way is to have a suitable random number generator create a 32-octet sequence. That octet sequence can then be base64url-encoded to produce a 43-octet URL safe string to use as a "code_challenge" that has the required entropy β¨
7.2. Protection against Eavesdroppers π
Clients MUST NOT downgrade to "plain" after trying the "S256" method π« Servers that support PKCE are required to support "S256", and servers that do not support PKCE will simply ignore the unknown "code_verifier". Because of this, an error when "S256" is presented can only mean that the server is faulty or that a MITM attacker is trying a downgrade attack π
The "S256" method protects against eavesdroppers observing or intercepting the "code_challenge", because the challenge cannot be used without the verifier π‘οΈ With the "plain" method, there is a chance that "code_challenge" will be observed by the attacker on the device or in the http request. Since the code challenge is the same as the code verifier in this case, the "plain" method does not protect against the eavesdropping of the initial request π±
The use of "S256" protects against disclosure of the "code_verifier" value to an attacker π
Because of this, "plain" SHOULD NOT be used and exists only for compatibility with deployed implementations where the request path is already protected. The "plain" method SHOULD NOT be used in new implementations, unless they cannot support "S256" for some technical reason π ββοΈ
The "S256" code challenge method or other cryptographically secure code challenge method extension SHOULD be used. The "plain" code challenge method relies on the operating system and transport security not to disclose the request to an attacker π
If the code challenge method is "plain" and the code challenge is to be returned inside authorization "code" to achieve a stateless server, it MUST be encrypted in such a manner that only the server can decrypt and extract it. π¨
7.3. Salting the code_challenge π§
To reduce implementation complexity, salting is not used in the production of the code challenge, as the code verifier contains sufficient entropy to prevent brute-force attacks. Concatenating a publicly known value to a code verifier (containing 256 bits of entropy) and then hashing it with SHA256 to produce a code challenge would not increase the number of attempts necessary to brute force a valid value for code verifier π§
While the "S256" transformation is like hashing a password, there are important differences. Passwords tend to be relatively low-entropy words that can be hashed offline and the hash looked up in a dictionary. By concatenating a unique though public value to each password prior to hashing, the dictionary space that an attacker needs to search is greatly expanded π
Modern graphics processors now allow attackers to calculate hashes in real time faster than they could be looked up from a disk. This eliminates the value of the salt in increasing the complexity of a brute-force attack for even low-entropy passwords π€
7.4. OAuth Security Considerations π‘οΈ
All the OAuth security analysis presented in [RFC6819] applies, so readers SHOULD carefully follow it π
7.5. TLS Security Considerations π
Current security considerations can be found in "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" [BCP195]. This supersedes the TLS version recommendations in OAuth 2.0 [RFC6749] π
8. References π
8.1. Normative References
[BCP195] Sheffer, Y., Holz, R., and P. Saint-Andre, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)", BCP 195, RFC 7525, May 2015, http://www.rfc-editor.org/info/bcp195.
[RFC20] Cerf, V., "ASCII format for network interchange", STD 80, RFC 20, DOI 10.17487/RFC0020, October 1969, http://www.rfc-editor.org/info/rfc20.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, http://www.rfc-editor.org/info/rfc2119.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, http://www.rfc-editor.org/info/rfc3986.
[RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, http://www.rfc-editor.org/info/rfc4648.
[RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, DOI 10.17487/RFC5226, May 2008, http://www.rfc-editor.org/info/rfc5226.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, http://www.rfc-editor.org/info/rfc5234.
[RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011, http://www.rfc-editor.org/info/rfc6234.
[RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012, http://www.rfc-editor.org/info/rfc6749.
8.2. Informative References
[RFC6819] Lodderstedt, T., Ed., McGloin, M., and P. Hunt, "OAuth 2.0 Threat Model and Security Considerations", RFC 6819, DOI 10.17487/RFC6819, January 2013, http://www.rfc-editor.org/info/rfc6819.
Appendix A. Notes on Implementing Base64url Encoding without Padding π§ββοΈ
This appendix describes how to implement a base64url-encoding function without padding, based upon the standard base64-encoding function that uses padding. π·
To be concrete, example C# code implementing these functions is shown below. Similar code could be used in other languages π»
static string base64urlencode(byte [] arg)
{
string s = Convert.ToBase64String(arg); // Regular base64 encoder
s = s.Split('=')[0]; // Remove any trailing '='s
s = s.Replace('+', '-'); // 62nd char of encoding
s = s.Replace('/', '_'); // 63rd char of encoding
return s;
}
An example correspondence between unencoded and encoded values follows. The octet sequence below encodes into the string below, which when decoded, reproduces the octet sequence β¨
3 236 255 224 193
A-z_4ME
Appendix B. Example for the S256 code_challenge_method π
okay so this appendix is the worked example, and it's giving full step-by-step tutorial π The client uses the output of a suitable random number generator to make a 32-octet sequence β¨ In this example, the octets (written as a JSON array) are:
[116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173,
187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83,
132, 141, 121]
Next, base64url-encoding that octet sequence gives you the value of the code_verifier π¦
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Then the code_verifier gets hashed with the SHA256 hash function, which produces:
[19, 211, 30, 150, 26, 26, 216, 236, 47, 22, 177, 12, 76, 152, 46,
8, 118, 168, 120, 173, 109, 241, 68, 86, 110, 225, 137, 74, 203,
112, 249, 195]
Base64url-encoding that octet sequence gives you the code_challenge πΈ
E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
The authorization request includes the code_challenge and the method, like so π
code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
Then the authorization server records the code_challenge and code_challenge_method along with the code that's granted to the client π§
In the request to the token_endpoint, the client sends the code it got in the authorization response, plus this extra parameter:
code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
The authorization server looks up the info for the code grant π Since the recorded code_challenge_method is S256, it hashes and base64url-encodes the code_verifier:
BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
Then it compares that calculated value with the value of "code_challenge":
BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) == code_challenge
If the two values match, the authorization server can hand over the tokens, as long as there are no other errors in the request π If they don't match, the request must be rejected, and an error gets returned π
Acknowledgements π«Ά
okay the big thank-you moment π₯Ή The initial draft of this spec was made by the OpenID AB/Connect Working Group of the OpenID Foundation π
This spec is the work of the OAuth Working Group, which has dozens of active and dedicated participants π These people in particular contributed ideas, feedback, and wording that shaped the final spec:
- Anthony Nadalin, Microsoft
- Axel Nenker, Deutsche Telekom
- Breno de Medeiros, Google
- Brian Campbell, Ping Identity
- Chuck Mortimore, Salesforce
- Dirk Balfanz, Google
- Eduardo Gueiros, Jive Communications
- Hannes Tschonfenig, ARM
- James Manger, Telstra
- Justin Richer, MIT Kerberos
- Josh Mandel, Boston Children's Hospital
- Lewis Adam, Motorola Solutions
- Madjid Nakhjiri, Samsung
- Michael B. Jones, Microsoft
- Paul Madsen, Ping Identity
- Phil Hunt, Oracle
- Prateek Mishra, Oracle
- Ryo Ito, mixi
- Scott Tomilson, Ping Identity
- Sergey Beryozkin
- Takamichi Saito
- Torsten Lodderstedt, Deutsche Telekom
- William Denniss, Google
Authors' Addresses π¦
Here are the people who wrote it, with their contact details π
Nat Sakimura (editor) π
Nat Sakimura (editor)
Nomura Research Institute
1-6-5 Marunouchi, Marunouchi Kitaguchi Bldg.
Chiyoda-ku, Tokyo 100-0005
Japan
Phone: +81-3-5533-2111
Email: n-sakimura@nri.co.jp
URI: http://nat.sakimura.org/
John Bradley β
John Bradley
Ping Identity
Casilla 177, Sucursal Talagante
Talagante, RM
Chile
Phone: +44 20 8133 3718
Email: ve7jtb@ve7jtb.com
URI: http://www.thread-safe.com/
Naveen Agarwal πΈ
Naveen Agarwal
Google
1600 Amphitheatre Parkway
Mountain View, CA 94043
United States
Phone: +1 650-253-0000
Email: naa@google.com
URI: http://google.com/
π¦ where this page comes from
- ietf: rfc7636 2015-09
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms