Vapor 4 Authentication Issue [User is not authenticated]

Viewed 55

I have an iOS client with OAuth 2.0 as an authenticating mechanism.

When a user signs in, I authenticate him with this method (Google sign in for example):

 func processGoogleLogin(request: Request, token: String) throws -> EventLoopFuture<ResponseEncodable> {
    try Google
        .getUser(on: request)
        .flatMap { userInfo in
            User
                .query(on: request.db)
                .filter(\.$email == userInfo.email)
                .first()
                .flatMap { foundUser in
                    guard let existingUser = foundUser else {
                        //creating a new user
                        return user
                            .save(on: request.db)
                            .map {
                                request.session.authenticate(user)
                                //redirecting with info
                            }
                    }
                    request.session.authenticate(existingUser)
                    //redirecting with info
                }
        }
}

After the login, I want to check if the user is authenticated and if I've successfully authenticated the user. So I have an endpoint that I protect from unauthenticated users, but even after signing in, the user cannot access this endpoint as he is not authenticated.


Error:
{
"error": true,
"reason": "User not authenticated."
}

My User Model conforms to ModelSessionAuthenticatable.

I also use the SessionMiddleware (ImpreialController is the auth controller):

   let imperialController = ImperialController(sessionsMiddleware: app.sessions.middleware)
   app.middleware.use(app.sessions.middleware)

In ImperialController:
class ImperialController {
    private let sessionsMiddleware: Middleware
    
    init(sessionsMiddleware: Middleware) {
        self.sessionsMiddleware = sessionsMiddleware
    }
    ....

And finally the protected route:
let protected = app.grouped(User.guardMiddleware())

protected.get { req -> HTTPResponseStatus in
    return .ok
}
1 Answers

It may be that you are doing it, but just not showing it in your question. You need to create and register an instance of SessionsMiddleware using something like this:

app.middleware.use(SessionsMiddleware(session: MemorySessions(storage: MemorySessions.Storage())))

Do this before you create the instance of your controller.

EDIT in reply to OP' comment: I normally pass the instances of the different middleware explicitly because I tend to apply subsets to groups of routes rather than all the middleware. For example:

    app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
    app.middleware.use(SessionsMiddleware(session: MemorySessions(storage: MemorySessions.Storage())))
    app.middleware.use(User.sessionAuthenticator(.mysql))

    try app.register(collection: APIController(middleware: UserToken.authenticator()))

    var middleware: [Middleware] = [CustomMiddleware.InternalErrorMiddleware()]
    try app.register(collection: InsecureController(middleware: middleware))

    middleware.append(contentsOf: [User.redirectMiddleware(path: [C.URI.Solidus].string),
                                   User.authenticator(), User.guardMiddleware(),
                                   CustomMiddleware.SessionTimeoutMiddleware()])
    try app.register(collection: CustomerController(middleware: middleware))

BTW, have you included my line 3 above? That may be your problem.

Related