Authenticating both SPA and a worker

I feel like I’m asking a dumb question here so please bear with me.

We currently have a SPA that talks to a (nodejs) API service. This API was not actually set up as an “API” in Auth0 terms, instead the user simply logged into auth0 and got a token back (both an access_token and id_token - i believe we use the id_token), which was then used to authorize itself against the API. The API validated the jwt token using express-jwt. All that works fine.

Now we want to add a worker to perform background tasks that would be trusted to call this API, which means we need a machine-to-machine app using the client credentials flow. After some reading we tried creating an “API” in auth0 terms, and set the machine app to be authorized with this api. After some fiddling we did end up authenticating the worker against auth0 and validated against the API, but I had to change the audience in the initial worker authorization to use the new API audience, and that also meant that I had to change the backend API JWT verification to check for the new audience. That in turn broke the SPA integration because it originally used the SPA client id as the audience in the id_token since it was the only client using the API. According to auth0 docs, that is by design (which is very confusing to me, since the audience is supposed to be the resource server, I thought). I did notice that the access_token had the “correct” audience, but my understanding is we’re supposed to be using the id_token, and that is also the one that has all the correct scopes in it.

I don’t know if this is relevant, but possibly complicating things is we have a multi-tenant set up (different from auth0’s concept of tenant), so we have a customized scope system whereby we use rules to callback to our service get a list of scopes that each user is able to access based on which domain they logged in from. This list makes it into the auth0 token which we use to validate the user can do various things. For machine to machine, it’s ok if it just gets a full list of scopes. However, this happens after the user has already authenticated and the token has been validated, and I can’t even get that far with both the SPA and worker.

My question is how can we make it so that our service can handle requests from both the SPA and the worker, and still validate the audience claim? Or is there a different way of handling this? I feel like I’m missing something but I’m not well versed in oauth best practices.

Thank you in advance!

In case anyone else has a similar problem, this ended up being because we were using the wrong token for authorization; access_token is meant for server side usage while id_token was meant for client side. A more careful reading of the documentation revealed this. That also meant we had to store our custom scopes in the accessToken property when our rule triggered. After figuring that out everything worked as expected.