AuthenticatorMiddleware

Protocol for a middleware that checks if a request is authenticated.

Authenticator.swift:54
protocol AuthenticatorMiddleware : RouterMiddleware where Self.Context : AuthRequestContext
Browse conforming types

Requires an authenticate function that returns authentication data when successful. If it is unsuccessful then nil should be returned so middleware further down the middleware chain can do authentication. If you don’t want any further middleware to run then throw an error.

To use an authenticator middleware it is required that your request context conform to AuthRequestContext so the middleware can attach authentication data to identity.

A simple username, password authenticator could be implemented as follows. If the authenticator is successful it returns a User struct, otherwise it returns nil.

struct BasicAuthenticator<Context: AuthRequestContext>: AuthenticatorMiddleware {
    func authenticate(request: Request, context: Context) async throws -> User? {
        // Basic authentication info in the "Authorization" header, is accessible
        // via request.headers.basic
        guard let basic = request.headers.basic else { return nil }
        // check if user exists in the database
        guard let user = try await database.getUserWithUsername(basic.username) else {
            return nil
        }
        // verify password against password hash stored in database. If valid
        // return the user. HummingbirdAuth provides an implementation of Bcrypt
        // This should be run on the thread pool as it is a long process.
        return try await context.threadPool.runIfActive {
            if Bcrypt.verify(basic.password, hash: user.passwordHash) {
                return user
            }
            return nil
        }
    }
}