Protecting Routes with Auth, Guest, and Admin Middleware
In this lesson, we'll learn about the auth and guest middleware included when we created our AdonisJS 6 project. Then, we'll create our own named middleware that will allow us to restrict page access to only users with the admin role.
- Author
- Tom Gobich
- Published
- Apr 27
- Duration
- 5m 36s
Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.
Adocasts
Burlington, KY
Transcript
Protecting Routes with Auth, Guest, and Admin Middleware
-
(upbeat music)
-
So if you recall back to a couple of lessons ago,
-
we added that guest middleware to our authentication routes.
-
So since we're authenticated here as John Doe,
-
we should not be able to go into /auth/login.
-
Whenever we attempted to do that,
-
it redirected us right back to our homepage
-
because we're already logged in.
-
If we jump back into our text editor here,
-
hit Command + P and dive into our routes.
-
The reason for that happening is because we applied
-
that guest middleware specifically
-
to all four of these routes.
-
And then we applied the auth middleware
-
specifically to our logout route.
-
Guest will only allow a user to view a page
-
or perform an action if they are unauthenticated.
-
Auth then is the inverse.
-
It will only allow a user to perform an action
-
if they are authenticated.
-
So we can actually use that methodology here
-
to create a router.group.
-
And let's give this a prefix of admin.
-
So we're gonna create an administrator only section here.
-
We'll also name this as admin as well.
-
But right now let's go ahead and just do router.get,
-
do slash so that slash admin matches
-
this particular route right here.
-
And let's just do an inline route handler for right now.
-
So we do ctx, return, you are here.
-
Let's give that a save to fix all our formatting.
-
So if we hit slash admin, at this point in time,
-
anybody would be able to hit it
-
and they would get back you are here.
-
If I were to open up a new private
-
or incognito window here,
-
go into localhost 3333/admin, hit Enter.
-
Oh, looks like we're unable to connect.
-
Let's see what happened.
-
Oh yes, we forgot to give the inner route here a name.
-
So let's jump back into our text editor as index.
-
Okay, jump back into our browser, give that a refresh.
-
Okay, so we're unauthenticated at this point
-
because we're in a brand new private browser session,
-
but we're able to see you are here A-okay.
-
So the first thing that we're gonna wanna do
-
is apply the auth middleware to this entire admin group
-
because we don't want non-authenticated users
-
to be able to get in here.
-
Furthermore, we probably don't want non-admins
-
to be able to get in here as well,
-
but we'll take care of that next.
-
So let's do use middleware auth, give that a call,
-
and save, jump back into our browser.
-
And now if we give this a refresh,
-
since we are unauthenticated,
-
we're gonna get redirected back to our login page,
-
or it will attempt to.
-
Our login page is at /auth/login,
-
so we do need to fix that as well.
-
So let's hide that away.
-
This is our auth middleware, so let's jump into there.
-
And we just need to switch redirect to /auth/login,
-
jump back into our browser.
-
And at this point, if we were to try to jump back into admin,
-
okay, there we go.
-
So now we got successfully redirected
-
back to our login page.
-
So let's go ahead and close out
-
this private browser session
-
and jump back into our authenticated browser session.
-
And now let's try to dive into /admin.
-
So now we're back to being able to access it
-
because we are authenticated.
-
We hide this back away, close out our auth middleware.
-
Let's make this a little bit more stateful.
-
So you are here, give ourselves backticks,
-
comma, ctxauthuser.fullname,
-
just so that we can verify that we are indeed authenticated
-
as ctxauthuser.roleidrole.
-
So now we'll be able to also see the user's role.
-
So if we jump back into our browser,
-
give that a refresh, there we go.
-
So you are here, John Doe, as one role.
-
So a role with an ID of one.
-
If we jump back into our enums, we have a roles enum.
-
One is a basic user, two is an admin.
-
So since this is our admin application section,
-
let's go ahead and create a new middleware
-
that will only allow users with a role ID of two
-
for our admin into this section.
-
So we'll jump into our terminal,
-
give our server a stop, node, base, make, middleware,
-
call this admin, run that.
-
And we're gonna wanna create this as a named middleware.
-
So we'll create it there.
-
It has given us an admin middleware file
-
as well as registered it within our kernel TS file.
-
So if we actually dive down into our kernel TS file
-
right down here, scroll down,
-
we'll see right here's our silent auth middleware
-
that we created a little bit ago.
-
Scroll down a little bit further.
-
Here is our new admin middleware.
-
So we can access it and apply it to individual routes
-
using the key admin.
-
You can customize this here if you want.
-
And it will use the file @middleware,
-
admin middleware to perform that action.
-
So let's go back to our middleware
-
and dive into our new admin middleware.
-
We want this middleware to run before our route handler.
-
So we wanna perform this check
-
before the next function call here.
-
So we'll do it right here.
-
So let's first grab whether or not they are an admin.
-
So we can do is admin equals ctx auth user.roleId
-
equals roles, import that from our enums.admin.
-
So if the user is authenticated
-
and our user property is populated
-
and that role ID for that user equals our enum admin role,
-
which is a value of two, then is admin will be truthy.
-
So we could do if not is admin,
-
you can either return or redirect the user somewhere
-
as guest and auth middleware are doing,
-
or we could do something like throw new exception
-
with a message, you are not authorized
-
to perform this action.
-
Provide an options for this exception of an error code.
-
So E not authorized with a status code of 401.
-
So now if the user is not an admin
-
and they try to attempt to view our admin section,
-
they'll see a 401 error.
-
So the last thing that we need to do is hit command P,
-
jump into our routes and switch from using auth
-
to our admin middleware.
-
So with that saved, if we jump back into our browser,
-
give this a refresh.
-
It looks like we ran into another error.
-
Oh, nope, okay, I just forgot to start server backup.
-
NPM run dev, give that another refresh there.
-
There we go, so now you are not authorized
-
to perform this action with an error status of 401.
-
If however, we jump into pgadmin, let's go find this user.
-
So we'll right click on users, view edit data,
-
just do all rows here.
-
Okay, so we're working with John Doe, our user ID of seven.
-
And right now the role ID is one.
-
Let's give that a double click and switch that to two
-
and head up to this save data changes button right here,
-
where you can hit F6 and that will just persist
-
the change that we made here within this table.
-
Let's go ahead and close this back out.
-
And now if we refresh this, we're back to being authorized
-
because we now have a role ID of two.
-
So we're an admin.
-
Introduction
-
Fundamentals
-
2.0Routes and How To Create Them5m 23s
-
2.1Rendering a View for a Route6m 29s
-
2.2Linking Between Routes7m 51s
-
2.3Loading A Movie Using Route Parameters9m 17s
-
2.4Validating Route Parameters6m 6s
-
2.5Vite and Our Assets6m 38s
-
2.6Setting Up Tailwind CSS9m 5s
-
2.7Reading and Supporting Markdown Content4m 32s
-
2.8Listing Movies from their Markdown Files8m 51s
-
2.9Extracting Reusable Code with Services7m 4s
-
2.10Cleaning Up Routes with Controllers4m 52s
-
2.11Defining A Structure for our Movie using Models9m 38s
-
2.12Singleton Services and the Idea of Caching6m 11s
-
2.13Environment Variables and their Validation4m 16s
-
2.14Improved Caching with Redis10m 44s
-
2.15Deleting Items and Flushing our Redis Cache6m 46s
-
2.16Quick Start Apps with Custom Starter Kits6m 28s
-
2.17Easy Imports with NodeJS Subpath Imports8m 40s
-
-
Building Views with EdgeJS
-
3.0EdgeJS Templating Basics8m 49s
-
3.1HTML Attribute and Class Utilities6m 9s
-
3.2Making A Reusable Movie Card Component10m 24s
-
3.3Component Tags, State, and Props4m 53s
-
3.4Use Slots To Make A Button Component6m 56s
-
3.5Extracting A Layout Component5m 13s
-
3.6State vs Share Data Flow2m 59s
-
3.7Share vs Global Data Flow6m 7s
-
3.8Form Basics and CSRF Protection6m 13s
-
3.9HTTP Method Spoofing HTML Forms3m 3s
-
3.10Easy SVG Icons with Edge Iconify7m 57s
-
-
Database and Lucid ORM Basics
-
4.0Configuring Lucid and our Database Connection4m 3s
-
4.1Understanding our Database Schema9m 35s
-
4.2Introducing and Defining Database Migrations18m 35s
-
4.3The Flow of Migrations8m 28s
-
4.4Introducing Lucid Models5m 43s
-
4.5Defining Our Models6m 49s
-
4.6The Basics of CRUD11m 56s
-
4.7Defining Required Data with Seeders11m 11s
-
4.8Stubbing Fake Data with Model Factories13m 48s
-
4.9Querying Our Movies with the Query Builder15m 30s
-
4.10Unmapped and Computed Model Properties3m 24s
-
4.11Altering Tables with Migrations7m 6s
-
4.12Adding A Profile Model, Migration, Factory, and Controller2m 57s
-
4.13SQL Parameters and Injection Protection9m 19s
-
4.14Reusable Query Statements with Model Query Scopes8m 11s
-
4.15Tapping into Model Factory States9m 15s
-
4.16Querying Recently Released and Coming Soon Movies4m 59s
-
4.17Generating A Unique Movie Slug With Model Hooks7m 59s
-
-
Lucid ORM Relationships
-
5.0Defining One to One Relationships Within Lucid Models5m 49s
-
5.1Model Factory Relationships2m 54s
-
5.2Querying Relationships and Eager Vs Lazy Loading5m 17s
-
5.3Cascading and Deleting Model Relationships5m 16s
-
5.4Defining One to Many Relationships with Lucid Models6m 56s
-
5.5Seeding Movies with One to Many Model Factory Relationships5m 24s
-
5.6Listing A Director's Movies with Relationship Existence Queries8m 41s
-
5.7Listing and Counting a Writer's Movies8m 41s
-
5.8Using Eager and Lazy Loading to Load A Movie's Writer and Director5m 18s
-
5.9Defining Many-To-Many Relationships and Pivot Columns9m 48s
-
5.10Many-To-Many Model Factory Relationships4m 50s
-
5.11A Deep Dive Into Relationship CRUD with Models18m 5s
-
5.12How To Create Factory Relationships from a Pool of Data13m 55s
-
5.13How To Query, Sort, and Filter by Pivot Table Data9m 47s
-
-
Working With Forms
-
6.0Accepting Form Data12m 15s
-
6.1Validating Form Data with VineJS9m 29s
-
6.2Displaying Validation Errors and Validating from our Request7m 16s
-
6.3Reusing Old Form Values After A Validation Error2m 3s
-
6.4Creating An EdgeJS Form Input Component5m 28s
-
6.5Creating A Login Form and Validator5m 1s
-
6.6How To Create A Custom VineJS Validation Rule9m 7s
-
-
Authentication & Middleware
-
7.0The Flow of Middleware7m 49s
-
7.1Authenticating A Newly Registered User4m 14s
-
7.2Checking For and Populating an Authenticated User2m 10s
-
7.3Logging Out An Authenticated User2m 24s
-
7.4Logging In An Existing User6m 54s
-
7.5Remembering A User's Authenticated Session6m 55s
-
7.6Protecting Routes with Auth, Guest, and Admin Middleware5m 36s
-
-
Filtering and Paginating Queries
-
8.0Creating A Movie List Page3m 43s
-
8.1Filtering A Query By Pattern Likeness7m 9s
-
8.2Filtering Our List by Movie Status5m 47s
-
8.3How To Apply A Dynamic Sort Filter To Your Query7m 12s
-
8.4Joining SQL Tables To Order By A Related Column4m 49s
-
Validating Query String Filter Values7m 23s
-
How To Paginate Filtered Query Results9m 15s
-
Pagination First, Last, Next, and Previous Buttons4m 2s
-
-
User Watchlist
-
An Alternative Approach to Many-To-Many Relationships4m 56s
-
Toggling A Movie in an Authenticated User's Watchlist9m 56s
-
Listing and Filtering User Watchlist Items7m 34s
-
Allowing Users To Toggle A Movie As Watched4m 44s
-
Filtering By User's Watched Status6m 7s
-
Defining A Composite Unique Constraint4m 46s
-
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!