PKCE explanation: https://www.oauth.com/oauth2-servers/pkce/

OAuth Flow example: https://developer.okta.com/docs/guides/implement-auth-code-pkce/use-flow/

My question is more specifically: Is there any reason to require state if PKCE is implemented?

state stops CSRF attacks by having the app server verify the state it gave the client is the same as the state the client gives it (after making the first OAuth request)

  1. App Server generates random state for each unique client & gives to client
  2. Client sends state to Auth Server, Auth Server returns with state & code
  3. Client sends state and code to App Server
  4. App Server ensures state in step 1 == state in step 2

However if you did this with PKCE:

  1. App Server generates random code_challenge for each unique client & gives it to the client (we can ignore the optional hashing for now)
  2. Client gives code_challenge to the Auth Server, Auth Server returns with code
  3. Client sends code to App Server
  4. App Server sends code & code_challenge in step 1 to Auth Server who verifies that code_challenge in step 1 == code_challenge in step 2

It seems like the exact same flow, except you have to store the code_challenge on your server instead of state being stored in either your server or the client's cookies and the end check is done by the Auth Server instead of the App Server.


The state is given back by the OAuth2 server in the redirected url, so the client app can verify that the request to open the authorization page was indeed triggered by itself.

The code_challenge is not given back by the OAuth2 server, but the client app must send the belonging code_verifier with the next request to exchange the authorization code for a token. The OAuth2 server can then be sure that it is the same client app which did the first request to open the authorization page.

Even if an attacker listened to the first request and the following redirect, (s)he cannot know the code_verifier, it is never sent over the wire. This makes it impossible to (mis)use the redirect and impersonate the client to get the token.

So yes both are required, the state makes the link between the open-authorization-page-request and the redirect, and the code_challenge makes the link between open-authorization-page-request and exchange-code-for-token-request.

  • Great answer! An RFC document related to OAuth2 best practices brought unnecessary confusion regarding state and PKCE. The document is here: tools.ietf.org/html/… It states the following: If PKCE [RFC7636] is used by the client and the authorization server supports PKCE, clients MAY opt to not use "state" for CSRF protection, as such protection is provided by PKCE. Some of my colleagues suggested that we don't need state anymore, as PKCE will do its work, but as you have pointed out, they serve different purpose.
    – luben
    Sep 14 '20 at 18:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.