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.