Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
PKCE: What and Why (dropbox.tech)
60 points by luord on Dec 5, 2020 | hide | past | favorite | 10 comments


OAuth 2.0 PKCE (pronounced "pixy") [1] is described in RFC 7636: Proof Key for Code Exchange by OAuth Public Clients [2]:

> OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack. This specification describes the attack as well as a technique to mitigate against the threat through the use of Proof Key for Code Exchange (PKCE, pronounced "pixy").

[1] https://oauth.net/2/pkce/

[2] https://tools.ietf.org/html/rfc7636


I really like the pseudo sequence diagram they used. Usually I'd draw all the arrows between the actors, which would end up looking very formal. The cartoon talking bubble with plain language seems much more casual and accessible!


Don't forget if you are using a public client, you need to be concerned not just with the client secret, but also with the access token. Unless the token is sender constrained (via MTLS, DPOP or something similar), anyone who gets it can use it to access whatever resources it grants permission to.

While losing a client secret to an attacker is obviously worse, because it allows for repeated grant requests, losing an access token can be bad too.

So, be aware of both things when you are running in a client like a browser or mobile application which can't be trusted to keep a secret. You can try to minimize the risk by using a HttpOnly cookie for the browser or secure storage (keychain, etc) on a mobile app, as well as keeping your token lifetimes short.

Disclosure: I work for an IDaaS provider.


I'm curious why we are still messing around with all these tokens when we could be using asymmetric encryption, like Apple is using for their AppStore connect API https://developer.apple.com/documentation/appstoreconnectapi...

Just seems fundamentally more secure.


For scenarios where third party clients clients require delegated access to users, you can combine these two approaches, giving you the best of both worlds.

For example we have configured our implementation of OpenID Connect to use PKCE for retrieving an authorization code, and then when calling the token endpoint, requires that the the client authenticate using a client_assertion JWT (as detailed in https://tools.ietf.org/html/rfc7523#section-2.2)


I don’t think I understand the attack scenario that this flow prevents even after reading the rfc. Can anyone explain?


The attack scenario occurs when the service (e.g. Facebook) wants to redirect the user back to the client (e.g. your website). That request contains an authorization code which is coupled to the client secret (it's only usable if you have the client secret). In server-side application this isn't a problem as the client secret is on the server-side. However, for mobile apps you'll have to embed the client secret into the application and it's relatively easy to find it.

This can be combined with registering a custom scheme handler and thus hijack the redirect URL. If you're able to register your app as a handler for "airbnb://", then your app will be opened once the service redirects back. And if you've figured out the client secret then you can finalize the authorization step and get an access token.

The difference in PKCE is that the client generates a unique random secret (code verifier) before it starts everything. The authorization is then coupled to the hash of the secret (code challenge), and for the authorization code to be converted into an access token the client needs to reveal the original code verifier.


You don't _need_ a client secret for authorization_code though, do you?

This part of the premise didn't make sense to me, and especially people opting for implicit as an alternative instead, because it still has this 'intercept' problem, except instead of a 1-time code, you get a long lived access token.


Implicit grant is depecrated, in the forthcoming OAuth 2.1 [1] standard this is solidified.

We start using the language "public client" and "private client", where a public client is an OAuth client like a mobile app or SPA that does not have a client secret, but has an access token delegated to it(+optional refresh token). Public clients must use implicit+PKCE.

Private clients are what we would have previously thought of as an Authorization code grant client where a server process has an access token to take actions on behalf of a user.

Depending on the OAuth use case, maintainers of the system may need to keep track of what clients are public or private, and limit their entitlements accordingly.

Public clients have the obvious issue that they're on an end-user device and thus the tokens may be stolen, proposed standards like JWT DPOP [2] and token binding [3] aim to address this.

[1] https://oauth.net/2.1/

[2] https://datatracker.ietf.org/doc/draft-ietf-oauth-dpop/

[3] https://tools.ietf.org/html/rfc8471 . Though I should say token binding does seem like it will never go anywhere.

This space is insane and hard to keep up with.


Huh, I never thought about this. I would guess an active MITM attack (breaking TLS) would work as well, since the server returns a 301 or something to airbnb:// which we could intercept and act on?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: