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.