Home > Net >  Vapor bearer auth with UserAuthenticator() always fails with 401 Unauthorized
Vapor bearer auth with UserAuthenticator() always fails with 401 Unauthorized

Time:06-21

I am new to Vapor and I am trying to add a login endpoint. I am following Vapor documentation on Bearer Authentication from https://docs.vapor.codes/security/authentication/#bearer

My implementation so far:

struct UserAuthenticator: AsyncBearerAuthenticator {

func authenticate(bearer: BearerAuthorization, for request: Request) async throws {
    typealias User = App.User

    let loginUser = try request.query.decode(LoginUserDTO.self)

    guard let user = try await User.query(on: request.db)
        .filter(\.$email == loginUser.email)
        .first(),
    let userId = user.id else {
        throw Abort(.notFound)
    }

    guard let userToken = try await UserToken.query(on: request.db)
        .filter(\.$user.$id == userId)
        .first() else {
        throw Abort(.notFound)
    }

    if bearer.token == userToken.value {
        request.auth.login(loginUser.toUser())
    }
}

}

My user Model class has an extension:

extension User: ModelAuthenticatable {
    static var usernameKey = \User.$email
    static var passwordHashKey = \User.$passwordHash

    func verify(password: String) throws -> Bool {
        self.passwordHash == password.generateHash(salt: salt)
    }
}

my routes file has this protected route:

    let protected = app.grouped(UserAuthenticator())
    protected.post("login") { request async throws -> ClientTokenReponse in
        let user: User = try request.auth.require(User.self)
        return ClientTokenReponse(token: "token")
    }

When I try to login with postman I always get a 401 Unauthorized, if I try to debug the UserAuthenticator class, it doesn't even stop at the breakpoint. What am I doing wrong?

CodePudding user response:

You are mixing two separate things, login and route protection.

AsyncBearerAuthenticator should not be used for the call to login, only for routes where the user should already be logged in with a token.

First the user should make a call to login to get a token. This can still be protected in some way, generally a user will have to provide a password. You can see this a bit further down in the Vapor documentation.

Your UserAuthenticator should only verify that the token is valid and match it to a user.

  • Related