The biggest problem we’ve faced as a company regarding security is how best to leverage open authentication to access our own databases. When authenticating with Google directly, there are ways to ensure security with server-to-server calls. With Auth0, a fantastic service, there is a complication. Auth0 doesn’t have a hook where our server can call them and say, “hey, is this JWT one of yours?”. Because of that, we were unable to use Auth0 for a long time.
On our systems, we create an authorization code and keep it in our database. Users who login, get a code and maintain it throughout their session. Pretty standard stuff, but that’s if we authenticate them. With Open Authentication, we simply get a JWT from Google or Auth0 or whomever with an identity token and an authorization hash to show that the identity token has not been modified. However, anyone can make a JWT and generate a hash, so if they post this to our server, how can we confirm it is “really” the person who they say it is, and not simply some hacker who made a JWT?
The solution is to create custom NONCE in the id_token prior to the generation of the JWT. Auth0 now allows you to add “Actions” between authentication and distribution of the token. Here’s how it can work: Auth0 gets a call for authentication using it’s standard universal authentication form. It then calls our API server, where we generate a nonce that is sent to auth0 and saved to a special nonce table in our database. Auth0 then adds that nonce to the id_token portion of the JWT before it generates the authorization hash. Now, the authorization hash of the server will validate that the nonce and user information have not been modified and are coming from Auth0.
So, how to we convert our standard login to use this? We simply add a single function to the current login api so it will also check to see if there is JWT attached to the POST. If so, then validate it has not been modified, check to see it was generated just seconds ago, then do a quick select call of our own nonce table to see if there is a nonce that matches the one in the JWT. If so, delete the nonce from the nonce table and return an authorization code that the user would normally get if they had just logged in directly.
Basically, we have allowed Auth0 to validate the identity, we can prove that there has been no manipulation of the JWT, we can verify that we provided the nonce and therefore our own servers can accept that validation with certainty of it’s legitimacy.
One note: I use the term “nonce”, because that is essentially what we are doing. Auth0 actually utilizes their own nonce, and we are not allowed to set it in the universal login formula, so what we are adding is actually a custom “claim”, which is no different than where you may have “family_name” in the id_token. For us, we called it a “session_id” and that’s simply a different name for the random alphanumeric string we produce.