# Sessions

> Octelium documentation. Canonical page: <https://octelium.com/docs/octelium/latest/management/core/session>.

A *User* can interact with the *Cluster* and access its *Services* **only** through a valid *Session* that is automatically created by the *Cluster* upon valid authentication. A *User* needs to periodically re-authenticate to keep the *Session* valid until it eventually expires. A *Session* can be either client-based or clientless:

- `CLIENT` is used by the `octelium` and `octeliumctl` clients.
- `CLIENTLESS` is used by `HUMAN` *Users* via browsers or by `WORKLOAD` *Users* via the OAuth2 client credentials flow (read more [here](https://octelium.com/docs/octelium/latest/user/clientless/oauth2.md)), direct access tokens (read more [here](https://octelium.com/docs/octelium/latest/management/core/credential.md#access-tokens)), or simply via the SDK (read more [here](https://octelium.com/docs/octelium/latest/management/guide/sdk.md)).

## Listing Sessions

You can list the *Cluster*'s *Sessions* (read more about listing resources [here](https://octelium.com/docs/octelium/latest/management/core/overview.md#listing-resources)) as follows:

```bash
octeliumctl get session
# Or simply
octeliumctl get sess

# Or list by a certain User
octeliumctl get sess --user john

# Show a certain Session
octeliumctl get sess <NAME>
```

## Session Tokens

Whenever a *User* successfully authenticates to the *Cluster*, the *Cluster* issues 2 JWT-like tokens to the *User* representing the *Session*'s validity:

- **Access token** Used to access the *Cluster*'s *Services* and is sent as a bearer token via the `Authorization: Bearer <TOKEN>` or `X-Octelium-Auth: <TOKEN>` headers or via an "HttpOnly" cookie for clientless browser requests. An access token should be considered a short-term credential. By default, the *Cluster* sets that duration to 4 hours. Once the access token expires, the *User* must re-authenticate to obtain a new valid token pair to once again interact with the *Cluster* and access its *Services*.
- **Refresh token** Used to interact with the *Cluster* *Auth* API. The *Auth* API provides various gRPC methods for the *Users* to primarily re-authenticate themselves and log out of the *Cluster*. A refresh token has a longer duration than an access token (for example, it is by default set to 16 hours for `HUMAN` *Users*). Once a refresh token expires before another re-authentication, the *Session* as a whole is considered expired and it's due for automatic deletion by the *Cluster*. In other words, an expired refresh token means that the *Session* itself is expired, and the *User* can no longer re-authenticate, and has to authenticate to the *Cluster* over again to obtain another *Session* and interact with the *Cluster* once again.

Access tokens and refresh tokens are JWT-like tokens. This is an example of an access token:

```bash
AQpAfS0-x94CtdYeeAg9Pb7vHJ56mzSHmd6UggIN_Z5AdceEHJy6IsdvvRAE7eGlVOUnPJVOjdfb3Gve1W9iePhpCRJACAESEBI9RHpGwkSdrduoM3903FgaEGmk7Bgf6Elnk2yfI22X540iEIA-OGp3Yk-sll9LrttrWWIqBgixlfLDBg
```

A token is encoded in base64 and its binary content is serialized protobuf which helps reduce the overall token size compared to JSON used in JWTs for example. A token includes a payload/content and a signature for that payload. The payload has a few claims: a type (i.e. access token or refresh token), a subject (i.e. the *Session* UID), a token ID that is rotated with every re-authentication to keep track of the current valid token, a key ID to denote the corresponding key that signed the token and an expiry timestamp.

It is important to understand a valid access token, from a signature as well as an expiration timestamp perspective, is not enough for a certain request to be authenticated and authorized. In other words, *Services* do not merely verify the access token in a stateless manner, like in JWT, to authenticate and authorize a request. The process of authentication and authorization is a stateful operation that uses the information obtained from the access token to fetch the *Session*, its *User*, and the *User*'s *Groups* and *Device* if available to complete the authentication and authorization process. This allows for instant *Session* revocation. For example, the *Session* can be deleted at any time (read more [here](https://octelium.com/docs/octelium/latest/management/core/session.md#deleting-a-session)), rejected (read more [here](https://octelium.com/docs/octelium/latest/management/core/session.md#state)), its expiration extended or shortened (read more [here](https://octelium.com/docs/octelium/latest/management/core/session.md#expiration)), the *User* can be disabled (read more [here](https://octelium.com/docs/octelium/latest/management/core/user.md#disabling-users)). Such changes are reflected instantly on the decision of the authentication/authorization process on a per-request basis regardless of whether the access token itself is valid.

## Duration

You can control the *Cluster*-wide default durations for both the access token and the refresh token, as well as the *Session* whole durations, in the *ClusterConfig*. Read more [here](https://octelium.com/docs/octelium/latest/management/core/cluster-config.md#session). Here is an example:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  session:
    human:
      clientDuration:
        days: 1
      clientlessDuration:
        hours: 10
      maxPerUser: 32
      accessTokenDuration:
        hours: 4
      refreshTokenDuration:
        hours: 18
    workload:
      clientDuration:
        months: 6
      clientlessDuration:
        weeks: 1
      maxPerUser: 100
      accessTokenDuration:
        hours: 4
      refreshTokenDuration:
        weeks: 2
```

You can also control the *Session* durations on a per-*User* basis [here](https://octelium.com/docs/octelium/latest/management/core/user.md#session). Here is an example:

```yaml
kind: User
metadata:
  name: usr-1
spec:
  type: HUMAN
  # !mark(1:10)
  session:
    clientDuration:
      days: 1
    clientlessDuration:
      hours: 10
    maxPerUser: 100
    accessTokenDuration:
      hours: 4
    refreshTokenDuration:
      days: 1
```

## State

A *Session* has one of 3 states at a time, namely `ACTIVE`, `REJECTED` and `PENDING` as follows:

- `ACTIVE` indicates an active *Session* that can access any *Service* if authorized.
- `REJECTED` means that the *Session* is simply deactivated and cannot access any *Service* unless is set to `ACTIVE` again.
- `PENDING` indicates that the *Session* is still pending for a decision whether to be activated or deactivated or `REJECTED`.

The *Cluster* by default automatically sets the state for a newly created *Session* to `ACTIVE`. You can explicitly set a default *Session* state for a specific *User* (read more [here](https://octelium.com/docs/octelium/latest/management/core/user.md#session)) as follows:

```yaml
kind: User
metadata:
  name: john
spec:
  type: HUMAN
  # !mark(1:2)
  session:
    defaultState: ACTIVE
```

You can also set the default state at the *Cluster* level via *ClusterConfig* (read more [here](https://octelium.com/docs/octelium/latest/management/core/cluster-config.md#session)), separately for `HUMAN` and `WORKLOAD` *Users*, as follows:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  session:
    human:
      # !mark
      defaultState: PENDING
    workload:
      # !mark
      defaultState: ACTIVE
```

### Approving Sessions

You can approve a *Session* to set its state to `ACTIVE` simply as follows:

```bash
octeliumctl update session --approve <SESSION_NAME>
```

### Rejecting Sessions

You can reject a *Session* to set its state to `REJECTED` simply as follows:

```bash
octeliumctl update session --reject <SESSION_NAME>
```

## Expiration

You can manually change the expiration date for a *Session* using the `--expire-in` flag as follows:

```bash
octeliumctl update session --expire-in 2days <SESSION_NAME>
```

Some examples are `600seconds`, `45minutes`, `7hour`, `3days`, `2weeks`, `6months`.

## Deleting a Session

You can also delete a *Session* as follows:

```bash
octeliumctl delete session <SESSION_NAME>
```

## Access Control

You can control access to *Services* in your *Policies* based on the *Session* information. Here is an example:

```yaml
kind: Policy
metadata:
  name: session-misc
spec:
  rules:
    - effect: ALLOW
      condition:
        any:
          of:
            - match: ctx.session.status.type == "CLIENT"
            - match: ctx.session.status.type == "CLIENTLESS" && ctx.session.status.isBrowser
    - effect: ALLOW
      condition:
        all:
          of:
            - match: ctx.session.status.authentication.info.type == "IDENTITY_PROVIDER"
            - match: 'ctx.session.status.authentication.info.identityProvider.type in ["OIDC", "SAML"]'
```

### Geolocation

Since version `v0.23.0`, you can also use geolocation info (read more on how to enable it [here](https://octelium.com/docs/octelium/latest/management/core/cluster-config.md#geolocation)) stored in the *Session* for a geolocation-based access control on a per-request basis. Here is an example:

```yaml
kind: Policy
metadata:
  name: geolocation
spec:
  rules:
    - effect: ALLOW
      condition:
        any:
          of:
            - match: ctx.session.status.authentication.info.geoip.country.code == "US"
            - match: ctx.session.status.authentication.info.geoip.country.name == "France"
            - match: ctx.session.status.authentication.info.geoip.continent.code == "EU"
            - match: ctx.session.status.authentication.info.geoip.continent.name == "Africa"
            - match: ctx.session.status.authentication.info.geoip.city.name == "New York"
            - match: ctx.session.status.authentication.info.geoip.coordinates.longitude < 40.1
            - match: ctx.session.status.authentication.info.geoip.coordinates.latitude > 73.5
```

## API Reference

[Session JSON Schema (Octelium core/v1, latest documentation)](https://octelium.com/schemas/octelium/latest/core.v1.Session.schema.json)
