# Security

Source: https://docs.interop.io/desktop/getting-started/security/index.html

## Overview

The following sections provide general guidelines on how to:

- Configure your **io.Connect Desktop** platform in order to optimize the security measures applied to the io.Connect Gateway connections and the Electron window containers created by the underlying Electron framework.

- Configure various security-related settings for your interop-enabled apps.

## io.Connect Gateway

The io.Connect Gateway acts as a message bus between the io.Connect platform and all client apps, facilitating the communication and the data sharing between all interop-enabled apps. **io.Connect Desktop** provides settings for the io.Connect Gateway that allow you to fully control which clients will be able to connect to the io.Connect Gateway.

The configuration settings for the io.Connect Gateway are located under the `"configuration"` property of the `"gw"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**. It's possible to configure the network access to the io.Connect Gateway and filter the connections by origin.

### Network Access

By default, the io.Connect Gateway is bound to loopback and is accessible only to local processes running on the same machine. To configure the network access to the io.Connect Gateway, use the `"ip"` property:

```json
{
    "gw": {
        "configuration": {
            // Set to `127.0.0.1` by default.
            // If set to `0.0.0.0`, will allow access to the io.Connect Gateway to all processes in the same network
            // and will render any origin filters useless.
            // Use this with caution in production environments.
            "ip": "127.0.0.1"
        }
    }
}
```

### Origin Filtering

The io.Connect Gateway supports connection filtering based on the `Origin` header of the connection.

To configure the origin filter for the io.Connect Gateway, use the `"origin_filters"` property of the `"security"` object. The following example demonstrates how to allow connections from a trusted origin, block connections from other origins, and block connection requests in which the `Origin` header is missing:

```json
{
    "gw": {
        "configuration": {
            "security": {
                "origin_filters": {
                    "whitelist": ["#https://my-org.com/.*"],
                    "missing": "blacklist",
                    "non_matched": "blacklist"
                }
            }
        }
    }
}
```

The `"origin_filters"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"blacklist"` | `string[]` | List of origins to block from connecting to the io.Connect Gateway. You can also use regular expressions (patterns must start with `#`). Defaults to `[]`. |
| `"missing"` | `"whitelist"` \| `"blacklist"` | Action to take if the `Origin` header in the connection request is missing. Defaults to `"whitelist"`. |
| `"non_matched"` | `"whitelist"` \| `"blacklist"` | Action to take if the origin isn't matched by the filters for allowing or blocking origins. Defaults to `"blacklist"`. |
| `"whitelist"` | `string[]`  | List of origins for which to allow connections to the io.Connect Gateway. You can also use regular expressions (patterns must start with `#`). The default origin filters are described below. |

