Authentication doesn't work on deployment to vapor.cloud

I’ve implemented authentication to my app, and it works perfectly locally on my development machine. I have deployed it vapor.cloud and I have reset the database. Created the admin user, and I can see the user when I use the API to check on the users. However, I cannot seem to log in after the deployment. Am I missing something on deployment?

my index handler looks like this.

// Default route where the templates will spawn from
func indexHandler(_ request: Request) throws -> Future<View> {
    
  // query the database to get all users
    return User.query(on: request).all().flatMap(to: View.self) { users in

        let currentUser = try request.authenticated(User.self)
    
        let context = IndexContext(title: "HomePage", users: users.isEmpty ? nil : users, authenticatedUser: currentUser)
        
        return try request.leaf().render("index", context)
    }
}

I can see that when it’s local it currentUser is fulfilled with the logged in user. I’m assuming the server is logging me in, but is not able to get the current user. I can tell by the route history, that my login was successful, but it sent me back to my login, because I’m not authenticated because my currentUser is nil.

@yungdai are there any cookies getting set etc? It should all ‘just work’ :tm: but there may be some differences.

Simple obvious questions:

Have you committed all your changes?
How are you setting up sessions?
What version of the packages are you running?

I’ve had Vapor Cloud login working so I know it should work.

  1. I’m using the same Chrome browser for the local as the vapor.cloud app. I’ve also tried using Safari as well. Cookies are set, because I can see them in the browser afterwards.

  2. I’m setting up the sessions like this:

    func loginPostHandler(_ request: Request) throws → Future {

    // send the data from the form to the decode function
    return try request.content.decode(LoginPostData.self).flatMap(to: Response.self) { data in
        
        // this requires you to import Crypto for password encyption
        let verifier = try request.make(BCryptDigest.self)
        return User.authenticate(username: data.userName, password: data.password, using: verifier, on: request).map(to: Response.self) { user in
            
            // FAILURE:
            // TODO: Throw up a real error on the login page
            guard let user = user else {
                return request.redirect(to: "/login")
            }
            
            try request.authenticateSession(user)
            return request.redirect(to: "/")
        }
    }
    

    }

pretty much exactly as you had written.

I’ve committed all my changes for sure before I sent it, because after I committed it, I ran it locally as well to troubleshoot using the same code.

These are my package versions:

    // 💧 A server-side Swift web framework.
    .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0-rc.2"),

    // 🔵 Swift ORM (queries, models, relations, etc) built on PostgreSQL.
    .package(url: "https://github.com/vapor/fluent-postgresql.git", from: "1.0.0-rc.2"),
    
    // This is the package to add Leaf 🍁 support
    .package(url: "https://github.com/vapor/leaf.git", from: "3.0.0-rc"),
    
    // This package is for authentication
    .package(url: "https://github.com/vapor/auth.git", from: "2.0.0-rc.2")

What about setting up the sessions with configure.swift?

/// Register providers first
try services.register(FluentPostgreSQLProvider())
// Added for Leaf Support
try services.register(LeafProvider())
// Added for Authentication Support
try services.register(AuthenticationProvider())

/// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
/// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(DateMiddleware.self) // Adds `Date` header to responses
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response

// This middleware adds sessions to the application
middlewares.use(SessionsMiddleware.self)

Yup it’s there. I can’t see why it wouldn’t work on the site and not works locally when compiled.

Yeah I don’t know! I’ll be coming to web login for the book soon so will be able to investigate this.