Reputation: 1461
In https://www.rfc-editor.org/rfc/rfc7636#section-4.4 it is stated that the challenge can be associated with the authorization code by including it in the code, but only in encrypted form (alternatively store it on the server, which is not related to my question). Why must it be encrypted?
It seems obvious to me that the challenge should not be possible to alter, because then a later request for an access code could include a new challenge that was never presented to the server, and for which an attacker conveniently has a code verifier ready. However, to protect against modification, it would be sufficient to include a signature in the authorization code -- encrypting the challenge would not be necessary.
Section 4.4 also says that "The server MUST NOT include the "code_challenge" value in client requests in a form that other entities can extract". Suppose that either the requestor or a third party could extract the code challenge -- why is that harmful? The requestor already knows the code challenge, and a third-party attacker cannot derive the code verifier from it.
Upvotes: 1
Views: 748
Reputation: 2243
The whole point of Proof Key for Code Exchange (PKCE) is to prevent request interception and reuse attacks. It achieves this by requiring a code verifier with every request between the client and the authorization server. These code verifier's are:
code
), issued by the authorization server.code_verifier
), a high-entropy secret used to prove the client’s legitimacy.code_challenge
), which is derived from the code_verifier
(usually SHA-256 + Base64) and sent in the initial request.When the client first requests authorization, it sends the code_challenge
and code_challenge_method
to the authorization server. Since the code_challenge
is just a hash of the code_verifier
, it isn’t encrypted. Once the user is authenticated, the authorization server stores the code_challenge
and returns an authorization code (code
) to the client.
According to the RFC:
When the server issues the authorization
code
in the authorization response, it MUST associate thecode_challenge
andcode_challenge_method
values with the authorization code so it can be verified later.
code
) can be issuedThere are two ways the authorization server can issue the code
:
One method is to generate a random code
and store it in the database, along with the code_challenge
, code_challenge_method
, and the user’s ID. When the client later exchanges the code
for a token, the server retrieves the stored data and verifies it. Since the code_challenge
is never exposed outside the server, this approach is inherently secure.
Another approach is to derive the code
itself using the user’s ID, code_challenge
, and code_challenge_method
, instead of storing them in a database. This allows the server to later extract the code_challenge
and code_challenge_method
from the code
without any need of a Database.
However, this introduces a security risk: if the authorization code
is intercepted, an attacker could also extract the code_challenge
and code_challenge_method
weakening the PKCE mechanism.
To mitigate this risk, the RFC suggests encrypting the code
in stateless implementations:
Typically, the "code_challenge" and "code_challenge_method" values are stored in encrypted form within the "code" itself (statless), but alternatively, they could be stored on the server (stateful). The server MUST NOT include the
code_challenge
in client requests in a form that other entities can extract.
In other words, if the code
itself contains the code_challenge
, it must be encrypted so that only the authorization server can extract it. Without encryption, an attacker who intercepts the code
could potentially bypass the PKCE protections.
Upvotes: 0
Reputation: 1
The instructions in https://www.rfc-editor.org/rfc/rfc7636#section-4.4 apply to a generic code_challenge_method
.
If the "plain" method is used, where code_challenge
equals code_verifier
, and the server does not protect (encrypt) the code_challenge
, an attacker can obtain both the code_verifier
and the authorization_code
to forge a malicious access token request.
Upvotes: 0
Reputation: 35
Why must it be encrypted?
With PKCE implementation the authorization server does not have the client secret. It uses the code_challenge
(an encrypted form of code_verifier
). you can treat code_verifier
as client_secret
. Since client_secret
cannot be sent through the front channel we are encrypting it. Once the authorization_code
is generated see section 4.6 how the authorization server verifies it. Here authorization_code
and code_challenge
are sent through the back channel.
Upvotes: 0