> ⚠️ *Note that if you decide to open the [network access](#ioconnect_gateway-network_access) instead of binding the io.Connect Gateway to loopback, the origin filters will be rendered useless since any untrusted app on the network can impersonate the `Origin` header.*

Available since io.Connect Desktop 10.0

The default origin filters specified in the `system.json` file of **io.Connect Desktop** enable the platform to use the built-in [launcher](https://docs.interop.io/desktop/capabilities/launcher/index.md) and the various demo apps distributed with the trial version. You should change these values to suit the needs of your project environment and improve the security of your platform.

The following example demonstrates the default **io.Connect Desktop** origin filters:

```json
{
    "gw": {
        "configuration": {
            "security": {
                "origin_filters": {
                    // Allow apps that don't set the `Origin` header (e.g., Java, Node.js demo apps).
                    "missing": "whitelist",
                    "whitelist": [
                        // Allow apps loaded by the platform from local files (e.g., the built-in launcher).
                        "#file://.*",
                        // Allow apps that use the WebSocket protocol (e.g., .NET demo apps).
                        "#ws://.*",
                        // Allow apps loaded in the browser from local files.
                        "null",
                        // Allow apps hosted at `localhost`.
                        "#http(s)?://localhost:\\d+",
                        // Allow other demo apps hosted at the specified domains.
                        "#https://(.*\\.)?interop\\.io",
                        "#https://(.*\\.)?glue42\\.com",
                        "#https://(.*\\.)?tick42\\.com",
                        "#https://(.*\\.)?finos\\.org"
                    ],
                    // All other origins will be blocked.
                    "non_matched": "blacklist"
                }
            }
        }
    }
}
```

### Authentication

**io.Connect Desktop** authenticates in two distinct phases, controlled by two different top-level keys in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file - `"auth"` and `"ssoAuth"`. Both accept the same [authentication controller](https://docs.interop.io/desktop/assets/configuration/authController.json) settings, but they run at different points of the startup sequence and their results are used for different purposes.

[Choosing the appropriate approach](#ioconnect_gateway-authentication-choosing_an_approach) depends mainly on your deployment scenario.

#### Before Connecting to the io.Connect Gateway

The `"auth"` top-level key controls how the platform itself logs in to the io.Connect Gateway. The authentication controller runs before the platform establishes a connection with the io.Connect Gateway, and the credentials it produces (user name and password, access token, or Windows identity) are sent as the login for that connection. Until authentication completes, the platform doesn't connect to the io.Connect Gateway and startup is suspended - no app stores are fetched and no apps are started:

```json
{
    "auth": {
        "authController": "sso"
    }
}
```

Besides an authentication controller, the `"auth"` key also accepts explicit credentials (`"username"` and `"password"`), or a string that will be used as a user name. If it's omitted, the platform logs in to the io.Connect Gateway as the currently logged in OS user.

The [login screen](#authentication-login_screen) and the `authDone()` method for [signaling the platform](#authentication-signaling_the_platform) work in the same way for both keys. However, when using the `"auth"` key, the definition of your SSO app must be available in a [system app store](https://docs.interop.io/desktop/developers/configuration/system/index.md#system_app_stores) - regular app stores are fetched only after the platform has connected to the io.Connect Gateway. Note also that the value passed to the `token` property of `authDone()` will be used as the login for the io.Connect Gateway connection. If you don't provide a token, the platform will attempt to log in with the user name and an empty password.

#### After Connecting to the io.Connect Gateway

The `"ssoAuth"` top-level key controls the user-facing authentication that runs after the platform has already established a connection with the io.Connect Gateway. The resulting user name, token, and headers are used to establish the identity of the user for the remote data stores (apps, Layouts, and app preferences), for requests to [**io.Manager**](https://docs.interop.io/manager/overview/index.md) and for any other remote service the platform contacts. Apps configured to auto start at the `"post-sso"` stage are started only after this authentication completes.

> ℹ️ *For details on how to configure SSO authentication that runs after the platform has established a connection with the io.Connect Gateway, see the [Authentication](#authentication) section.*

#### Authenticators

The `"auth"` key defines only how the platform authenticates itself. Which credentials the io.Connect Gateway accepts (and therefore what any other client must present) is configured separately via the `"authentication"` property of the `"configuration"` object under the `"gw"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:

```json
{
    "gw": {
        "configuration": {
            "authentication": {
                "available": ["basic"],
                "default": "basic"
            }
        }
    }
}
```

The `"authentication"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"available"` | `string[]` | List of the authenticators to enable. Defaults to `["basic"]`. |
| `"basic"` | `object` | Settings for the built-in `"basic"` authenticator. |
| `"default"` | `string` | The authenticator to use when the client doesn't specify one. Defaults to `"basic"`. |
| `"oauth2"` | `object` | Settings for the built-in `"oauth2"` authenticator. It's required to use the `"issuerBaseURL"` and `"audience"` properties to specify the identity provider against which to validate the token. |

The following authenticators are available:

| Authenticator | Description |
|---------------|-------------|
| `"basic"` | Validates a user name and password, as well as access tokens issued by the io.Connect Gateway itself. Enabled by default. |
| `"oauth2"` | Validates an access token issued by an external identity provider. Requires `"issuerBaseURL"` and `"audience"` to be specified. Required when [OIDC authentication](#authentication-openid_connect) has been configured by using the `"auth"` top-level key, in which case it must also be set as the default authenticator. |
| `"win"` | Validates a Windows identity via SSPI. Required when using the `"sspi"` authentication controller. Available only on Windows. |

> ⚠️ *Note that the `"authentication"` object replaces the default settings entirely - it isn't merged with them. If you enable another authenticator, but your apps still connect with a user name and password, you must keep `"basic"` in the list of enabled authenticators.*

> ⚠️ *Note that the `"oauth2"` authenticator doesn't accept explicit endpoints. The io.Connect Gateway always resolves the JWKS endpoint and the issuer of your identity provider from its metadata document, discovered at `/.well-known/openid-configuration` or at `/.well-known/oauth-authorization-server` relative to `"issuerBaseURL"`. Identity providers that don't publish a metadata document at either location can't be used with the `"auth"` top-level key.*

#### Choosing an Approach

Use the `"auth"` key when the io.Connect Gateway itself must be protected - e.g., when it isn't running on the user machine, but is hosted remotely or is part of an [**io.Bridge**](https://docs.interop.io/bridge/general-overview/index.md) deployment. In these cases, the io.Connect Gateway is reachable over the network and the login credentials the platform presents are what prevents an unauthorized client from connecting.

If the io.Connect Gateway is deployed locally and bound to loopback (the default), using the `"ssoAuth"` key is generally the better choice. In this case, the io.Connect Gateway is reachable only from the local machine and the [origin filters](#ioconnect_gateway-origin_filtering) provide an additional restriction for browser-based clients. The origin filters aren't an authentication mechanism - the default filters allow connections without an `Origin` header so that native clients (e.g., Java or .NET apps) can connect, which means that a local process can still attempt a connection. Configure the origin filters to your environment and don't treat them as a replacement for io.Connect Gateway authentication if untrusted local processes are a concern.

## Electron App

**io.Connect Desktop** uses the [Electron](https://www.electronjs.org/) framework for hosting web apps in windows on the desktop. This means that the security of your interop-enabled web apps is largely affected by the underlying security features and policies of the Electron framework. To avoid any potential security risks in the underlying Electron framework, the **io.Connect Desktop** platform is updated with the latest Electron version with each release. Therefore, it's highly recommended that clients upgrade their platforms to the latest io.Connect version too.

While regular upgrades can help improve your platform security, it's also important to be aware of and properly configure the available security settings related to the Electron window containers.

All security settings related to Electron windows are available on system level via the `"system"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**, and per app (for web apps only) via the `"system"` property of the `"details"` top-level key in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md) files. The settings in the app definition will override the settings in the system configuration.

All settings, except `"onCertificateError"` and `"allowedExternalURISchemes"`, correspond exactly to the settings found in the [`WebPreferences`](https://www.electronjs.org/docs/latest/api/structures/web-preferences) object that describes the options for creating a [`BrowserWindow`](https://www.electronjs.org/docs/latest/api/browser-window) instance. The settings imported directly from the `WebPreferences` object have the same default values as in Electron.

> ℹ️ *For more details and best practices regarding the Electron security settings, see the [Security Tutorial](https://www.electronjs.org/docs/latest/tutorial/security) in the official Electron documentation.*

The `"security"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"allowedExternalURISchemes"` | `string[]` | List of external URI schemes that are allowed to be opened. Use this to allow opening external URI schemes that aren't handled by the Electron framework by default. |
| `"allowRunningInsecureContent"` | `boolean` | If `true`, will allow an HTTPS page to run JavaScript, CSS or plugins from HTTP URLs. Defaults to `false`. |
| `"contextIsolation"` | `boolean` | If `true`, will allow running code in preload scripts and in Electron APIs in a dedicated JavaScript context. Context isolation allows each script running in the renderer process to make changes to its JavaScript environment without conflicting with scripts in the Electron API or preload script. Defaults to `false`. |
| `"navigateOnDragDrop"` | `boolean` | If `true`, dragging and dropping a file or a link onto the page will trigger navigation. Defaults to `false`. |
| `"nodeIntegration"` | `boolean` | If `true`, will enable Node.js integration. Defaults to `false`. |
| `"onCertificateError"` | `object` | Settings for handling web pages with invalid certificates. |
| `"sandbox"` | `boolean` | If `true` (default), the renderer associated with the window will be sandboxed, making it compatible with the Chromium OS-level sandbox and disabling the Node.js engine. |
| `"webSecurity"` | `boolean` | If `true` (default), web security will be enabled. Set to `false` to disable the same-origin policy (e.g., for testing purposes) and to set `"allowRunningInsecureContent"` to `true`. |

The `"onCertificateError"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"action"` | `"allow"` \| `"deny"` \| `"ask"` | Controls the behavior for loading web pages with invalid certificates - whether to allow or deny loading the page, or to ask the user. Defaults to `"deny"`. |
| `"reportURL"` | `string` | URL pointing to a page that will be shown to the user and will allow them to report the issue. Only valid if `"action"` is set to `"ask"`. |

## io.Connect Apps

The [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) of **io.Connect Desktop** and the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md) files enable you to configure various permission settings for your interop-enabled apps on a global level and per app respectively. You can use these settings to grant or deny permissions to your apps for accessing environment resources (cookies, OS info, environment variables, and more) or for performing certain actions (overriding app definition properties programmatically, executing code, manipulating request and response headers, and more).

For configuring the permissions for your apps, see the following sections:

- Access to [environment variables](https://docs.interop.io/desktop/capabilities/more/apis/index.md#environment_variables).
- Access to [OS info](https://docs.interop.io/desktop/capabilities/more/apis/index.md#os_info).
- Access to [auth info](#authentication).
- Allowing [app definition overrides](https://docs.interop.io/desktop/developers/configuration/application/index.md#app_definition_overrides).
- Allowing [script execution](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.md#window_operations-execute_code).
- Allowing [cookies manipulation](https://docs.interop.io/desktop/capabilities/more/apis/index.md#cookies)
- Allowing [request headers manipulation](https://docs.interop.io/desktop/capabilities/more/apis/index.md#request_headers).
- Allowing [response headers manipulation](https://docs.interop.io/desktop/developers/configuration/application/index.md#modifying_response_headers).
- Allowing [proxy settings manipulation](https://docs.interop.io/desktop/capabilities/more/apis/index.md#proxy_settings).
- Allowing [clearing cache](https://docs.interop.io/desktop/capabilities/more/apis/index.md#clearing_cache).
- Filtering URLs when [opening new windows](https://docs.interop.io/desktop/developers/configuration/application/index.md#opening_new_windows).
- Handling the [browser native `window.open()`](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.md#opening_windows-handling_the_browser_windowopen)
- Using  [isolated app sessions](https://docs.interop.io/desktop/developers/configuration/application/index.md#isolated_browser_sessions_for_apps) to separate the cookies, cache, local and session storage of your apps.

## Authentication

This section describes how to configure and use authentication for your interop-enabled apps within **io.Connect Desktop** when the platform has already established a connection with the io.Connect Gateway.

> ℹ️ *For details on how to configure SSO authentication that runs before the platform has established a connection with the io.Connect Gateway, see the [io.Connect Gateway > Authentication](#ioconnect_gateway-authentication) section.*

**io.Connect Desktop** doesn't provide a built-in support for any particular authentication mechanism, but rather provides mechanisms for easily integrating your already existing authentication processes. This design decision allows you to keep your existing authentication flows and processes unchanged, while still being able to leverage the io.Connect platform and its capabilities.

The io.Connect platform enables you to show a [login screen](#authentication-login_screen) (an SSO app) before the first client app has been loaded. The io.Connect API injected in the SSO app provides a method for [signaling the platform](#authentication-signaling_the_platform) when a user has been successfully authenticated. You can also pass to the platform any relevant information about the authenticated user, which the platform in turn will pass to **io.Manager** and to any other remote store connected to **io.Connect Desktop**. This information can later be retrieved by other apps in order to enhance the SSO flow when authentication is needed for additional services.

It's also possible to configure **io.Connect Desktop** to use SSO with [Microsoft Entra ID](#authentication-entra_id_sso) and [OpenID Connect](#authentication-openid_connect).

### Login Screen

To enable using a login screen, you have to modify the system configuration of **io.Connect Desktop** and create an [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md) file for your SSO app. To complete the authentication process and allow the user access, you have to signal io.Connect that the user has logged in successfully.

The SSO app is a special system app that is loaded on startup of **io.Connect Desktop** and allows the user to authenticate. If authentication is successful, then all other app definitions are fetched and loaded based on user permissions.

There are two ways you can define your SSO app:

- By creating a standalone SSO [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md) file, adding it to a system app store of **io.Connect Desktop**, and enabling SSO authentication via the `system.json` file of **io.Connect Desktop** (see [Standalone SSO App Definition](#authentication-login_screen-standalone_sso_app_definition)). This is the recommended approach, as it allows you more freedom in configuring your SSO app.

- By defining your SSO app directly in the `system.json` file of **io.Connect Desktop** (see [SSO via System Configuration](#authentication-login_screen-sso_via_system_configuration)). Not recommended, as this way you can control only a very limited number of properties for the SSO app.

> ⚠️ *Note that no matter how you choose to define your SSO app, it will have [cookies manipulation](https://docs.interop.io/desktop/capabilities/more/apis/index.md#cookies) and [access to OS info](https://docs.interop.io/desktop/capabilities/more/apis/index.md#os_info) enabled by default, even if you don't set these properties in its definition file, because SSO apps usually need such permissions in order to complete the authentication process.*

#### Standalone SSO App Definition

If you decide to use a standalone app definition file for your SSO app, follow these steps:

1. Enable the login screen by using the `"ssoAuth"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop** and setting its `"authController"` property to `"sso"`:

```json
{
    "ssoAuth": {
        "authController": "sso"
    }
}
```

> ℹ️ *For details on the available properties for configuring the authentication mechanism of **io.Connect Desktop**, see the [authentication controller schema](https://docs.interop.io/desktop/assets/configuration/authController.json).*

2. Create an [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md) file for your SSO app.

> ⚠️ *Note that it's mandatory to use `"sso-application"` as a name for your app in the definition. Otherwise, **io.Connect Desktop** won't recognize your SSO app and will load the built-in login screen.*

The following is an example definition of an SSO app:

```json
{
    "name": "sso-application",
    "title": "My SSO App",
    "icon": "https://example.com/icon.ico",
    "type": "window",
    "details": {
        "url": "https://example.com",
        "mode": "html",
        "width": 400,
        "height": 400,
        "startLocation": "center"
    }
}
```

3. Add your SSO app definition to a [system app store](https://docs.interop.io/desktop/developers/configuration/system/index.md#system_app_stores) of **io.Connect Desktop**. A system app store contains system app definitions that are loaded before all other app definitions. Use the `"systemAppStores"` top-level key in the `system.json` file to define a local or a remote system app store and provide the location of your SSO app definition.

The following example demonstrates how to configure a local system app store:

```json
{
    "systemAppStores": [
        {
            "type": "path",
            "details": {
                "path": "./config/system-apps"
            }
        }
    ]
}
```

#### SSO via System Configuration

> ⚠️ *Note that this approach isn't recommended, because you can define only a very limited number of properties for your SSO app. *

Enable the login screen by using the `"ssoAuth"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop** and setting its `"authController"` property to `"sso"`. Use the `"options"` property to provide the location of the login screen and settings for the io.Connect Window in which it will be loaded:

```json
{
    "ssoAuth": {
        "authController": "sso",
        "options": {
            "url": "http://localhost:3000/",
            "window": {
                "width": 500,
                "height": 730,
                "mode": "flat"
            }
        }
    }
}
```

The `"options"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"keepAlive"` | `boolean` | If `true`, **io.Connect Desktop** won't close the login window. This way, you can hide it yourself and use it to refresh the authentication arguments (user, token and headers) when necessary. |
| `"url"` | `string` | Location of the login screen. If not provided, will default to the location of the built-in login screen of **io.Connect Desktop**. |
| `"window"` | `object` | Settings for the io.Connect Window in which the login screen will be loaded. |

The `"window"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"height"` | `integer` | Height in pixels for the login window. |
| `"hidden"` | `boolean` | If `true`, the login window will be hidden. *Available since **io.Connect Desktop** 9.4.* |
| `"mode"` | `string` | io.Connect Window [mode](https://docs.interop.io/desktop/capabilities/windows/window-management/overview/index.md#window_modes). Possible values are `"html"` (default), `"flat"` and `"tab"`. |
| `"width"` | `integer` | Width in pixels for the login window. |

> ℹ️ *For details on the available properties for configuring the authentication mechanism of **io.Connect Desktop**, see the [authentication controller schema](https://docs.interop.io/desktop/assets/configuration/authController.json).*

#### Visibility

Available since io.Connect Desktop 9.4

The visibility of the login screen can be controlled via configuration and programmatically.

For [standalone SSO app definitions](#authentication-login_screen-standalone_sso_app_definition), use the `"hidden"` property of the `"details"` top-level key in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md):

```json
{
    "name": "sso-application",
    "title": "My SSO App",
    "icon": "https://example.com/icon.ico",
    "type": "window",
    "details": {
        "url": "https://example.com",
        "mode": "html",
        "width": 400,
        "height": 400,
        "startLocation": "center",
        // Will hide the login screen from the user.
        "hidden": true
    }
}
```

For [SSO apps defined via system configuration](#authentication-login_screen-sso_via_system_configuration), use the `"hidden"` property of the `"window"` object under the `"options"` property of the `"ssoAuth"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:

```json
{
    "ssoAuth": {
        "authController": "sso",
        "options": {
            "url": "http://localhost:3000/",
            "window": {
                "width": 500,
                "height": 730,
                "mode": "flat",
                // Will hide the login screen from the user.
                "hidden": true
            }
        }
    }
}
```

If you need to show or hide the SSO app dynamically, but don't want to initialize the entire [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) library, use the `showWindow()` and `hideWindow()` methods of the `iodesktop` object injected in the global `window` object:

```javascript
// Hide the login window.
await iodesktop.hideWindow();

// Show the login window.
await iodesktop.showWindow();
```

### Signaling the Platform

To allow the user access after authenticating, you must signal **io.Connect Desktop** that the authentication process is complete. Use the `authDone()` method of the `iodesktop` object which is injected in the global `window` object. It accepts an optional object as an argument in which you can specify the name of the authenticated user, а token and headers:

```javascript
const options = {
    user: "john.doe@org.com",
    token: "token",
    headers: {
        "name": "value"
    }
};

iodesktop.authDone(options);
```

The optional object passed as an argument to `authDone()` has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `headers` | `object` | JSON object with extra headers that will be passed to the remote stores or [**io.Manager**](https://docs.interop.io/manager/overview/index.md). |
| `user` | `string` | The user ID will be set as a value of the `sid` property of `iodesktop`. Can be used for visualization purposes. |
| `token` | `string` | The token will be applied to each request to the remote stores or [**io.Manager**](https://docs.interop.io/manager/overview/index.md). |

The authentication information passed to the `authDone()` method can be later retrieved by other apps in order to enhance the SSO flow when authentication is needed for additional services. To allow apps to retrieve authentication information, use the `"allowAuthInfo"` property of the `"details"` top-level key in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md):

```json
{
    "details": {
        "allowAuthInfo": true
    }
}
```

To retrieve the authentication information dynamically, use the `getAuth()` method of the `iodesktop` object:

```javascript
const authInfo = await iodesktop.getAuth();
```

### Microsoft Entra ID SSO

Available since io.Connect Desktop 9.12 & 10.0.4

**io.Connect Desktop** supports seamless SSO authentication with Microsoft Entra ID by automatically injecting Windows proof-of-possession cookies into requests to specified Microsoft Entra ID login URLs.

To enable SSO with Microsoft Entra ID, use the `"entraSSO"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file:

```json
{
    "entraSSO": {
        "enabled": true,
        "urls": [
            "https://login.microsoftonline.com/*",
            "https://login.microsoft.com/*",
            "https://login.live.com/*",
            "https://*.microsoftonline.com/*"
        ]
    }
}
```

The `"entraSSO"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"enabled"` | `boolean` | If `true`, will enable proof-of-possesion cookie injection for Microsoft Entra ID authentication. Defaults to `false`. |
| `"urls"` | `string[]` | List of Microsoft Entra ID login URLs for which proof-of-possession cookies will be injected. Supports wildcard symbols (`*`). The default Microsoft Entra ID endpoints are included by default. |

### OpenID Connect

Available since io.Connect Desktop 10.4

**io.Connect Desktop** supports authentication via the OpenID Connect (OIDC) protocol. Authentication is performed by a trusted identity provider and control is returned to the io.Connect platform via a loopback HTTP server or a custom protocol scheme. This enables you to authenticate your users against any identity provider supporting OIDC (Microsoft Entra ID, Auth0, Okta, Google, Keycloak, and more) without having to implement your own authentication controller.

The claim extracted from the ID token becomes the identity of the authenticated user, which is then published to the io.Connect Gateway and to your apps. The access token is applied to each request to the remote stores and to [**io.Manager**](https://docs.interop.io/manager/overview/index.md) in the same way as when [signaling the platform](#authentication-signaling_the_platform) via the `authDone()` method.

#### Configuration

To enable OIDC authentication, set the `"authController"` property to `"oidc"` in the `"ssoAuth"` top-level key of the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop** and use the `"options"` property to configure the identity provider:

```json
{
    "ssoAuth": {
        "authController": "oidc",
        "options": {
            "authority": "https://login.microsoftonline.com/<tenant-id>/v2.0",
            "clientId": "<client-id>",
            "scopes": ["openid", "profile", "email", "offline_access"],
            "usernameClaim": "preferred_username",
            "redirect": { "type": "loopback" }
        }
    }
}
```

It's required to provide the OAuth 2.0 client ID, settings for redirecting after authentication, and either `"authority"` (for identity providers that support OIDC discovery), or both `"authorizationEndpoint"` and `"tokenEndpoint"` (for identity providers that don't support it).

The `"options"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"authority"` | `string` | Base issuer URL of the OIDC provider to be used for OIDC discovery at `/.well-known/openid-configuration`. Use this property for identity providers that support OIDC discovery. For providers that don't support OIDC discovery, use `"authorizationEndpoint"` and `"tokenEndpoint"` instead. |
| `"authorizationEndpoint"` | `string` | Explicit authorization endpoint URL. Use this together with `"tokenEndpoint"` if the identity provider doesn't support OIDC discovery. For providers that support OIDC discovery, use `"authority"` instead. |
| `"clientId"` | `string` | **Required.** OAuth 2.0 client identifier registered with the identity provider. |
| `"endSessionEndpoint"` | `string` | Explicit end session endpoint to be used when the io.Connect platform initiates a logout. Use this when the identity provider doesn't advertise an end session endpoint in its discovery settings. If you don't specify an end session endpoint, the discovered one will be used. If neither is available, the io.Connect platform will only drop the local tokens and the identity provider session will be left intact (the user won't be logged out). |
| `"extraAuthParams"` | `object` | Additional provider-specific query parameters to be appended to the authorization request. |
| `"issuer"` | `string` | Issuer identifier of the OIDC provider (the base URL of the identity provider). Required when using explicit authorization and token endpoints for identity providers that don't support OIDC discovery. |
| `"jwksUri"` | `string` | JWKS endpoint of the OIDC provider for verifying the signature of the ID token. Required when using explicit authorization and token endpoints for identity providers that don't support OIDC discovery. |
| `"loginSurface"` | `"system-browser"` \| `"embedded-window"` | Specifies where the identity provider login will be displayed. If set to `"system-browser"` (recommended), the login will be displayed by opening the default system browser. If set to `"embedded-window"`, the login will be opened in an io.Connect Window (discouraged practice, blocked by some identity providers like Google). Defaults to `"system-browser"`. |
| `"logoutOnShutdown"` | `boolean` | If `true`, a logout request for ending the identity provider session will be sent when the io.Connect platform shuts down. The next platform launch will require a new login. Defaults to `false`. |
| `"redirect"` | `object` | **Required.** Redirection endpoint settings to be sent to the identity provider for redirecting after authentication. It's possible to configure a loopback HTTP server or a custom protocol scheme. |
| `"scopes"` | `string[]` | OAuth 2.0 scopes to request from the identity provider during authentication. Defaults to `["openid", "profile", "email"]`. |
| `"timeoutMs"` | `number` | Interval in milliseconds to wait for the authentication process to complete. Defaults to `300000`. |
| `"tokenEndpoint"` | `string` | Explicit token endpoint URL. Use this together with `"authorizationEndpoint"` if the identity provider doesn't support OIDC discovery. For providers that support OIDC discovery, use `"authority"` instead. |
| `"usernameClaim"` | `string` | The name of the claim to be extracted from the ID token and to be used as the identity of the authenticated user. Defaults to `"sub"`. |
| `"window"` | `object` | Settings for the io.Connect Window when using an embedded window to display the login. |

> ℹ️ *For details on the available properties for configuring the authentication mechanism of **io.Connect Desktop**, see the [authentication controller schema](https://docs.interop.io/desktop/assets/configuration/authController.json).*

It's generally recommended to use the `"ssoAuth"` top-level key for configuring OIDC authentication. This authentication mechanism runs after the platform has already established a connection with the io.Connect Gateway.

However, if your deployment scenario requires you to authenticate the user before establishing a connection with the io.Connect Gateway, you can use the `"auth"` top-level key to provide the OIDC authentication settings. In this case, the access token issued by the identity provider will be used as the login for the connection to the io.Connect Gateway and the platform won't start until the authentication process completes.

When using the `"auth"` top-level key, you must also enable the `"oauth2"` [authenticator](#ioconnect_gateway-authentication-authenticators) for the io.Connect Gateway, set it as the default one, and configure it with the settings of your identity provider:

```json
{
    "gw": {
        "configuration": {
            "authentication": {
                "available": ["basic", "oauth2"],
                "default": "oauth2",
                "oauth2": {
                    "issuerBaseURL": "https://<issuer-domain>",
                    "audience": "https://<my-api>"
                }
            }
        }
    }
}
```

Both the `"issuerBaseURL"` and the `"audience"` properties are required and must be provided explicitly - they aren't inherited from the settings of the OIDC authentication controller specified in the `"auth"` top-level key.

The `"issuerBaseURL"` property is the base issuer URL of your identity provider and must have the same value as the `"authority"` property of the OIDC authentication controller. The `"audience"` property is the identifier of the API for which the access token has been issued and is used for validating the `aud` claim.

> ⚠️ *Note that the `"oauth2"` authenticator doesn't accept explicit endpoints, unlike the OIDC authentication controller. The io.Connect Gateway always resolves the JWKS endpoint and the issuer of your identity provider from its metadata document, discovered at `/.well-known/openid-configuration` or at `/.well-known/oauth-authorization-server` relative to `"issuerBaseURL"`. Identity providers that don't publish a metadata document at either location can't be used with the `"auth"` top-level key.*

> ℹ️ *For more details on the available authentication flows, see the [io.Connect Gateway > Authentication](#ioconnect_gateway-authentication) section.*

#### Redirection Endpoint

The `"redirect"` object accepts settings either for a loopback HTTP server, or for a custom protocol scheme.

Use a loopback HTTP server on the local machine as a redirection endpoint. This is the recommended approach, supported by most identity providers:

```json
{
    "ssoAuth": {
        "options": {
            "redirect": {
                "type": "loopback",
                "host": "localhost",
                "port": 9372,
                "path": "/callback"
            }
        }
    }
}
```

The `"redirect"` object for a loopback HTTP server has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"host"` | `"127.0.0.1"` \| `"localhost"` | Loopback host to use in the redirect URI. Defaults to `"127.0.0.1"`. |
| `"path"` | `string` | Path for the loopback redirection URI. Defaults to `"/callback"`. |
| `"port"` | `number` | Fixed loopback port. Use a fixed port for identity providers that require exact URI matching for redirection. Can be omitted for identity providers that don't enforce exact port matching, in which case the OS will assign an available port on startup. |
| `"type"` | `string` | **Required.** Type of the redirection endpoint. Must be set to `"loopback"`. |

> ⚠️ *Note that some identity providers accept only one of the two supported loopback hosts, so make sure that the value of the `"host"` property matches the redirect URI registered with the identity provider.*

> ⚠️ *Note that Microsoft Entra ID, Okta, Google, and Keycloak ignore the loopback port, so you can omit the `"port"` property and let the OS assign an available one on startup - no fixed port has to be reserved. Auth0 requires a fixed port.*

Use a custom protocol scheme for redirection after authentication only when the provider rejects loopback redirection URIs. The io.Connect platform will automatically register the specified scheme with the OS before initiating login:

```json
{
    "ssoAuth": {
        "options": {
            "redirect": {
                "type": "custom-scheme",
                "scheme": "ioconnect",
                "path": "callback"
            }
        }
    }
}
```

The `"redirect"` object for a custom protocol scheme has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"path"` | `string` | Path for the custom protocol scheme. Defaults to `"callback"`. |
| `"scheme"` | `string` | **Required.** Custom protocol scheme to be used as a redirection endpoint. |
| `"type"` | `string` | **Required.** Type of the redirection endpoint. Must be set to `"custom-scheme"`. |

> ⚠️ *Note that on macOS the OS routes only custom protocol schemes declared in the app bundle. Using any other custom protocol scheme other than the ones declared requires repackaging the app. You can also use a loopback redirection endpoint instead.*

#### Login Window

By default, the identity provider login is displayed in the default system browser. To display it in an io.Connect Window instead, set the `"loginSurface"` property to `"embedded-window"` and use the `"window"` property to configure the login window:

```json
{
    "ssoAuth": {
        "options": {
            "loginSurface": "embedded-window",
            "window": {
                "width": 500,
                "height": 730,
                "mode": "flat"
            }
        }
    }
}
```

The `"window"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"height"` | `number` | Height in pixels for the login window. |
| `"mode"` | `"flat"` \| `"tab"` \| `"html"` \| `"frameless"` | io.Connect Window [mode](https://docs.interop.io/desktop/capabilities/windows/window-management/overview/index.md#window_modes) for the embedded login window. Defaults to `"html"`. |
| `"userAgent"` | `string` | String to be used for the `User-Agent` request header. |
| `"width"` | `number` | Width in pixels for the login window. |

> ⚠️ *Note that opening the identity provider login in an embedded window is a discouraged practice and is blocked by some identity providers like Google. When using an embedded window, a loopback redirection endpoint must specify a fixed `"port"`.*

#### Logout

To initiate a logout on demand, [invoke](https://docs.interop.io/desktop/capabilities/data-sharing/interop/javascript/index.md#method_invocation) the already registered by the platform `"T42.GD.Execute"` Interop method and pass the `"logout"` command as an argument. This will end the identity provider session, drop the local tokens, and by default restart **io.Connect Desktop**, so that a new login will be required:

```javascript
const methodName = "T42.GD.Execute";
const args = { command: "logout", args: { restart: true } };

await io.interop.invoke(methodName, args);
```

To end the identity provider session automatically when **io.Connect Desktop** shuts down, set the `"logoutOnShutdown"` property to `true`.
