OAuth Recipe for Monday, or is it really that easy?

I’ve only ever dealt with OAuth using things like Google, Facebook, and Twitter and they offer extremely easy to use tools. Doing OAuth with Monday is the first time I actually have to use my own brain, which is fine but I may get it wrong and mess up security.

It seems simple enough to send the user to the monday.com server, grab the code from the url parameters when the user comes back, and finally ask for the token using the code and my client secret. Is that all there is to it? I do understand this needs to happen on a server and not in the user’s browser so that the client secret stays secret.

I’ve asked around somewhere else and passport.js was recommended, however they don’t have a monday.com recipe. I’m hesitant to jump into a library for this if it’s not going to hold my hand because I don’t really know what it’s supposed to be doing.

Is there anything I need to consider before doing this myself or do I have it right?

passport.js doesnt have support for monday.com yet. I’ve thought about creating the recipe for it but never had the time/ambition since I wrote my own already.

Pretty much as you said, its straight forward. Here are a few things worth mentioning.

  • verify the JWT sent as “token” in the query string, using your signing secret.
  • check if you already have an OAuth token for the user/account/app ID combination. Then you can just redirect to the backToUrl if you already have a token.
  • store the user_id, app_id, account_id, back_to_url, and state string in some sort of datastore. You need the first three for storing the token, as its not provided in the callback. You need the back_to_url for the same reason.
  • I use a UUID for the state string and as the key in the datastore.

Those are the only gocthas i can think of.

2 Likes

Thanks, that makes a lot of sense. I’ve managed to receive the tokens and just now am thinking about how to make it persist. I think I remember seeing a suggestion to user a cookie or localstorage but a secure database makes sense. I read about state string in the OAuth Simplified article but haven’t tried using it yet. I’ll try doing it your way because I don’t want to mess with cookies.

But I am confused how this all goes together. I send UUID as a state string with the code to get the token, and then use the UUID as the key in a database to store the user information. But I don’t see how I reference that UUID at any other time and I don’t have access to any user data before they log in*, right?

  • edit by this I mean that before they go through the OAuth process I don’t have any information on the user. Right?? I must be missing something.

The callback with the code includes the state only, so you need to store the userid, accountid, and appid from the initial request (which is in the JWT in the initial request, you get this as output from jwt.verify).

Once you get the token you store it along with the accountid, userid, and appid you stored previously. Then when you receive events for your app, you can look up the oauth token using the accountid, userid, and appid.

That said, what is your use case that you need OAuth tokens, and the Short Lived Tokens don’t work?

That’s a good question. Ultimately I probably want to try to have something running on the monday platform so I think I can just use the sdk to make authentication a lot easier. I don’t really know what I have in mind, tbh, I’m just trying to throw something together that does something with Monday and I got stuck on auth. I did have in mind an app that might run off the platform and I’d want to keep the user logged in between sessions.

I think I see now that I’m storing these values and the JWT if my app runs in the background and needs to respond to events. I hadn’t thought of that but I’m sure this is something that would happen in a lot of situations.

I’m not sure if you can help me, or anyone else, but I am having a HELL of a time verifying my JWT. I’ve run jsonwebtoken in the browser but I’m not sure if that even works so I made an edge function on supabase with denojwt (djwt) and I can only get ‘the jwt’s signature does not match’. I’ve run the jwt and the signing secret a dozen times through jwt.io. If I put the signature in first and then the jwt it says it doesn’t match, and when I put the jwt in first and then the signature it just changes the last section of the jwt to make it match. I’ve spent a day on this and I’m still 90% sure it’s user error, but if I can’t get anything the verify the pair I wonder if something is actually wrong. I’ve tried regenerating the signing secret and getting a new jwt with no luck.