Sessions & Cookies

In this section we will learn how to configure Session cookies (and general HTTP cookies) in a more security-perspective view.

Disable Subdomain Persistence

By default Iris Sessions Manager allows cookie sharing between your root domain and subdomains, for security reasons you may want to disable that behavior with the DisableSubdomainPersistence option:

import "github.com/kataras/iris/v12/sessions"
sess := sessions.New(sessions.Config{
Cookie: "_iris_session",
AllowReclaim: true,
DisableSubdomainPersistence: true,
})
app.UseRouter(sess.Handler())

Contrariwise, the default cookie options have disabled the cookie sharing across subdomains. When working with HTTP cookies, the SameSite option should be set to http.SameSiteLaxMode and its Domain field to the current site domain in order to enable cookie sharing under a root domain and its subdomains. You can do it by setting the CookieAllowSubdomains Cookie Option to the Iris request Context:

CookieAllowSubdomains(cookieNames ...string) CookieOption
func routeHandler(ctx iris.Context) {
ctx.SetCookieKV("name", "value", iris.CookieAllowSubdomains())
}
import "net/http"
// [...]
func routeHandler(ctx iris.Context) {
ctx.SetCookie(&http.Cookie{
Name: "name",
Value: "value",
// Other Fields...
}, iris.CookieAllowSubdomains())
}

Or by using the AddCookieOptions.

func middleware(ctx iris.Context) {
ctx.AddCookieOptions(iris.CookieAllowSubdomains())
ctx.Next()
}
func routeHandler(ctx iris.Context) {
ctx.SetCookieKV("name", "value")
}
func main() {
app := iris.New()
app.Use(middleware)
app.Get("/", routeHandler)
// [...]
}

Cookie Encryption

Like the CSRF token, we learnt about in the previous sections, you can also secure all cookies in general.

The iris.CookieEncoding option registers a SecureCookie implementation.

CookieEncoding(encoding SecureCookie, cookieNames ...string) CookieOption

The SecureCookie interface looks like this:

type SecureCookie interface {
Encode(name string, val interface{}) (string, error)
Decode(name string, original string, dest interface{}) error
}

The SecureCookie interface is 100% compatible with the gorilla/securecookie package. Which is simple and easy to use and it does its job very good.

Let's see how we can integrate it with Iris to safely transmit our cookies to clients. Note that, it's still highly recommended your server runs under TLS (https://).

1. Install the securecookie package:

$ go get -u github.com/gorilla/securecookie

2. Import it in your code:

import "github.com/gorilla/securecookie"

3. The securecookie requires hash and block keys, should be NOT shared publically. For the sake of the example we will use generated ones but, keep note that the keys should be persistence across server restarts in production stage in order for cookies to be validated as expected:

hashKey := securecookie.GenerateRandomKey(64)
blockKey := securecookie.GenerateRandomKey(32)

4. Initialize a secure cookie instance:

s := securecookie.New(hashKey, blockKey)

5. Register it with the Iris CookieEncoding Option, as we've seen below there are several ways, depending when and where you need a cookie option to be applied:

import "net/http"
// [...]
func routeHandler(ctx iris.Context) {
ctx.SetCookie(&http.Cookie{
Name: "name",
Value: "value",
}, iris.CookieEncoding(s))
}
func main() {
app := iris.New()
app.Get("/", routeHandler)
// [...]
}

OR to register it on all cookies, using a middleware and calling the AddCookieOption Context method:

func routeHandler(ctx iris.Context) {
ctx.SetCookie(&http.Cookie{
Name: "name",
Value: "value",
})
}
func main() {
app := iris.New()
app.UseRouter(func(ctx iris.Context) {
ctx.AddCookieOptions(iris.CookieEncoding(s))
ctx.Next()
})
app.Get("/", routeHandler)
// [...]
}