You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After that the codebase felt ready to get right to implementing a POC integration with Plaid behind a beta flag (auth0 user role).
🔒 Auth0
Auth0 is key in the implementation as it's what we use to authenticate our users and check that they have the needed role to access our features. On the frontend side, there's a getAccessTokenSilently function that you can use to retrieve the auth0 access token. The first problem you find though is that it returns an opaque token unless you set a custom audience in the provider:
The audience tells Auth0 that you are requesting access to a specific API, in our case, the set of server actions we will code later. For this to work, you need to create the API on Auth0's (under Applications/APIs):
The next step is to make sure that auth0 includes the roles for your API in the accessToken it return. To do so we need to create a Post Login action:
exports.onExecutePostLogin=async(event,api)=>{constnamespace='https://maffin';if(event.authorization){api.accessToken.setCustomClaim(`${namespace}/roles`,event.authorization.roles);api.idToken.setCustomClaim(`${namespace}/roles`,event.authorization.roles);// We will talk about this later}};
And that's it on the Auth0 side! Now you can retrieve the access token once the user has authenticated with getAccessTokenSilently call.
🚪 Storing the access token
The access token is something that you'll need to be using quite a bit in your app to check if the user has permissions to do something or if you want to enable different UI depending on the user. With the current version of auth0-react you need to use the useAuth0 hook in order to have access to the function that returns the token:
Until here, we've been talking about access token but Auth0 works with two tokens:
idToken: provides information about the user itself and it's what auth0.user returns. This one is mostly used in the frontend
accessToken: contains authorization information to verify the access is granted to APIs.
When I initially wrote this blogpost, I was using access token both for UI and API but updated my code (and the post) to use the idToken in the UI instead after this very constructive discussion where I learned a lot.
Thanks to the line added in our Auth0 action: api.idToken.setCustomClaim(${namespace}/roles, event.authorization.roles); we now have the roles in the idToken returned by Auth0.
{email: <user_email>
// beta is a role I created in the auth0 dashboard and assigned to my user
'https://maffin/roles': ['beta'],
...
}
we can now take decisions in the UI to show one component or the other:
We've modified the useSession hook we defined above to attach the roles to the returned object.
With above, if the user doesn't have the beta role they won't see anything while if they have it, they'll see the Plaid import button:
Note that this only changes the UI behavior but doesn't protect your backend resources. A bad agent could always modify the source and inject the roles which would show the "hidden" UI which then can trigger calls to your protected backend. That's what we focus on on the next section.
🛡️ Protected server actions
auth0-react provides a getAccessTokenSilently that allows us to retrieve the access token in React components, hooks, etc. The problem with this is that you can't retrieve the access token in normal functions like for example the ones defined in server actions. To work around this some people suggest to store it in local storage and retrieve it whenever you need. Auth0 recommends to keep access tokens in memory to reduce risk surface. In our case, we just created a class with a static accessToken variable so it can be set and retrieved whenever is needed:
With this, you can do AccessTokenHolder.accessToken anywhere in your code. In our case we wrap our server actions with this so the access token is injected whenever they are called:
And that's it! if someone tries to pass a wrong jwt token, the verification will fail so it will not execute. Also, if a user with the wrong roles tries to execute, it will also fail.
💚 Conclusion
With this change, I introduced a way for Maffin to protect features and modify behavior based on the roles assigned to the user in Auth0. Before that, I did it based on the environment I was deploying (i.e. production, staging, etc.) which meant I couldn't have premium and standard users in the same environment and less, have a way to segment functionality.
As always, you can find the full PR in Github. If you want to talk more about this or need help, feel free to join our discord!
If you enjoyed the post, feel free to react to it directly in Github :).
The text was updated successfully, but these errors were encountered:
+++
slug = "nextjs-feature-flags-auth0"
reading_time = "15m"
summary = "A simple way to enable beta features for your users using Auth0 roles"
+++
In the last weeks I've been working on integrating Plaid into Maffin so your data is automatically synced. When I first looked at it, it felt too much because there were many missing parts in the app in order to support it properly. I transitioned backend functionality from express to server actions and protected them using jwt verification.
After that the codebase felt ready to get right to implementing a POC integration with Plaid behind a beta flag (auth0 user role).
🔒 Auth0
Auth0 is key in the implementation as it's what we use to authenticate our users and check that they have the needed role to access our features. On the frontend side, there's a
getAccessTokenSilently
function that you can use to retrieve the auth0 access token. The first problem you find though is that it returns an opaque token unless you set a custom audience in the provider:The audience tells Auth0 that you are requesting access to a specific API, in our case, the set of server actions we will code later. For this to work, you need to create the API on Auth0's (under Applications/APIs):
The next step is to make sure that auth0 includes the roles for your API in the accessToken it return. To do so we need to create a Post Login action:
And that's it on the Auth0 side! Now you can retrieve the access token once the user has authenticated with
getAccessTokenSilently
call.🚪 Storing the access token
The access token is something that you'll need to be using quite a bit in your app to check if the user has permissions to do something or if you want to enable different UI depending on the user. With the current version of
auth0-react
you need to use theuseAuth0
hook in order to have access to the function that returns the token:🍿 Role based UI
Until here, we've been talking about access token but Auth0 works with two tokens:
auth0.user
returns. This one is mostly used in the frontendThanks to the line added in our Auth0 action:
api.idToken.setCustomClaim(
${namespace}/roles, event.authorization.roles);
we now have the roles in the idToken returned by Auth0.we can now take decisions in the UI to show one component or the other:
With above, if the user doesn't have the beta role they won't see anything while if they have it, they'll see the Plaid import button:
🛡️ Protected server actions
auth0-react provides a
getAccessTokenSilently
that allows us to retrieve the access token in React components, hooks, etc. The problem with this is that you can't retrieve the access token in normal functions like for example the ones defined in server actions. To work around this some people suggest to store it in local storage and retrieve it whenever you need. Auth0 recommends to keep access tokens in memory to reduce risk surface. In our case, we just created a class with a static accessToken variable so it can be set and retrieved whenever is needed:With this, you can do
AccessTokenHolder.accessToken
anywhere in your code. In our case we wrap our server actions with this so the access token is injected whenever they are called:Then, within our server action, we need to verify the JWT. If it's valid, check for the right permissions and then execute:
The
verify
function looks like this:And that's it! if someone tries to pass a wrong jwt token, the verification will fail so it will not execute. Also, if a user with the wrong roles tries to execute, it will also fail.
💚 Conclusion
With this change, I introduced a way for Maffin to protect features and modify behavior based on the roles assigned to the user in Auth0. Before that, I did it based on the environment I was deploying (i.e. production, staging, etc.) which meant I couldn't have premium and standard users in the same environment and less, have a way to segment functionality.
As always, you can find the full PR in Github. If you want to talk more about this or need help, feel free to join our discord!
If you enjoyed the post, feel free to react to it directly in Github :).
The text was updated successfully, but these errors were encountered: