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 ?
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"}