How does PKCE help public clients?

82 Views Asked by At

According to https://www.linkedin.com/advice/0/how-does-pkce-prevent-authorization-code-interception-attacks#why-use-pkce?

The attacker can then use the stolen code to request an access token from the token endpoint, impersonating the legitimate client. This is especially risky for public clients, which are applications that cannot store a client secret securely, such as native or single-page applications.

If the attacker has control over the user in a way that can prevent use of the authorization code, what's to stop them from obtaining the PKCE challenge too?

They obviously have complete control over the client.

2

There are 2 best solutions below

4
On BEST ANSWER

PKCE is there to ensure that it is the same client(application) that does both the initial authenticaton request and the request with the authorization code.

For example, in mobile apps or browser extensions, if a "evil" app gets the authorization code, then it should not be able to use it.

enter image description here

The problem is that multiple apps might try to register for the same redirect_uri in a mobile phone for example.

How can a hacker capture the redirect?

Mobile applications often register a custom scheme to receive the redirect request back from the STS:

app-name://?access_token=??????

For example:

com.googleusercontent.apps.123504760640ip7qq628i6dreavptfk981d9ji6x:/oauth2callback
com.googleusercontent.apps.5996697-7obf9q7equ9msfakdcg8iveqgn3sck1s:/oauth2callback
fb19884028963vimeo://authorize/fb1592193007691679://authorize/
x-msauth-azureiosapp://com.microsoft.azure
ms-whiteboard-iosauth://com.microsoft.whiteboard
mevo://vimeooauth
oreilly://oauth/complete

What if the hacker also registers the same scheme?

The clientID, the hacker can easilly by capturing a sample request from a mobile application.

0
On

when user logins, we create a challenge

import pkce from 'pkce-gen';

const challenge = pkce.create();
console.log('challnge', challenge);

// challnge {
  code_verifier: 'wM8w-unbwmv5UWNWxV3dftSLxEPVKJaoKC7bEPE0cOw',
  code_challenge: '2mMkAfg2efGKAA16b-0AXCPi7ISG6D6FWM_cbEc9ODo'
}

when we make the first request to oauth server we pass the code_challenge

code_challenge_method: 'S256',
code_challenge: challenge.code_challenge

the oauth server hashes this and resend it back to redirect url in the url as parameter. so in your callback api route

const code = url.searchParams.get('code') || null;

The code verifier is transformed (usually by using a hashing method) to create a code challenge, which is sent along with the authorization request.

Now client makes a POST request to the authorization server passing the code and the original challenge.code_verifier which is created in previous step. The authorization server checks if this code verifier matches the one used to create the code challenge.

As you see, with PKCE, this intercepted code alone is not enough to get tokens. The genuine client application also needs to provide the original code verifier during the token exchange. Without this verifier, the server won't grant access.