Discover more from A slice of experiments
Syncing Auth0 users to my own database
Gotta keep my own records
TL;DR: Auth0 Actions have what’s basically event triggered webhooks
I’m working on a small side project to automate something for myself. I think it’ll be useful to other people and so I took this as an opportunity to build it such that other people would also be able to use it if they wanted to. It’s a much larger project than my usual afternoon long or weekend long projects, which means I can milk multiple posts out of it if I wanted to. I’ll try to spread them out though if I have other things that I’ve worked on.
I’ve worked at multiple companies now that have used Auth0 for user management. Conceptually, I understand fairly well how JWT based authentication works. I also understand things like machine-to-machine, etc. I’ve built websites with user management on other platforms, but I’ve never actually built anything with Auth0 for myself from scratch. Something new for me, delightful. Ideally, I’d have done more of this in Terraform to keep multiple environments in-sync but I’ve actually been pretty lazy with this project compared to what I normally keep as my standard. I don’t even run anything locally when developing this project. I’m sure one day I should fix that but my push to live pipeline takes about 60-70 seconds. I know that can be a pretty long iteration time, but everything I have written to this point is really simple so far so… meh.
I created the Auth0 application, configured for a React Single Page Application, aka client side only JWTs. Easy enough. Now though… I want to store some user specific information. Like for example, I want user’s to be able to login with multiple different identity providers but still have the same account on my backend. If someone logs in with Twitch credentials or with Discord credentials (it’s a gaming related website), I want them to be considered the same user. So I need to track a user ID on my side of things that will be mapped from their individual identity provider logins.
Auth0 has a login flow where you can hook in and modify the JWT or do some other minor actions before anything ever reaches your service.
Every time someone logs in, a request is sent to my backend which then checks to see if this email has ever been seen before. If the email hasn’t, we generate a new “account” on my database, and return a unique ID for that user. If the email has already been seen, then we fetch the previously used unique ID and send it back. Simple enough. Right? Right? You know that every time I say “simple enough”, there’s like a 50% chance that it’s not actually that simple.
Auth0 Actions send that HTTP request but unlike other webhook style workflows like from Stripe or Slack, the Auth0 Action requests don’t come with any kind of verifiable signature. So people could send requests to my endpoint and I’d just blindly assume that they are from Auth0. After reading through the docs, I found that the way to go about this is to add a secret to the action that I’d then verify from my server. I wish I didn’t have to do this but at least it’s not that much extra work.
Verifying Auth0 tokens
Last thing I wanted to mention in this post is verifying the tokens. One of the values of using a JWT is that they’re verifiable completely on their own. You don’t have to make a request to a third party service in order to know that it’s a valid token, which is important for things like access tokens that you might use to grant access to private information.
However, unbeknownst to me, Auth0 may actually not grant a JWT for an access token. If you do not specify an
audience when creating your client, you will instead receive an opaque token that doesn’t have any information on its own. That means that you have to send this request to Auth0, specifically their /userinfo endpoint in order to get user information from the access token. I thought about setting an audience or even just sending the id token while all I care about right now is authentication, not authorization, but instead I just got lazy and started sending requests to userinfo.
This was probably a mistake because it turns out that the userinfo endpoint has a fairly low rate limit. I don’t know exactly what it is but I kept hitting it a lot, so I just threw an in-memory cache on my server side. These tokens are valid for 24 hours by default, so having a 5 minute cache isn’t going to be a problem.
That’s all for now. Thanks for reading and I’ll see ya’ll for the next one.
Thanks for reading A slice of experiments!