In attempting to implement OAuth2 into a natively installed client application, we face the problem that we cannot securely store the pre-shared client secret. After doing some research, I came across PKCE, which I had not previously heard of. Swapping out the client secret for a short-lived nonce seems like a reasonable idea to me, but I can't figure out how we protect against what seems like a fairly clear man-in-the-middle attack. My thinking is thus:
The flow starts with Alice sending bob a hashed code challenge along with some assertion of her identity (like a session token). The challenge is hashed because it cannot be assumed to be secure. The server stores the hashed code challenge but otherwise follows basic OAuth2 and returns an authorisation code. All good so far.
The next step is for Alice to send the authorisation code and the now un-hashed code challenge back to Bob, now all encrypted in an HTTPS POST request. Bob can validate the code challenge by hashing the value and comparing it with the previous hash, and generate an access token for the authorisation code.
I understand that the reason this is "more secure" is because an interceptor ("Eve") would not have the plain text code challenge value in the second step, and thus, even if they heard the authorisation code, wouldn't be able to request an access token. My concern is, though, could Eve not just intercept the initial request and swap out the hashed code challenge for the hash of challenge she created herself? (In practice, I would imagine this being something akin to returning a false 302 response which redirects the user with a swapped out hash in the QS)Then the authorisation code would be associated with that challenge and not Alice's!
I've gone round this a few times and flip flopped between being happy I've understood it and not convinced, so it's probably a case I've thought about this too much. But if someone could explain why I am wrong in plain English I would much appreciate it :)
Thanks in advance!