> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> How Atoti UI retrieves a JWT from the jwtServer and uses it across embedded and remote deployment setups, covering the login and logout flows, WebSocket authentication via cookie, CORS configuration, and custom authentication via configuration.higherOrderComponents.

Atoti UI authenticates all its HTTP requests to [Atoti Server](https://docs.activeviam.com/engine/java-sdk/latest/) and the [content server](https://docs.activeviam.com/engine/java-sdk/latest/content_server/cs_overview/) with a [JWT](https://jwt.io/).
It also authenticates the opening of a [WebSocket](https://developer.mozilla.org/docs/Web/API/WebSockets_API) against Atoti Server in order to perform real-time MDX queries, using a [cookie](https://developer.mozilla.org/docs/Web/HTTP/Cookies).

This page describes how Atoti UI retrieves the JWT and cookie by default.
This flow depends on whether Atoti UI is served by the JWT server itself, or by a remote web server.

<Note>
  Atoti UI works with any authentication scheme by default. You can use it
  off-the-shelf, independently from whether you use a login form, LDAP, OIDC,
  Kerberos, etc. on the server side.
</Note>

## Server requirements

There are requirements on the server side for users to be able to authenticate on Atoti UI:

* One of your servers must expose a `jwt` service returning the JWT when receiving a `GET` request carrying the valid session cookie of an authenticated user. This server is referred to as the **JWT server** throughout the documentation and it is typically the content server, although it can also be one of the Atoti servers.

<Note>
  The `jwtServer` property in
  [`env.js`](./install-and-start/set-up#configure-server-connections-env-js)
  configures the URL and version of this server.
</Note>

* The JWT must be shared by all servers: Atoti UI authenticates once against the JWT server, and is then able to communicate with all servers.
* Each Atoti server in the solution must expose a `ping` endpoint, which responds with a `pong` success message and sets a cookie upon receiving a `GET` request authenticated with the JWT. This is necessary for Atoti UI to [open WebSockets](#websockets).

## Embedded Atoti UI

In this scenario, the Atoti UI assets are served directly by the JWT server, and they are protected by its security filters.

<Tip>
  This is the recommended way of serving Atoti UI, as this significantly
  simplifies the configuration (CORS, cookie security, etc.) and authentication
  flow (server redirection logic, number of network roundtrips, loading of Atoti
  UI assets, etc.).
</Tip>

### Login

For example, let's assume that the content server is configured to be the JWT server and to serve Atoti UI at path `/ui/index.html`
The authentication flow goes as follows:

* The user visits `contentServerUrl/ui/index.html` in their browser. From there, two things can happen:
  * The user is already logged in: a valid session cookie is already set in the browser for the content server. In that case:
    * Atoti UI's `index.html` is loaded, and its JavaScript is run.
    * A request is made to the `/jwt` service of the JWT server (= content server in this case) in order to retrieve the JWT, authenticated thanks to the session cookie.
    * The JWT server responds with a status code 200 and a JWT.
    * This JWT is used in all further requests to all servers (including the Atoti servers and the content server defined in `env.js`).
  * The user is not logged in: no session cookie is set, or it is invalid. In that case:
    * The server redirects the user to `/login`.
    * Upon successful login, the server redirects to `/ui/index.html`.
    * Atoti UI's `index.html` is loaded, and its JavaScript is run (see above).

```mermaid theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
sequenceDiagram
    participant Browser
    participant Content server as Content server = JWT server = server hosting Atoti UI
    participant Atoti server

    rect rgb(191, 223, 255)
        Note left of Browser: Fetch Atoti UI assets
        Browser->>+Content server: Visit contentServerUrl/ui/index.html
        Content server-->>-Browser: Redirect to contentServerUrl/login
        Browser->>+Content server: Credentials (e.g. POST username:password in a form login)
        Content server-->>-Browser: Redirect to contentServerUrl/ui/index.html, with session cookie
        Browser->>+Content server: GET JavaScript scripts
        Content server-->>-Browser: JavaScript scripts, including env.js
    end
    Browser->>Browser: Run JavaScript scripts, including reading the target servers from env.js
    rect rgb(191, 223, 255)
        Note left of Browser: Get JWT
        Browser->>+Content server: GET /jwt (authenticated with session cookie)
        Content server-->>-Browser: JWT
    end
    Browser->>Browser: Provides the JWT in the React context, and authenticates all further requests with it
    par
        Browser->>+Content server: Request dashboards, settings, permissions, etc.
        Content server-->>-Browser: Dashboards, settings, permissions, etc.
    and
        Browser->>+Atoti server: Request data model
        Atoti server -->>-Browser: Data model
    and
        rect rgb(191, 223, 255)
            Note left of Browser: Open WebSocket
            Browser->>+Atoti server: Ping authenticated with JWT
            Atoti server-->>-Browser: Pong with Atoti server cookie
            Browser->>Atoti server: Open WebSocket, authenticated with the cookie
        end
    end
    Browser->>+Atoti server: MDX query
    Atoti server -->>-Browser: Cellset
```

### Logout

When the user logs out from Atoti UI, its JavaScript navigates to the `/logout` page of the JWT server, and sends a `POST /logout` request to all other Atoti servers and the content server.

Here is a sequence diagram to illustrate this, where the content server is configured to be the JWT server and to serve Atoti UI.

```mermaid theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
sequenceDiagram
    participant Browser
    participant UI as Web server hosting Atoti UI
    participant JWT server as Content server = JWT server = server hosting Atoti UI
    participant Atoti server

    rect rgb(191, 223, 255)
        Note left of Browser: Logout
        Browser->>Browser: User clicks logout in Atoti UI
        par
          Browser->>+Atoti server: POST /logout
        and
          Browser->>+JWT server: Visit jwtServerUrl/logout
        end
       JWT server->>-Browser: Redirect to an "after logout" page
    end
```

## Remote Atoti UI

### Additional server requirements

Serving Atoti UI from a remote web server adds the following constraints on the JWT server:

* An unauthenticated call to the `/jwt` service must yield a 401.
* Upon successfully authenticating on `/login?redirectUrl=myAtotiUIUrl`, the server must redirect to `myAtotiUIUrl`, with a session cookie set for `jwtServer`.

### Login

The login flow then goes as follows:

* When Atoti UI's JavaScript is run, a request is made to the `/jwt` service of the JWT server in order to retrieve the JWT. From there, two things can happen:
  * The user is already logged in: a valid session cookie is already set in the browser for the JWT server. In that case:
    * The JWT server responds with a status code 200 and a JWT.
    * This JWT is used in all further requests to all servers (including the Atoti servers and the content server defined in `env.js`).
  * The user is not logged in: no session cookie is set, or it is invalid. In that case:
    * The JWT server responds with a [401](https://developer.mozilla.org/docs/Web/HTTP/Status/401) status code.
    * Upon receiving it, Atoti UI redirects the user to the `/login` page of the JWT server, with the `redirectUrl` [search parameter](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) set to the current URL (where the user accessed Atoti UI).
    * Upon successful login, the JWT server redirects the user to Atoti UI (thanks to the `redirectUrl` search parameter) with a valid session cookie for the JWT server.
    * Atoti UI sends a request to the `/jwt` service again, which is successful this time thanks to the cookie (see above).

Here is a sequence diagram to illustrate this flow, where the content server is configured to be the JWT server.

```mermaid theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
sequenceDiagram
    participant Browser
    participant UI as Web server hosting Atoti UI
    participant Content server as Content server = JWT server
    participant Atoti server

    rect rgb(191, 223, 255)
        Note left of Browser: Fetch Atoti UI assets and initiate authentication on the JWT server
        Browser->>+UI: Visit atotiUIUrl
        UI-->>-Browser: index.html
        Browser->>+UI: GET JavaScript scripts
        UI-->>-Browser: JavaScript scripts, including env.js
        Browser->>Browser: Run JavaScript scripts, including reading the target servers from env.js
        Browser->>+Content server: GET /jwt (unauthenticated because no session cookie yet)
        Content server-->>-Browser: 401
        Browser->>+Content server: Visit jwtServerUrl/login?redirectUrl=atotiUIUrl
        Content server-->>-Browser: jwtServerUrl/login.html (for example with form login)
        Browser->>+Content server: POST username:password
    end
    rect rgb(191, 223, 255)
    Note left of Browser: Get the JWT
        Content server-->>-Browser: Redirect to atotiUIUrl, with session cookie
        Browser->>+Content server: GET JavaScript scripts
        Content server-->>-Browser: JavaScript scripts, including env.js
        Browser->>Browser: Run JavaScript scripts, including reading the target servers from env.js
        Browser->>+Content server: GET /jwt (this time authenticated with session cookie)
        Content server-->>-Browser: JWT
    end
    Browser->>Browser: Provides the JWT in the React context, and authenticates all further requests with it
    par
        Browser->>+Content server: Request dashboards, settings, permissions, etc.
        Content server-->>-Browser: Dashboards, settings, permissions, etc.
    and
        Browser->>+Atoti server: Request data model
        Atoti server -->>-Browser: Data model
    and
        rect rgb(191, 223, 255)
            Note left of Browser: Open WebSocket
            Browser->>+Atoti server: Ping authenticated with JWT
            Atoti server-->>-Browser: Pong with Atoti server cookie
            Browser->>Atoti server: Open WebSocket, authenticated with the cookie
        end
    end
    Browser->>+Atoti server: MDX query
    Atoti server -->>-Browser: Cellset
```

Notice how this is more complex than the [embedded](#embedded-atoti-ui) setup.
On top of the additional constraints on the server and the added network roundtrips, you will potentially have to configure [CORS](https://developer.mozilla.org/fr/docs/Web/HTTP/CORS) and handle third-party cookies if you deploy your UI and server on different domains.
In particular, note that [third-party cookies are deprecated or blocked by default in most major browsers](https://developer.mozilla.org/en-US/blog/goodbye-third-party-cookies/).

### Logout

This is the same as in the [embedded case](#logout).

## Websockets

As illustrated in the diagrams above, Atoti UI securely opens a WebSocket against each Atoti server it is connected to.

Since in the WebSocket protocol HTTP headers cannot be passed in the [opening handshake](https://websockets.spec.whatwg.org/#websocket-opening-handshake), and in particular the JWT cannot be passed as an `Authorization` header, Atoti UI authenticates the WebSocket through a cookie instead.

To obtain this cookie before actually opening the WebSocket, Atoti UI first makes a request on the Atoti server's `ping` endpoint, authenticated with the JWT.
If the JWT is valid, Atoti Server responds with a `pong` success message which sets a cookie in the user's browser for this server.

Note that:

* This cookie must not be confused with the session cookie associated with the JWT server and allowing the login flow described above (unless the Atoti server itself is used as the JWT server, as opposed to the content server for example).
* Cookies are set by domain, but not by port, so if you deploy several servers at different ports on the same domain in your Atoti solution, you need to use a different cookie name for each server.

## Opting out of the default flow - Custom authentication

As described in the sections above, Atoti UI works off-the-shelf with any authentication scheme on the server side, without requiring any custom JavaScript code on the client side.

But if you still want to opt out of this default behavior, you can implement a custom authentication flow.
To do so, use your own [`configuration.higherOrderComponents`](./reference/types#configuration) instead of `withAuthenticatedClientsAndUser` in your Atoti UI extensions.
