-
Notifications
You must be signed in to change notification settings - Fork 109
Description
Per the OAuth PKCE RFC: https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
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.
But the implementation of this method in OAuth2\AbstractProvider::generatePKCECodeVerifier() handles this incorrectly.
- it accepts length, defaults to 128
- it then checks if this length is >= 43 and <= 128. So far so good.
- it generates random bytes with this length
- encodes these random bytes to base64 and returns this value
When you encode 128 bytes to base64, you will now have a string that is longer than 128.
We discovered this bug when implementing PKCE authentication with Auth0. They specifically check the length of code_verifier, and throw an error if the length is > 128 or < 43.
The valid number of bytes to generate would be 32 - 96, which then encoded to base64 will net 43 - 128.
See:
auth/src/OAuth2/AbstractProvider.php
Lines 63 to 71 in ee93abe
| private function generatePKCECodeVerifier(int $length = 128) | |
| { | |
| if ($length < 43 || $length > 128) { | |
| throw new \Exception("Length must be between 43 and 128"); | |
| } | |
| $randomBytes = random_bytes($length); | |
| return rtrim(strtr(base64_encode($randomBytes), '+/', '-_'), '='); | |
| } |