Refresh unexpired token for SPA

We use Auth0 custom database connections to our existing user database backend. Our business defines a tiered account structure for our users (trial -> basic user -> verified user). We use rules to properly set custom claims on the id_token of a user based on their account level.

When a user is logged in and “upgrades” their account, they need to be issued a new token with the updated claims.

Our application is a SPA using the implicit flow. We have tried to use “getSilentToken” however because the access token is still valid (it hasn’t yet expired), it immediately returns the same token again.

Is there a way to cause the “Silent Authentication” flow to not return the same access token and to call the custom login function again to get the updated user data and rerun all the rules or do I have to get them to logout completely and login again?

1 Like

Hi @betmix-matt

Welcome to the Auth0 Community Forum!

Just to confirm here, you are using this method and you are not receiving the new token with the correct claims?

I am looking at the library, and that method describes the getTokenSilently function to do the following:

If there’s a valid token stored, return it. Otherwise, opens an iframe with the /authorize URL using the parameters provided as arguments.

So you would be correct in observing that the same stored token is returned. I think you could probably remove the token and then you should be able to make the call with success. I am not sure how to do this, I’ll have to ask for some help.

1 Like

The problem isn’t that the getTokenSilently function is caching the token. We pass " ignoreCache" as true which causes it to go the /authenticate endpoint with prompt=none. The issue is that the token isn’t actually expired yet, so /authenticate immediately returns back success with the same exact token. It doesn’t reissue it.

1 Like

There shouldn’t be caching of the token on the auth0 side, it should be creating a new token. Are you sure the rule is running?

I think the issue may lie in the fact I’m using a Custom Database login script which is not being called with the refresh. I wonder if I could detect this case with a rule and call my backend to retrieve the updated data before the rules run again.

Are you using the Sync user profile attributes at each login feature? It is in settings in your custom DB.

I’ve actually solved this now though the solution was not easy. Because I’m using a custom database, unless the user actually logs in with their custom database account connection (e.g. if they logged in using a linked social account), the custom login script does not get called. Additionally I cannot call the “createUser” or “updateUser” endpoints (updateUser works for a few fields, but not all) because the DB connection using a custom login script.

I had to come up with some hacky solution where I have a rule (at the top of the list of rules, so it triggers first) which triggers if the user being logged in to is from the custom db connection but the connection being logged in to is not the DB connection, if context.protocol === ‘oauth2-refresh-token’, or the context.request.query.prompt === ‘none’.

The rule calls the ‘updateAppMetadata’ endpoint on the user record with an attribute with a randomly generated password and starts a passwordGrant flow for that user using the randomly generated password. I then updated the custom login script to call the management getUsers endpoint with a query for the username before calling to my customer back end and if the password matches the randomly generated one in the app_metadata, calls a different login endpoint that doesn’t require a password (one that’s secured to only allow access from Auth0). I make sure to clear the randomly generated password from the app metadata before calling the callback.

The original rule finishes execution after the passwordGrant flow and updates the “user” using “getUser” on the management API (so that it has the updates from the flow in memory). This makes sure all rules run with the updated data pulled from the backend API.

This allows me to refresh the data in all cases where the custom login endpoint was not called for a user whose primary connection is that database.

@betmix-matt,

Sounds like quite the workaround. I am surprised that this isn’t working as you initially expected, it sounds like there is something wrong with the refresh.

I would like to also remind you that you have access to our support team, which will guarantee a response time compared to community.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.