Image from: https://github.com/vapor/auth

Vapor 2 Authentication

Benjamin Baumann
The Swift Web Developer

--

Vapor offers a great toolset for user authentication and access restriction. It provides all the standard authentication procedures that are widely used.

This article will show how to register and authenticate with Basic Auth (Username and Password) via a web frontend. We will also create and persist a session for the authenticated user, so he does not need to send his credentials with every request and stays logged in.

Project Setup

Let’s create a new Vapor project with the following commands:

We will use the in memory database for now, this needs no configuration at all. The data will not be persist after you shut down the application. But for development this is fine.

If you hit run on the scheme Run > MyMac and go to http://0.0.0.0:8080 you should see this:

Now go to Packages.swift and add the fluent and auth packages so your file looks like this:

No go ahead and create fluent.json in the Config folder:

After that you have to fetch the depenencies and create the project again with the command:

vapor xcode

If you have compiler errors please run:

swift package update

and

vapor xcode

Creating the App

The app will need a User object which represents the user and handles the authentication. We will also need a Login and Registration Process via a web frontend which will be just two basic html forms.

So let’s create the User object: Under Sources we create a new group named “Models”. We select the group and press CMD + n and create a new Swift file named “User”. Make sure to select “App” as target. That’s it we have a User class.

The User will have to implement the following protocols:

Model, PasswordAuthenticatable and SessionPersistable

Model provides the interaction with the database via Fluent

PasswordAuthenticatable provides authentication methods to login and logout the user

SessionPersistable provides the methods which are necessary to enable sessions for the users

We now have to implement the needed methods from the User protocol in our user.The other protocols don’t need impementations as long as we have the “email” and “password” field for authentication. We can use their standard implementations. The User should look like so (only boilerplate code):

To hook the user into the database via fluent we have to adjust our config like so:

This adds the “User” to preparations. Vapor will prepare the database accordingly when starting. It will call the implementation of the “Preparations” protocol implementation on the “User” object and create the rows and tables.

Adding the frontend

Now we add the html interface to our app. For that create “register.leaf” and “login.leaf” under Resources > Views

.leaf files are the HTML templates which are built into Vapor.

Paste those snippets into the files or download them directly. What this does is only creating a very basic form which triggers a POST request to our server.

To wire this to our server go to Routes.swift and add the following routes in the “build” function:

The first two routes are GET requests which is the standard HTTP request when requesting a webpage. They create a html page out of our templates and send it to the client.

The POST method reads out the query paramters which we are sending to our backend and creates a new user with our credentials and a very basic input validation.

Now we can access the register and login page and create new users. The next step is to add protected routes which can only be accessed by authenticated users and a login function to authenticate a user.

In Vapor you can protect whole groups with as authentication mechanism so you don’t have to define it for every route yourself. We will now declare the routes of the “HelloController.swift” as protected routes.

We have to modify the Routes.swift as follows:

And add the droplet to parameters in Droplet+Setup.swift:

That’s it, now we have the ability to login with persisted sessions and to protect routes. Let’s do this now and modify again Routes.swift:

~Done~

You can now register on http://0.0.0.0:8080/register and then login on http://0.0.0.0:8080/login. After that you are authenticated and you can access http://0.0.0.0:8080/hello

Recap

If you build and run you should have a complete web app with username and password protection, registration and persisted sessions. It is the foundation of every bigger web app.

How it works:

When Vapor gets a request on a route that is password protected the session middleware checks if the request headers contain a valid session token. If yes, the user is authenticated by this token. If there is no token but a base64 encoded “Basic: jkansdkjad” including username and password, it tries to authenticate the user by those credentials. If that works a session token is created and persisted in the in memory database for sessions and sent back to the client as a cookie.

If none of those methods work an error with status code 401 — unauthorized is thrown and the resource it not presented to the user.

If you want to check out the complete project you can find it here:

Please feel free to ask or contact me if you have questions or if you want a tutorial on another Vapor topic.

--

--