Skip to content

Persisting Auth

Persisting authentication means that a user does not need to provide their credentials with every request. This is useful for web apps where a user should only have to log in once.

Note

For APIs, it's recommended that the user send a token with every request. See Getting Started for an example about Token auth.

Sessions

Sessions are built into Vapor by default and are an easy way to persist users in your web app.

SessionPersistable

The first step is to conform your user model to the SessionPersistable protocol.

import AuthProvider

extension User: SessionPersistable {}

If your user is a Model, the protocol methods will be implemented automatically. However, you can implement them if you want to do something custom.

import AuthProvider
import HTTP

extension User: SessionPersistable {
    func persist(for: Request) throws {
        // something custom
    }

    static func fetchPersisted(for: Request) throws -> Self? {
        // something custom
    }
}

Middleware

Now that the user is SessionPersistable, we can create our middleware.

Sessions

First let's start by creating SessionsMiddleware. We'll use the MemorySessions() to get started.

let memory = MemorySessions()
let sessionsMiddleware = SessionsMiddleware(memory)

Persist

Now let's create the PersistMiddleware. This will take care of persisting our user once they've been authenticated.

let persistMiddleware = PersistMiddleware(User.self)

Since our user conforms to SessionPersistable (and thus Persistable), we can pass it into this middleware's init.

Authentication

Now to create the authentication middleware of your choice. We'll use PasswordAuthenticationMiddleware which requires an Authorization: Basic ... header with the user's username and password.

let passwordMiddleware = PasswordAuthenticationMiddleware(User.self)

!!! note: User must conform to PasswordAuthenticatable to be used with this middleware. See the Password section to learn more.

Droplet

Now we can create a Droplet and add all of our middleware.

import Vapor
import Sessions
import AuthProvider

let drop = try Droplet()

let authed = drop.grouped([sessionsMiddleware, persistMiddleware, passwordMiddleware])

Seealso

If you only want to globally require the password middleware, checkout the Middleware Config section in the HTTP docs.

Route

Now you can add a route to return the authenticated user.

authed.get("me") { req in
    // return the authenticated user
    return try req.auth.assertAuthenticated(User.self)
}

Request

Now we can make a request to our Vapor app.

GET /me HTTP/1.1
Authorization: Basic dmFwb3I6Zm9v 

Note

dmFwb3I6Zm9v is "vapor:foo" base64 encoded where "vapor" is the username and "foo" is the password. This is the format of Basic authorization headers.

And we should get a response like.

HTTP/1.1 200 OK
Content-Type: text/plain
Set-Cookie: vapor-session=...

Vapor

Notice the vapor-session in the response. This can be used in subsequent requests instead of the username and password.