I'm building a basic authentication setup similar to how it's used in Vapor's auth-template template (from here). I have everything set up the same way as in the template.
However, I would like to add salt. I can generate a salt for a user upon creation:
static func create(_ req: Request, newUserRequest user: CreateUserRequest) throws -> Future<User.Public> {
return User.query(on: req).filter(\.username == user.username).first().flatMap { existingUser in
guard existingUser == nil else {
throw Abort(.badRequest, reason: "A user with the given username already exists.")
}
guard user.password == user.passwordVerification else {
throw Abort(.badRequest, reason: "Given passwords did not match.")
}
let count = 16
var pw_salt_data = Data(count: count)
let _ = pw_salt_data.withUnsafeMutableBytes { mutableBytes in
SecRandomCopyBytes(kSecRandomDefault, count, mutableBytes)
}
let pw_salt = try BCrypt.hash(pw_salt_data.base64EncodedString())
let pw_hash = try BCrypt.hash(pw_salt + user.password)
return User(id: nil, username: user.username, pw_hash: pw_hash, pw_salt: pw_salt, email: user.email).save(on: req).toPublic()
}
}
But there's no way to retrieve that salt when performing authentication during login:
static func login(_ req: Request) throws -> Future<UserToken> {
let user = try req.requireAuthenticated(User.self)
let token = try UserToken.create(userID: user.requireID())
return token.save(on: req)
}
I want the salt to be randomly generated for each user and stored in the database as a separate column from the hashed password to be used later during authentication.
Is there a standardized way to handle salting a password hash in Vapor 3?