Skip to main content
added 948 characters in body
Source Link
CBHacking
  • 54.1k
  • 3
  • 101
  • 147

I suspect your confusion is in how OAuth itself works, rather than anything about PKCE in particular. The purpose of OAuth is to allow an app (the OAuth client) to access identity information or resources from some other app/service (the OAuth server). Critically the OAuth app never sees any user credential, or access token, that the OAuth server uses for itself. That's the central point of OAuth; the ability for an app to use e.g. stuff in your Google account without getting general access to your Google account.

As such, a lot of your questions don't make much sense. I've tried to address them all below, with explanations and guesses as to where your confusion is and how things really work. Let me know (in a comment, or by editing the question) if something is still not adding up for you. It might help, in cases like that, to lay out your understanding of what's happening / how things work in considerable detail.


I suspect your confusion is in how OAuth itself works, rather than anything about PKCE in particular. The purpose of OAuth is to allow an app (the OAuth client) to access identity information or resources from some other app/service (the OAuth server). Critically the OAuth app never sees any user credential, or access token, that the OAuth server uses for itself. That's the central point of OAuth; the ability for an app to use e.g. stuff in your Google account without getting general access to your Google account.

As such, a lot of your questions don't make much sense. I've tried to address them all below, with explanations and guesses as to where your confusion is and how things really work. Let me know (in a comment, or by editing the question) if something is still not adding up for you. It might help, in cases like that, to lay out your understanding of what's happening / how things work in considerable detail.


Source Link
CBHacking
  • 54.1k
  • 3
  • 101
  • 147

the point of PKCE is to mitigate client-side credential hijacking

Sort of, but perhaps not in the way you mean. The point of PKCE is to mitigate theft of the authorization code, the short-lived secret that is returned from the Authorization Request (assuming authorization is granted) and then transmitted during the Authorization Code Exchange. This is technically a credential, but not in the sense of a password, access token, API key, etc; it has only one purpose, is single-use, and expires immediately whether or not it's used.

The typical attack vector for stealing authorization codes is to have an app that registers the URI scheme for a different app (e.g. a malicious app registers for Slack's URI scheme) and thus when the OAuth server tells your device to redirect to slack:...code=XXXX, the wrong app receives the code (and can immediately exchange it for an access token). PKCE mitigates this by requiring that the trusted app generate a "code challenge" secret, which the OAuth server associates with the authorization code that it generates and returns (but does not include the code challenge secret in the response).

For the next resource request, the logged-in client must generate a new code challenge pair and lodge the code challenge with the auth server at the /authorize endpoint

If you're using OAuth/OIDC for login, why is a logged-in client needing to contact (the same) OAuth server again anyhow; it should have received an access token / authorized resource access already? If you mean a different OAuth server, then sure, the app (OAuth client) will need to generate a new PKCE challenge, but that has nothing to do with the prior OAuth activity or the app's logged-in status.

In this case, the auth server will use the access token to authenticate the client request, no?

Assuming by "auth server" you mean OAuth server, "no" indeed. The use case for OAuth is when you don't have an access token (or at least, not one for the resource you're trying to access); access tokens often come to your app from OAuth servers, but never flow from your app to the OAuth server.

what stops a malicious user from using a hijacked token ...

If by "hijacked token" you mean "hijacked access token", nothing (or at least, nothing in OAuth; there can be other measures sometimes though none of them are very reliable). Once an OAuth server vends you (app) an access token, anybody could use it; it is your responsibility to keep it out of malicious hands. The OAuth standard has some opinions about things like how long the token should last and whether you should be able to refresh it without full re-authentication, but fundamentally, protecting the access token once it is sent to the OAuth client (app) is always the app's responsibility.

... using a hijacked token to illegitimately obtain access tokens

Again, if the hijacked token is an access token that was issued by the OAuth server, the thing stopping this from working is that the OAuth server is not looking for and does not care whether or not you send back the access token it sent you. The protection against a malicious client getting access tokens from the OAuth server is the same things it always is:

  • [user] don't run malicious apps
  • [user] if an OAuth server asks about authorization for a malicious/unexpected app then don't grant it
  • [OAuth servers] clearly indicate which app is requesting what authorization (so the user can decide whether or not to approve)
  • [app authors] specify a minimal scope of acceptable redirect URIs
  • [app authors] use a client secret (where possible) and don't expose it
  • [app authors] use the State secret and verify that it is correct and expected whenever you get a request to the OAuth redirection target (technically this is about preventing a malicious app from authorizing your app to a malicious account, but that basically counts since a malicious app will already have access to the malicious account)
  • [OAuth servers] verify the authorization code and challenge (and client secret, where present) correctly before returning the access token
  • [OAuth servers] don't redirect (send the authorization code) to URIs not explicitly trusted by the client

That's multiple responsibilities on every party, user included. OAuth is complicated and hard! If done right, it's secure, but don't use it unless you have a good reason to. People get confused and make mistakes about it a lot, and a lot of client (and some server) implementations are buggy, often in security-impacting ways.

requests to lodge new code challenges by the client must also be validated with additional ephemeral log-in session data

Authorization requests via OAuth always require that the OAuth server have some idea who you (the user) are, so they know what things you're allowed to authorize access to, but that information never comes from the OAuth client. It typically comes from the browser, in the form of a first-party session token. For example, if an app is using Google as your OAuth server - whether for OIDC or resource access - then the app never has access to your Google session, but your browser does; if your browser isn't logged into Google when the OAuth request starts, then Google will first demand that you log in so it knows what you can authorize for the app.

To be clear, since it seems like this might be the crux: if that first-party (only ever used on e.g. *.google.com domains) session token is stolen, no part of OAuth (including PKCE) can do anything about it, and since that token is never exposed to any OAuth clients anyhow (since they're third-party), no OAuth feature could even in theory protect (or expose) it.

[from comment] If this lodgement requires the use of a vulnerable token stored on browser, then I'm trying to understand what prevents a malicious attacker from hijacking this token

If the token you refer to is the first-party session token for the OAuth server, then "what prevents a malicious attacker from hijacking this token" is just... writing a secure first-party web application. The token needs to be securely generated with high entropy so it can't be guessed, transmitted exclusively over secure connections, stored securely on the client, not exposed via XSS or similar, and so on. The browser will do the rest, via Same-Origin Policy preventing third-party sites from reading secrets across origins.

If the token you're referring to is one that the OAuth server previously returned to the app (OAuth client), then that token isn't used for future OAuth requests at all. Also, it might be stored in the browser (if the app is web-based) but often it isn't; it might be stored in a mobile or desktop app, or sometimes in the back-end server of an app, or (typical for OIDC) it would be used to generate an app-specific session token between the app's front-end (web or otherwise) and its back-end and then discarded.