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?
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
I recently blogged about the state parameter here: