# 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:

```go
import "github.com/kataras/iris/v12/sessions"
```

```go
sess := sessions.New(sessions.Config{
    Cookie: "_iris_session",
    AllowReclaim: true,
    DisableSubdomainPersistence: true,
})
app.UseRouter(sess.Handler())
```

The Sessions Manager has its own field to configure the session cookie encryption in order to be independent from other cookies sent to the client. You can pass `Cookie Options` at the `sess.Handler(...CookieOption)` method too.

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:

```go
CookieAllowSubdomains(cookieNames ...string) CookieOption
```

```go
func routeHandler(ctx iris.Context) {
    ctx.SetCookieKV("name", "value", iris.CookieAllowSubdomains())
}
```

```go
import "net/http"
// [...]

func routeHandler(ctx iris.Context) {
    ctx.SetCookie(&iris.Cookie{
        Name: "name",
        Value: "value",
        // Other Fields...
    }, iris.CookieAllowSubdomains())
}
```

Or by using the `AddCookieOptions`.

```go
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.

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

The `SecureCookie` interface looks like this:

```go
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](https://github.com/kataras/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
$ go get -u github.com/gorilla/securecookie
```

**2.** Import it in your code:

```go
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:

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

**4.** Initialize a secure cookie instance:

```go
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:

```go
import "net/http"
// [...]

func routeHandler(ctx iris.Context) {
    ctx.SetCookie(&iris.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:

```go
func routeHandler(ctx iris.Context) {
    ctx.SetCookie(&iris.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)
    // [...]
}
```

## Cookie SameSite

The introduction of the SameSite attribute (defined in [RFC6265](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00)) allows you to declare if your cookie should be restricted to a first-party or same-site context. It's helpful to understand exactly what 'site' means here. The site is the combination of the domain suffix and the part of the domain just before it. For example, the `www.web.dev` domain is part of the `web.dev` site.

> If the user is on `www.web.dev` and requests an image from `static.web.dev` then that is a same-site request.

The [public suffix](https://publicsuffix.org/) list defines this, so it's not just top-level domains like .com but also includes services like `github.io`. That enables `your-project.github.io` and `my-project.github.io` to count as separate sites.

> If the user is on `your-project.web.dev` and requests an image from `my-project.github.io` that's a cross-site request.

Introducing the `SameSite` attribute on a cookie provides three different ways to control this behaviour. You can choose to not specify the attribute, or you can use Strict or Lax to limit the cookie to same-site requests.

The `SameSite` attribute accepts three values:

* `Lax` Cookies are allowed to be sent with top-level navigations and will be sent along with GET request initiated by third party website. This is the default value in modern browsers.
* `Strict` Cookies will only be sent in a first-party context and not be sent along with requests initiated by third party websites.
* `None` Cookies will be sent in all contexts, i.e sending cross-origin is allowed. None used to be the default value, but recent browser versions made **Lax the default value** to have reasonably robust defense against some classes of cross-site request forgery (CSRF) attacks. None requires the [Secure](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Secure) attribute in latest browser versions.

Available Cookie SameSite Values:

* `iris.SameSiteDefaultMode`
* `iris.SameSiteLaxMode`
* `iris.SameSiteStrictMode`
* `iris.SameSiteNoneMode`

Set `SameSite` with `SetCookie`:

```go
ctx.SetCookie(&iris.Cookie{
    Name: ...,
    Value: ...,
    SameSite: iris.SameSiteLaxMode,
})
```

Set `SameSite` with `AddCookieOptions`:

```go
ctx.AddCookieOptions(iris.CookieSameSite(iris.SameSiteLaxMode))
```

Set `SameSite` with `SetCookieKV`:

```go
ctx.SetCookieKV(name, value, iris.CookieSameSite(iris.SameSiteLaxMode))
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://iris-go.gitbook.io/iris/security/security-sessions-cookies.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
