Tutorial: How to build Basic Auth with Session

Ohw this is a small step in coding but a huge step for our skillset! At the end of this tutorial you will have a register-view, a login-view and a profile-view and you will learn how to build basic authentication, use session to remember a logged in user and how to secure a view so only logged in user can access it✨

You can find the result of this tutorial on github here

This tutorial is a natural follow-up of How to write Controllers. You can either go for that tutorial first and come back later or be a rebel, skip it and read on 😊

1. Create and generate a new project
2. Adjust Model: User
3. Create View: Register
4. Adjust UserController: Add Register-Routes
5. Create View: Login
6. Adjust UserController: Add Login-Routes
7. Create View: Profile
8. Adjust UserController: Add Profile-Route
9. Adjust UserController: Add Logout-Route

We will use the outcome of the aforementioned tutorial as a template to create our new project:

Before we generate an Xcode project we would have to add the Auth-Provider as a dependency and also change the package name within Package.swift:

Now in the terminal at the root directory projectName/ execute:

It may take a bit fetching the dependency, but when done you should have a project structure like this:

In our Models/User.swift we extend our User by PasswordAuthenticatable and SessionPersistable, change all username occurrences to email and add another property password:

Nice! Let’s implement a view with a form that has an input for an email and one for a password! First we’ll rename our userview.leaf to register.leaf within Resources/Views/ and then adjust the content to the following:

NOTE: Remember that the names in our input-tags are the keys we will use in our controller function in order to access the values of the input fields 🤓

Next we need to implement a route that would return our register view. But first let’s remove all functions inside our Controllers/UserController.swift:

Now we’re good to go to implement a route that returns our register view:

Let’s not forget to remove/add our routes within Routes/Routes.swift:

If you now cmd+r or run everything should built without any error and we should see our nice register-form when opening /register in our browser 😊!

Note: make sure to select Run as a scheme next to your button before running the app

To finish our registration all that’s left is the route that handles our register-form. So within our Controllers/UserController.swift add:

And finally in our routes within Routes/Routes.swift add:

You could now cmd+r to run the project, go to /register and try to register yourself with an email. It should redirect you to /login that doesn’t exist, yet. Just go back to /register and try to register with that same email again, it will give you “email already exists” now! Means everything works just perfectly 🙌🏻

Okay so in order to log in we’ll need a view with a form that has an input for an email and one for a password. So within Resources/Views/ create a new file and name it login.leaf and add:

NOTE: Select login.leaf and go to Editor>Syntax Coloring>HTML 😉

The first route for returning our login view is simple. Add the following within our Controllers/UserController.swift:

And then go to Routes/Routes.swift and add our new route:

If you would now cmd+r and register yourself under /register you’ll be successfully redirected to our new shiny login view 😊!

The next route will take a little more. We need a route that would handle the login-values from our login-form. With handle I mean to authenticate the user and persist him in a session. So first in Routes/Routes.swift add:

Let me explain for short what we did here. As mentioned we want to be able to persist our User within a session. It’s super nice we have a Middlewares that do the work for us. In order to have persistence working we only need a few things. First: we need to conform our User to SessionPersistable which we did in Step 2 of this tutorial. Second: initialize the PersistMiddleware with our User. Then we decide what storage we want to use to persist the user on the server which is Memory here (it also means all session data will be purged once we restart the application) and initialize our SessionsMiddleware with it. The next thing we do with loginRoute is creating a RouteBuilder that has both Middlewares so their functionality are available for all routes we create with that RouteBuilder.

That’s why we can now be certain within our yet to be implemented postLogin function we can authenticate and persist a user. Let’s do it!

Within our Controllers/UserController.swift add the following:

Ohw I love how easy it actually is! If we would now cmd+r our project and go to /register to register ourself and then get redirected to /login and if we now type in our credentials we used for registration we will get redirected to a yet not existing route /profile BUT if you open up your developer console in your browser and look for your cookies you’ll find a vapor-session!

We are almost through! Next thing is to create a profile view so create a new file within Resources/Views/ and name it profile.leaf and add:

We will make the profile view only accessible for an authenticated user. Therefor within our Routes/Routes.swift add the following:

Again we have an awesome Middleware that does the authentication work for us. For a protected route we sure need again access to the persisted user in the session cookie and we add a Middleware that would use that data for an authentication check. That’s why we create a RouteBuilder named authRoute that has not only the SessionsMiddleware and the PersistMiddleware but also the PasswordAuthenticationMiddleware. All routes created with that RouteBuilder are secured to be accessible only if a user has logged in before.

Within our Controllers/UserController.swift return the profile view with:

What if I tell you that if you go and cmd+r to run your project now and try to access /profile you will get a 401 unauthorized? And that if you go and register yourself and then login that you will be redirected to /profile and then be able to access the secured view? Yes, it’s that mind-blowingly easy!

Ready for a two liner? Within Controllers/UserController.swift add:

And then go to Routes/Routes.swift and add:

NOTE: We use the RouteBuilder loginRoute here because we need access to the user who was persisted in the session in order to delete (unauthenticate) him 😊

And finally add a button to our Resources/Views/profile.leaf that fires it:

Our final cmd+r or run and refresh of our site and that’s it! You can try to access /profile it wont work, but if you register and login yourself you can access it and from there also logout again!

That’s it! You successfully implemented basic auth using session 🎉 🎉 🎉

It’s not complicated, quickly implemented and here we go: we would adjust our User within Models/User.swift to the following:

NOTE: The code above is sorta self explaining but in case it’s not don’t hesitate to ask or comment if you need any further explanation or help 😊!

Now the only thing left is to hash the users password before we store him. So within Controllers/UserController.swift add:

And. We. Are. Done. Through. Finished. Happy. Glad. Skilled. Level Up. 😊✨

I'm an always optimistic, open minded and knowledge seeking fullstack developer passionate about UI/UX and changing things for the better :)