Skip to content

Instantly share code, notes, and snippets.

@hannesmnagel
Last active June 2, 2025 18:08
Show Gist options
  • Select an option

  • Save hannesmnagel/5d108dc94aae8945530a5fc454705cfd to your computer and use it in GitHub Desktop.

Select an option

Save hannesmnagel/5d108dc94aae8945530a5fc454705cfd to your computer and use it in GitHub Desktop.
Sessionauthentication in Vapor
import NIOSSL
import Fluent
import FluentPostgresDriver
import Vapor
func configure(_ app: Application) async throws {
app.databases.use(DatabaseConfigurationFactory.postgres(configuration: .init(
hostname: Environment.get("DATABASE_HOST") ?? "localhost",
port: Environment.get("DATABASE_PORT").flatMap(Int.init(_:)) ?? SQLPostgresConfiguration.ianaPortNumber,
username: Environment.get("DATABASE_USERNAME") ?? "vapor_username",
password: Environment.get("DATABASE_PASSWORD") ?? "vapor_password",
database: Environment.get("DATABASE_NAME") ?? "vapor_database",
tls: .prefer(try .init(configuration: .clientDefault)))
), as: .psql)
app.migrations.add(CreateUser())
app.sessions.use(.memory)
try await app.autoMigrate()
app.middleware.use(app.sessions.middleware)
try routes(app)
}
func routes(_ app: Application) throws {
app.grouped(User.sessionAuthenticator()).get("login") { req in
let users = try await User.query(on: req.db).all()
if let user = users.first {
print("new request..........................................")
print("user id is: ", user.sessionID.uuidString)
print(req.session.data)
print(req.cookies)
print("authenticated: ", req.session.authenticated(User.self) as Any)
req.session.data["test"] = Date().formatted(date: .omitted, time: .complete) //this works
print("authenticating.......................................")
req.session.authenticate(user)
print(req.session.data)
print(req.cookies)
print("authenticated: ", req.session.authenticated(User.self) as Any)
print("request finished....................................")
return HTTPStatus.ok
} else {
try await User(id: .generateRandom(), password: "abc123")?.create(on: req.db)
return .created
}
}
}
final class User: Model, @unchecked Sendable, Authenticatable, ModelSessionAuthenticatable {
static let passwordHashKey: KeyPath<User, Field<String>> = \.$passwordHash
static let schema = "users"
@ID(key: .id)
var id: UUID?
@Field(key: "password_hash")
var passwordHash: String
init() {}
init(id: UUID, passwordHash: String) {
self.id = id
self.passwordHash = passwordHash
}
init?(id: UUID, password: String) {
guard let hash = try? Bcrypt.hash(password) else { return nil }
self.id = id
self.passwordHash = hash
}
func verify(password: String) -> Bool {
(try? Bcrypt.verify(password, created: passwordHash)) == true
}
var sessionID: UUID {id!}
}
//Here is the output I get in the console when opening /login and then reloading:
/*
[ INFO ] GET /login [request-id: AE5E90A7-3374-4674-A13B-F9FED662DF88]
new request..........................................
user id is: 40D257B1-3AC6-451C-BD2F-ECD56EFF5D21
SessionData(storage: [:])
HTTPCookies(cookies: [:])
authenticated: nil
authenticating.......................................
SessionData(storage: ["_UserSession": "40D257B1-3AC6-451C-BD2F-ECD56EFF5D21", "test": "19:55:22 GMT+2"])
HTTPCookies(cookies: [:])
authenticated: Optional(40D257B1-3AC6-451C-BD2F-ECD56EFF5D21)
request finished....................................
[ INFO ] GET /login [request-id: 7FD30D3A-2B28-4EC9-90A1-6BEC2B19B8D7]
new request..........................................
user id is: 40D257B1-3AC6-451C-BD2F-ECD56EFF5D21
SessionData(storage: ["test": "19:55:22 GMT+2"])
HTTPCookies(cookies: ["vapor-session": Vapor.HTTPCookies.Value(string: "xIrkV7J9G4YBT4BGW2c8Y16dIT+22V0bIHiiaK0QtV8=", expires: nil, maxAge: nil, domain: nil, path: Optional("/"), isSecure: false, isHTTPOnly: false, sameSite: Optional(Vapor.HTTPCookies.SameSitePolicy.lax))])
authenticated: nil
authenticating.......................................
SessionData(storage: ["_UserSession": "40D257B1-3AC6-451C-BD2F-ECD56EFF5D21", "test": "19:55:23 GMT+2"])
HTTPCookies(cookies: ["vapor-session": Vapor.HTTPCookies.Value(string: "xIrkV7J9G4YBT4BGW2c8Y16dIT+22V0bIHiiaK0QtV8=", expires: nil, maxAge: nil, domain: nil, path: Optional("/"), isSecure: false, isHTTPOnly: false, sameSite: Optional(Vapor.HTTPCookies.SameSitePolicy.lax))])
authenticated: Optional(40D257B1-3AC6-451C-BD2F-ECD56EFF5D21)
request finished....................................
[ INFO ] GET /login [request-id: D6A89CC6-BEEA-4582-9DFD-B4FCCB01CB21]
new request..........................................
user id is: 40D257B1-3AC6-451C-BD2F-ECD56EFF5D21
SessionData(storage: ["test": "19:55:23 GMT+2"])
HTTPCookies(cookies: ["vapor-session": Vapor.HTTPCookies.Value(string: "xIrkV7J9G4YBT4BGW2c8Y16dIT+22V0bIHiiaK0QtV8=", expires: nil, maxAge: nil, domain: nil, path: Optional("/"), isSecure: false, isHTTPOnly: false, sameSite: Optional(Vapor.HTTPCookies.SameSitePolicy.lax))])
authenticated: nil
authenticating.......................................
SessionData(storage: ["_UserSession": "40D257B1-3AC6-451C-BD2F-ECD56EFF5D21", "test": "19:58:53 GMT+2"])
HTTPCookies(cookies: ["vapor-session": Vapor.HTTPCookies.Value(string: "xIrkV7J9G4YBT4BGW2c8Y16dIT+22V0bIHiiaK0QtV8=", expires: nil, maxAge: nil, domain: nil, path: Optional("/"), isSecure: false, isHTTPOnly: false, sameSite: Optional(Vapor.HTTPCookies.SameSitePolicy.lax))])
authenticated: Optional(40D257B1-3AC6-451C-BD2F-ECD56EFF5D21)
request finished....................................
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment