AuthenticatorMiddleware
Protocol for a middleware that checks if a request is authenticated.
protocol AuthenticatorMiddleware : RouterMiddleware where Self.Context : AuthRequestContext
Browse conforming typesRequires 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
}
}
}