In the third part of this series of auth with Supabase, we’ll be using middleware to block users who aren’t logged in.
Get notified when we release new tutorials, lessons, and other expert Nuxt content.
The whole point of adding auth to our Nuxt 3 app is to restrict access to certain parts of our application.
That’s where route middleware comes in, which we’ll be using to block users who aren’t logged in.
In this series, we’re covering how to use Supabase with Nuxt 3 to add auth to our apps:
In this third article, we’ll create the middleware that will prevent users from accessing routes that they shouldn’t.
Here’s a quick refresher on route middleware in Nuxt 3.
Route middleware are run every single time your Vue app changes to a new route. This is done within Vue itself, but the middleware may run on the server during server-side rendering.
Each middleware receives a to
and from
route. They must return one of:
abortNavigation
— this is how you’d return an error in order to stop navigation completelynavigateTo
— if you want to redirect to somewhere elseIt might look something like this:
function(to, from) {
// We can use the `to` and `from` routes to figure
// out what we should be doing in this middleware
if (notValidRoute(to)) {
// Shows a "Page not found" error by default
return abortNavigation();
} else if (useDifferentError(to)) {
// Pass in a custom error
return abortNavigation(
createError({
statusCode: 404,
message: 'The route could not be found :(',
})
);
} else if (shouldRedirect(to)) {
// Redirect back to the home page
return navigateTo('/');
} else {
// If everything looks good, we won't do anything
return;
}
}
Let’s see how we can use this protect specific routes using the authentication we set up in the previous articles.
We’ll create a basic auth middleware:
function(to, from) {
const user = useSupabaseUser();
if (!user.value) {
return navigateTo('/login');
}
};
This middleware will redirect back to the /login
page if the user is not logged in. If there is a logged in user, we don’t need to do anything!
To use the middleware on a route, we need to add it to a page we want to protect using definePageMeta
:
<script setup>
definePageMeta({
middleware: function(to, from) {
const user = useSupabaseUser();
if (!user.value) {
return navigateTo('/login');
}
},
});
</script>
This is an inline middleware, because we’ve defined it directly in the page. If we use an array for middleware
, we can actually add as many middleware functions as we want:
<script setup>
definePageMeta({
middleware: [
function(to, from) {
const user = useSupabaseUser();
if (!user.value) {
return navigateTo('/login');
}
},
// Add in more middleware here
]
});
</script>
But this isn’t great if we want to add this middleware to multiple pages. For that, we’ll want to use a named middleware.
We’ll do this by creating a new file at ~/middleware/auth.js
, and wrapping the middleware function in defineNuxtRouteMiddleware
:
export default defineNuxtRouteMiddleware((to, from) => {
const user = useSupabaseUser();
if (!user.value) {
return navigateTo('/login');
}
});
Now, we can simply refer to the name of the middleware as a string in our middleware
array:
<script setup>
definePageMeta({
middleware: [
'auth',
// Add in more middleware here
]
});
</script>
This is now much easier to add to multiple pages!
If we wanted to add this middleware to all routes, we can simply add the .global
suffix to the filename. We’ll rename ~/middleware/auth.js
to ~/middleware/auth.global.js
.
But global middleware can present some problems. Now every single route will require the user to be logged in, which sort of makes it impossible to log in in the first place!
We also need to be careful with redirects in global middleware, as we can easily get stuck in an infinite redirect loop.
At this point, our users can log in and out, and they can only access protected routes once logged in.
But route middleware don’t run for our API endpoints. Right now they are completely unprotected.
This presents a big flaw in our security. We’ll patch that up next using server middleware.
Next Article: Protecting Server Routes