The title of my talk today is It's Not Magic, and I'm going to talk about elevating auth security with Pixie Best Practices. Now, the open standards that we currently use for resource access with OAuth 2 and log in with OpenID Connect have been around for over a decade. While OAuth 2 and OIDC are great for app security, they were written over 10 years ago.
App architectures are way more dynamic now, technology has changed, and attackers have had plenty of time to learn how to exploit implementation weaknesses and anti-patterns. So in January of 2025, the IETF published new best practices for OAuth and OIDC security. Now, this is a lightning talk, so I'm only going to cover one way to enhance security for web apps, and that is by using Proofkey for Code Exchange, or PIXIE.
PIXIE is an added layer of security over the authorization code flow. This flow works like this. Let's say you have your node app living on your server, and then you have an authorization server. Now, this is really just a fancy word for a set of endpoints for issuing tokens. The authorization server might be hosted locally on your own infrastructure or in the cloud. Now, when a user comes to your site, in the browser, they're going to receive a prompt to log in, and on the client side, you're going to create a high-entropy random string. This is called our code verifier.
Now, we also have a hashing function called the code challenge method. Hashing is irreversible, so once a string is hashed, it can't be unhashed. There's no way to get back to the original input. Using this function, we hash the code verifier to compute a hashed output string, which we're going to call the code challenge. We then take the authorization request and the code challenge, and optionally the code challenge method, and we send this to the authorization server's authorization endpoint. The authorization server authenticates the end user, and then it generates a code, which is sent to the browser in a URL query string.
Now, in the normal authorization code flow without Pixie, there is no code verifier, and at this point, the app would exchange the code for tokens that identify the user or grant access to resources. However, because this code is exposed in the browser, an attacker could potentially steal it and attempt to exchange it for the user's tokens by injecting it into their own session. This is called authorization code injection. Pixie prevents code injection by binding the authorization request to the token request. Once the app has the code, the code, the code verifier, and the token request are sent to the authorization server's token endpoint. The authorization server confirms that the code is the same code it sent in response to the app's authorization request. This was the one that was delivered to the app in the query string. Now, the authorization server also has the code verifier, which is the random string that was generated by the client at the beginning of this process. Remember, we sent the code challenge, which is the hash code verifier, and the code challenge method from the app to the authorization server when we issued the authorization request. This now means the authorization server has everything it needs to hash the code verifier with the code challenge method itself. It does so and then it compares its freshly computed code challenge to the code challenge that the app sent earlier, and if the challenges match, then tokens are issued and delivered to the app where they are validated.
Comments