Skip to main content
Solved

Best practice for handling OAuth Scope changes and Token Validation

  • January 9, 2026
  • 5 replies
  • 53 views

Hi everyone,

I'm building a Monday App using React and Express. I'm using SecureStorage to store the OAuth access_token after the handshake.

I have a concern regarding Scope Management and Token Validation.

Currently, I define my required scopes in an Environment Variable (e.g., MONDAY_SCOPES="boards:read users:read"). In my authentication middleware, I simply check if an access_token exists in the storage. If it exists, I assume the user is authorized.

The Logic:

  1. Env: SCOPES="boards:read"

  2. User authorizes: I get a token with boards:read and save it to SecureStorage.

  3. Later: I update my app features and change Env to SCOPES="boards:read boards:write".

  4. The Problem: My middleware still sees the old token in SecureStorage. It returns 200 OK for the auth check, but the API calls fail later because the token lacks the new boards:write permission.

Here is a simplified version of my check:

TypeScript

 

// Middleware or Auth Check Logic
export async function checkAuth(req, res, next) {
const secureStorage = new SecureStorage();

// 1. I retrieve the token
const accessToken = await secureStorage.get("access_token");

// 2. I check if it exists
if (!accessToken) {
return res.status(401).json({ error: "Re-authorization needed" });
}

// THE ISSUE:
// I have no way of knowing if this specific 'accessToken'
// covers the scopes defined in process.env.MONDAY_SCOPES

req.mondayToken = accessToken;
next();
}

My Question: What is the standard way to handle this in Monday Apps?

  1. Should I store the granted_scopes string in SecureStorage alongside the access_token and compare them on every request?

  2. Or is there an endpoint to "validate" the token and see its scopes before using it?

  3. Or should I just let the API call fail with a "Scope Error" and handle the re-auth on the frontend?

I feel like checking against Environment Variables manually is prone to errors. Any advice is welcome!

Best answer by xatxat

hey!

you can decode the access token with a jwt library. the scopes of the token are then part of the jwt payload.

- simon

 

5 replies

xatxat
Forum|alt.badge.img+1
  • Participating Frequently
  • Answer
  • January 9, 2026

hey!

you can decode the access token with a jwt library. the scopes of the token are then part of the jwt payload.

- simon

 


  • Author
  • Participating Frequently
  • January 9, 2026

Hi ​@xatxat ,

You are absolutely right! I just checked and I can indeed access the scopes from the decoded JWT. That simplifies things a lot.

So the flow would be:

  1. Get the access token from SecureStorage.

  2. Decode it.

  3. Check if the token's scopes cover my process.env.MONDAY_SCOPES.

  4. If not, return 401 (to trigger re-auth on the frontend).

My final question: Is this considered the best practice for Monday apps, or is it more of a workaround? I want to make sure I'm building this on solid foundations.

Thanks again!


  • Author
  • Participating Frequently
  • January 9, 2026

hey!

you can decode the access token with a jwt library. the scopes of the token are then part of the jwt payload.

- simon

 

Hi ​@xatxat ,

You are absolutely right! I just checked and I can indeed access the scopes from the decoded JWT. That simplifies things a lot.

So the flow would be:

  1. Get the access token from SecureStorage.

  2. Decode it.

  3. Check if the token's scopes cover my process.env.MONDAY_SCOPES.

  4. If not, return 401 (to trigger re-auth on the frontend).

My final question: Is this considered the best practice for Monday apps, or is it more of a workaround? I want to make sure I'm building this on solid foundations.

Thanks again!


xatxat
Forum|alt.badge.img+1
  • Participating Frequently
  • January 10, 2026

I would consider it best practice 😉 the jwt payload is the source of truth.


  • Author
  • Participating Frequently
  • January 15, 2026

Hi ​@xatxat ,

Thanks for the confirmation! It gives me peace of mind knowing that relying on the JWT payload is the standard way to go and the single source of truth for the backend.

Just to add a small finding that might help others: I also noticed that on the client side, using monday-sdk-js, we can actually access the approved and required scopes through the context.

 

const monday = mondaySdk();
monday.get("context").then(res => {
// I can see scope details here as well
console.log(res);
});

This is really useful for handling UI states (like disabling buttons or showing an "Update Permissions" banner) on the frontend before even sending the request to the backend.

Thanks again for the help!