3

If I was developing a web app client that would be served statically, I would need to either use the implicit grant flow (which is no longer advisable) or use the authorization code grant flow with PKCE. Given that I'm developing a web app client that will be served dynamically by a server, it's possible for me to utilize an authorization code grant flow in OAuth 2.0 without using PKCE -- the callback and subsequent token request will be handled server-side and the client secret can be stored securely on the server.

However, it would still be possible for me to utilize PKCE in this case (the server can generate the necessary code verifier instead of the client app). So my question is, is there any advantage to using one approach over the other (providing the client secret vs utilize PKCE). Is one more secure than the other in this context?

2

It boils down to whether there is a chance your authorization code might leak.

PKCE is about preventing leaked "authorization code"s from being useful. When you ask for an authorization code, PKCE requires you to send the hash of a nonce. When you redeem the code, you must provide the original nonce.

This means that a malicious actor (XSS or CSRF vulnerability) observing the authorization code request and response cannot redeem the code, as they don't know the nonce.

Edit: Additionally, the client_secret means that only your server can redeem authorization codes. But, anyone can send messages to your server! If the authorization code has been leaked, then that means you don't know who is sending your server the authorization code -- is it the person who initially asked for it or some eavesdropping app? Without checking the nonce, your server may end up using its client_secret to redeem authorization codes for an eavesdropper.

5
  • Thanks. That makes sense, but then if we're already using a client secret, even if the authorization code is compromised the attacker still won't be able to do anything with it. Having both mechanisms seems redundant. Just wondering if one is better than the other. – Daniel Rearden Oct 11 '19 at 7:10
  • see edit above :) – jnnnnn Oct 11 '19 at 7:23
  • Have a look at this video which explains the issues with PKCE: youtube.com/watch?v=_zWovo2zv6k&ab_channel=PingIdentityTV – David Brossard Dec 3 '20 at 23:11
  • 1
    I'm sorry, but are you sure that the code_verifier and nonce are actually identical? – F8ER Feb 8 at 14:30
  • @F8ER code_verifier and nonce are not the same. See this article by Daniel Fett "PKCE vs. Nonce: Equivalent or Not?". In OpenID Connect, you could use both together. – lumiemp Feb 16 at 11:14
1

Following the OAuth 2.0 Security Best Current Practice, you should use PKCE:

Clients MUST prevent injection (replay) of authorization codes into the authorization response by attackers. Public clients MUST use PKCE [RFC7636] to this end. For confidential clients, the use of PKCE [RFC7636] is RECOMMENDED.

If you have any reason not to use PKCE, the use of OpenID Connect "nonce" can be an alternative.

With additional precautions, described in Section 4.5.3.2, confidential clients MAY use the OpenID Connect "nonce" parameter and the respective Claim in the ID Token [OpenID] instead.

This applies to both public clients/native apps/SPAs as well as confidential clients.

Note: Although PKCE was designed as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications.

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.