Add PKCE Support to the OAuth2.0 Authorization Code Flow
I am currently developing a native Android application for Twitch and want to make use of the OAuth2.0 API. Since the Twitch Authorization Server doesn't seem to support the PKCE (Proof Key for Code Exchange), i will have to put my client secret into my native application, which isn't secure at all, because the app can easily be decompiled.
This is a requirement for all native apps, as stated by the IETF in RFC 7636 (https://tools.ietf.org/html/rfc7636).
I hope to see this implemented soon, because this poses a huge security risk for all native apps and their developers.
-
nIronwolf commented
So if I'm understanding this correctly, say a game using the API that doesn't do all of this running around may have it's client secret as part of it's general distribution code? So after a streamer authorizes that game, anyone can find that secret in the game executable and start taking actions on that account?
-
JamesTheElixirGuy commented
There is a way to "jury-rig" something like PKCE.
1. native app generates a random string called `codeVerifier`.
2. native app opens twitch oauth with `?state={codeVerifier}` param and skipping the code exchange. If you use `react-native-app-auth`, just set `skipCodeExchange=true`.
3. successful twitch login redirects to "backend" server with `code` and `state` values. Rename respectively to `twitchCode` and `codeVerifier`.
4. backend server creates a random string called `internalCode`.
5. backend server caches a KVP with key `codeVerifier` and value `{internalCode: internalCode, twitchCode: twitchCode}`
6. backend server sets window location to `myapp://oauthpath/twitch?internalCode={internalCode}`.
7. native app handles this route by sending a login POST request to backend with 2 params: `internalCode` and `codeVerifier`.
8. backend handles the login request by looking for `codeVerifier` in the cache. It checks the `internalCode` matches. If it does match, use the accompanying `twitchCode` to hit twitch API, get the user, login/register with the user details and return a normal "access token" for your app to the native app.
TL;DR use twitch's CSRF-thwarting "state" mechanism as a way of passing a `codeVerifier` from frontend to backend. It is never passed from backend to frontend, so PKCE is achieved (I think).
-
JamesTheElixirGuy commented
Until this is implemented, it should be common knowledge that Twitch OAuth is insecure on any native application.
-
GenideGaming commented
Someone please implement this soon!
IEFT best practices REQUIRES PKCE for public clients (e.g. Standalone Applications) and is RECOMMENDED for confidential clients (e.g. Web Server). Twitch should transition away from implicit authorization to PKCE Authorization code flow.
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-2.1Re-posting links here because the original one leads to 404.
https://oauth.net/2/pkce/
https://datatracker.ietf.org/doc/html/rfc7636 -
Shackleberry112 commented
Absolutely required, the only options (AFAIK) are to use implicit flow which has inherent risks when using the access token for API calls or to expose the client secret.
PKCE is vital to ensure public client applications can be secured!