oauth-2.0azure-ad-b2copenid-connectpkce

code_challange vs state parameter in OAuth? What is the difference?


I'm trying to understand the difference between code_challange and state parameter from OAuth 2.0 Authorization Code Flow + PKCE.

I know that state parameter is a validation against CSRF attack and is generated (and saved in local storage) on Client (eg. Angular SPA) - and need to be returned from Authorization application in callback after successful login and compared with state value saved previously on local storage.

Whereas code_challange is generated based on code_verifier also genereated and saved in localstorage. So where is the differance with usage?

Also I've noted strange thing - I copied generated auth url which is: https://APP_ADDRESS.b2clogin.com/APP_ADDRESS.onmicrosoft.com/b2c_signupsignin/oauth2/v2.0/authorize?client_id=f9d2b[...]&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fauth-callback&response_type=code&scope=f9d2b[...]%20openid&state=31caa207[...]&code_challenge=-MefGRhOo[...]&code_challenge_method=S256&response_mode=query

And I used that url in different browser. And I was able to login successfuly. I only had an error in console: No matching state found in storage. Which make sense since local storage was empty in new browser.

But why there wasn't any error about the code_challange? I think it shouldn't be able to login successful, or I miss something?


Solution

  • With PKCE, the checks that the code_challenge is correct is done on the authentication server-side and the check for valid state is done on the client-side.

    There are cases where the client does not check the state/nonce properly (or not at all) and we added PKCE to let the auth-server do the check instead. The auth server can force/require that all clients follow the PKCE concept.

    Together we get a very strong protection.

    The picture below shows how PKCE works

    enter image description here

    I recently blogged about the state parameter here: