gogo-fiber

My fiber session doesn't persist after a Save()


I'm currently creating a web API using fiber v2.

I added a simple basic authentication by using a simple middleware checking if the key exist in the session.

But I always end up getting 401 - Unauthorized because my fibber session is empty. I start my app, login (and so create a key in my session), and when I hit another route that is protected by my middleware/auth.go, the session is empty.

I separated my codes into multiple files and it looks like this:

// Web Server
app := fiber.New(fiber.Config{
    AppName:               "My App",
    WriteTimeout:          time.Minute,
    ReadTimeout:           time.Minute,
    BodyLimit:             20971520,
    DisableStartupMessage: true,
    Views:                 engine,
})

app.Use(middleware.AuthRequired)

session/session.go

var (
    store *session.Store
)

func GetSession() *session.Store {
    if store == nil {
        var config = session.Config{
            // Official documentation Recommend to use the __Host- prefix when serving the app over TLS
            KeyLookup:      "cookie:__Host-session",
            Expiration:     30 * time.Minute,
            CookieSecure:   true,
            CookieHTTPOnly: true,
            CookieSameSite: "Lax",
        }
        // Initialize a session store
        store = session.New(config)
    }

    return store
}

middleware/auth.go

func AuthRequired(c *fiber.Ctx) error {
    if c.Path() == "/login" {
        return c.Next()
    }

    session, err := sessions.GetSession().Get(c)
    if err != nil {
        return err
    }

    // Here my session.Get("username") will always return nil
    if session.Get("username") == nil {
        return c.SendStatus(fiber.StatusUnauthorized)
    }

    return c.Next()
}

handler/auth.go

func (h Handler) AuthLogin(c *fiber.Ctx, params Params) error {
    // Get the user, verify its password & co...

    // Create a session and save the username
    session, err := sessions.GetSession().Get(c)
    if err != nil {
        return err
    }

    session.Set("username", data.Username)
    if err := session.Save(); err != nil {
        return err
    }

    // Here my session.Get("username") correctly return my username
    logger.Error(fmt.Sprintf("@@@@@@@@@ %+v\n", session.Get("username")))
    return c.SendStatus(fiber.StatusOK)
}

From what I understood reading the documentation, Hitting the /login route will create a key "username" and store the value of the username in the session, and when I hit another route, the auth middleware should get the according session, get the username's key and let the user access to the route, but in the middleware, session.Get("username") always return <nil>, like the session didn't exist.

I'm currently testing my routes using curl like this:

curl -X POST http://localhost:4242/login -H 'Content-Type: application/json' -d '{"username":"toto","password":"tototata"}'
# -> 200 with a json OK response, no cookie or content returned

curl http://localhost:4242/hostname
# -> 401

Does anyone saw something odd in my code or reasonning ?


Solution

  • I figured out my code wasn't the issue.

    I didn't know how to use sessions, if I correctly add the session token in the cookie it does work.

    # Note I added the -v flag to enable the verbose mode and see the returned cookies
    > curl -X POST http://localhost:4242/login -H 'Content-Type: application/json' -d '{"username":"toto","password":"tototata"}' -v
    
    ...
    < Content-Type: text/plain; charset=utf-8
    < Content-Length: 2
    < Set-Cookie: session_id=1d002787-3795-4e21-ab50-4272c577037f; max-age=3600; path=/; HttpOnly; secure; SameSite=Strict
    < 
    * Connection #0 to host localhost left intact
    OK
    

    I had only to copy paste the cookie session like this:

    curl http://localhost:4242/hostname -H 'cookie:session_id=1d002787-3795-4e21-ab50-4272c577037f;'
    {"hostname":"titi"}