Session Middleware for Fiber
The session
middleware provides session management for Fiber applications, utilizing the Storage package for multi-database support via a unified interface. By default, session data is stored in memory, but custom storage options are easily configurable (see examples below).
As of v3, we recommend using the middleware handler for session management. However, for backward compatibility, v2's session methods are still available, allowing you to continue using the session management techniques from earlier versions of Fiber. Both methods are demonstrated in the examples.
Table of Contentsβ
Migration Guideβ
v2 to v3β
-
Function Signature Change: In v3, the
New
function now returns a middleware handler instead of a*Store
. To access the store, use theStore
method on*Middleware
(obtained fromsession.FromContext(c)
in a handler) or useNewStore
orNewWithStore
. -
Session Lifecycle Management: The
*Store.Save
method no longer releases the instance automatically. You must manually callsess.Release()
after using the session to manage its lifecycle properly. -
Expiration Handling: Previously, the
Expiration
field represented the maximum session duration before expiration. However, it would extend every time the session was saved, making its behavior a mix between session duration and session idle timeout. TheExpiration
field has been removed and replaced withIdleTimeout
andAbsoluteTimeout
fields, which explicitly defines the session's idle and absolute timeout periods.-
Idle Timeout: The new
IdleTimeout
, handles session inactivity. If the session is idle for the specified duration, it will expire. The idle timeout is updated when the session is saved. If you are using the middleware handler, the idle timeout will be updated automatically. -
Absolute Timeout: The
AbsoluteTimeout
field has been added. If you need to set an absolute session timeout, you can use this field to define the duration. The session will expire after the specified duration, regardless of activity.
-
For more details about Fiber v3, see Whatβs New.
Migrating v2 to v3 Example (Legacy Approach)β
To convert a v2 example to use the v3 legacy approach, follow these steps:
- Initialize with Store: Use
session.NewStore()
to obtain a store. - Retrieve Session: Access the session store using the
store.Get(c)
method. - Release Session: Ensure that you call
sess.Release()
after you are done with the session to manage its lifecycle.
When using the legacy approach, the IdleTimeout will be updated when the session is saved.
Example Conversionβ
v2 Example:
store := session.New()
app.Get("/", func(c *fiber.Ctx) error {
sess, err := store.Get(c)
if err != nil {
return err
}
key, ok := sess.Get("key").(string)
if !ok {
return c.SendStatus(fiber.StatusInternalServerError)
}
sess.Set("key", "value")
err = sess.Save()
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return nil
})
v3 Legacy Approach:
store := session.NewStore()
app.Get("/", func(c fiber.Ctx) error {
sess, err := store.Get(c)
if err != nil {
return err
}
defer sess.Release() // Important: Release the session
key, ok := sess.Get("key").(string)
if !ok {
return c.SendStatus(fiber.StatusInternalServerError)
}
sess.Set("key", "value")
err = sess.Save()
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return nil
})
v3 Example (Recommended Middleware Handler)β
Do not call sess.Release()
when using the middleware handler. sess.Save()
is also not required, as the middleware automatically saves the session data.
For the recommended approach, use the middleware handler. See the Middleware Handler (Recommended) section for details.
Typesβ
Configβ
Defines the configuration options for the session middleware.
type Config struct {
Storage fiber.Storage
Next func(fiber.Ctx) bool
Store *Store
ErrorHandler func(fiber.Ctx, error)
KeyGenerator func() string
KeyLookup string
CookieDomain string
CookiePath string
CookieSameSite string
IdleTimeout time.Duration
AbsoluteTimeout time.Duration
CookieSecure bool
CookieHTTPOnly bool
CookieSessionOnly bool
}
Middlewareβ
The Middleware
struct encapsulates the session middleware configuration and storage, created via New
or NewWithStore
.
type Middleware struct {
Session *Session
}
Sessionβ
Represents a user session, accessible through FromContext
or Store.Get
.
type Session struct {}
Storeβ
Handles session data management and is created using NewStore
, NewWithStore
or by accessing the Store
method of a middleware instance.
type Store struct {
Config
}
Signaturesβ
Session Package Functionsβ
func New(config ...Config) *Middleware
func NewWithStore(config ...Config) (fiber.Handler, *Store)
func FromContext(c fiber.Ctx) *Middleware
Config Methodsβ
func DefaultErrorHandler(fiber.Ctx, err error)
Middleware Methodsβ
func (m *Middleware) Set(key string, value any)
func (m *Middleware) Get(key string) any
func (m *Middleware) Delete(key string)
func (m *Middleware) Destroy() error
func (m *Middleware) Reset() error
func (m *Middleware) Store() *Store
Session Methodsβ
func (s *Session) Fresh() bool
func (s *Session) ID() string
func (s *Session) Get(key string) any
func (s *Session) Set(key string, val any)
func (s *Session) Destroy() error
func (s *Session) Regenerate() error
func (s *Session) Release()
func (s *Session) Reset() error
func (s *Session) Save() error
func (s *Session) Keys() []string
func (s *Session) SetIdleTimeout(idleTimeout time.Duration)
Store Methodsβ
func (*Store) RegisterType(i any)
func (s *Store) Get(c fiber.Ctx) (*Session, error)
func (s *Store) GetByID(id string) (*Session, error)
func (s *Store) Reset() error
func (s *Store) Delete(id string) error
GetByID
Methodβ
The GetByID
method retrieves a session from storage using its session ID. Unlike Get
, which ties the session to a fiber.Ctx
(request-response cycle), GetByID
operates independently of any HTTP context. This makes it ideal for scenarios such as background processing, scheduled tasks, or non-HTTP-related session management.
Key Featuresβ
- Context Independence: Sessions retrieved via
GetByID
are not bound tofiber.Ctx
. This means the session can be manipulated in contexts that aren't tied to an active HTTP request-response cycle. - Background Task Suitability: Use this method when you need to manage sessions outside of the standard HTTP workflow, such as in scheduled jobs, background tasks, or any non-HTTP context where session data needs to be accessed or modified.
Usage Considerationsβ
- Manual Persistence: Since there is no associated
fiber.Ctx
, changes made to the session (e.g., modifying data) will not automatically be saved to storage. You must callsession.Save()
explicitly to persist any updates to storage. - No Automatic Cookie Handling: Any updates made to the session will not affect the client-side cookies. If the session changes need to be reflected in the client (e.g., in a future HTTP response), you will need to handle this manually by setting the cookies via other methods.
- Resource Management: After using a session retrieved by
GetByID
, you should callsession.Release()
to properly release the session back to the pool and free up resources.
Example Use Casesβ
- Scheduled Jobs: Retrieve and update session data periodically without triggering an HTTP request.
- Background Processing: Manage sessions for tasks running in the background, such as user inactivity checks or batch processing.
Examplesβ
Security Notice: For robust security, especially during sensitive operations like account changes or transactions, consider using CSRF protection. Fiber provides a CSRF Middleware that can be used with sessions to prevent CSRF attacks.
Middleware Order: The order of middleware matters. The session middleware should come before any handler or middleware that uses the session (for example, the CSRF middleware).
Middleware Handler (Recommended)β
package main
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/csrf"
"github.com/gofiber/fiber/v3/middleware/session"
)
func main() {
app := fiber.New()
sessionMiddleware, sessionStore := session.NewWithStore()
app.Use(sessionMiddleware)
app.Use(csrf.New(csrf.Config{
Store: sessionStore,
}))
app.Get("/", func(c fiber.Ctx) error {
sess := session.FromContext(c)
if sess == nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
name, ok := sess.Get("name").(string)
if !ok {
return c.SendString("Welcome anonymous user!")
}
return c.SendString("Welcome " + name)
})
app.Listen(":3000")
}
Custom Storage Exampleβ
package main
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/storage/sqlite3"
"github.com/gofiber/fiber/v3/middleware/csrf"
"github.com/gofiber/fiber/v3/middleware/session"
)
func main() {
app := fiber.New()
storage := sqlite3.New()
sessionMiddleware, sessionStore := session.NewWithStore(session.Config{
Storage: storage,
})
app.Use(sessionMiddleware)
app.Use(csrf.New(csrf.Config{
Store: sessionStore,
}))
app.Listen(":3000")
}
Session Without Middleware Handlerβ
package main
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/csrf"
"github.com/gofiber/fiber/v3/middleware/session"
)
func main() {
app := fiber.New()
sessionStore := session.NewStore()
app.Use(csrf.New(csrf.Config{
Store: sessionStore,
}))
app.Get("/", func(c fiber.Ctx) error {
sess, err := sessionStore.Get(c)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
defer sess.Release()
name, ok := sess.Get("name").(string)
if !ok {
return c.SendString("Welcome anonymous user!")
}
return c.SendString("Welcome " + name)
})
app.Post("/login", func(c fiber.Ctx) error {
sess, err := sessionStore.Get(c)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
defer sess.Release()
if !sess.Fresh() {
if err := sess.Regenerate(); err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
}
sess.Set("name", "John Doe")
err = sess.Save()
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.SendString("Logged in!")
})
app.Listen(":3000")
}
Custom Types in Session Dataβ
Session data can only be of the following types by default:
string
int
int8
int16
int32
int64
uint
uint8
uint16
uint32
uint64
bool
float32
float64
[]byte
complex64
complex128
interface{}
To support other types in session data, you can register custom types. Here is an example of how to register a custom type:
package main
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/session"
)
type User struct {
Name string
Age int
}
func main() {
app := fiber.New()
sessionMiddleware, sessionStore := session.NewWithStore()
sessionStore.RegisterType(User{})
app.Use(sessionMiddleware)
app.Listen(":3000")
}
Configβ
Property | Type | Description | Default |
---|---|---|---|
Storage | fiber.Storage | Defines where session data is stored. | nil (in-memory storage) |
Next | func(c fiber.Ctx) bool | Function to skip this middleware under certain conditions. | nil |
ErrorHandler | func(c fiber.Ctx, err error) | Custom error handler for session middleware errors. | nil |
KeyGenerator | func() string | Function to generate session IDs. | UUID() |
KeyLookup | string | Key used to store session ID in cookie or header. | "cookie:session_id" |
CookieDomain | string | The domain scope of the session cookie. | "" |
CookiePath | string | The path scope of the session cookie. | "/" |
CookieSameSite | string | The SameSite attribute of the session cookie. | "Lax" |
IdleTimeout | time.Duration | Maximum duration of inactivity before session expires. | 30 * time.Minute |
AbsoluteTimeout | time.Duration | Maximum duration before session expires. | 0 (no expiration) |
CookieSecure | bool | Ensures session cookie is only sent over HTTPS. | false |
CookieHTTPOnly | bool | Ensures session cookie is not accessible to JavaScript (HTTP only). | true |
CookieSessionOnly | bool | Prevents session cookie from being saved after the session ends (cookie expires on close). | false |
Default Configβ
session.Config{
Storage: memory.New(),
Next: nil,
Store: nil,
ErrorHandler: nil,
KeyGenerator: utils.UUIDv4,
KeyLookup: "cookie:session_id",
CookieDomain: "",
CookiePath: "",
CookieSameSite: "Lax",
IdleTimeout: 30 * time.Minute,
AbsoluteTimeout: 0,
CookieSecure: false,
CookieHTTPOnly: false,
CookieSessionOnly: false,
}