Element (Synapse) OIDC Integration

This document explains how to implement Monosign with Element, the Matrix client, through the Matrix homeserver Synapse. Element itself has no sign-in settings: it asks the homeserver how users can sign in. Single Sign-On with OpenID Connect (OIDC) is therefore configured on Synapse, and Element Web shows a Continue with Monosign button once Synapse offers it. Synapse reads the Monosign addresses from the OIDC discovery document, uses the Authorization Code flow with PKCE and verifies the ID token, so the OIDC/OpenID access key of Monosign is used. Before you continue, it is better to read the Synapse OpenID Connect documentation.

This configuration is done with Synapse 1.163.0 (image ghcr.io/element-hq/synapse:v1.163.0) and Element Web 1.12.32 (image ghcr.io/element-hq/element-web:v1.12.32) running on Docker, with the built-in SQLite database. SQLite is meant for tests; use PostgreSQL in production. If your versions or deployment type are different, please check the Synapse and Element documentation.

Synapse supports OpenID Connect (and OAuth 2.0 based providers, SAML and CAS). The provider is configured in the file homeserver.yaml of Synapse, there is no single sign-on screen in Element or Synapse.

Monofor has no responsibility to do Element and Synapse configurations. If you need support please contact the Element community or your Element support provider.

Synapse is free and open source (AGPL-3.0) and Element Web is open source (AGPL-3.0 or the Element commercial license). Single sign-on is not limited by a license in the self-hosted version.

The server name of a Matrix homeserver (server_name) becomes a part of every user ID (for example @john:<server-name>) and cannot be changed later. The identifier idp_id of the OIDC provider also cannot be changed later, because users are linked to it. Choose both before the first sign-in.

📑 Instructions

This documentation contains 5 main steps for integration.

  1. Creating an application on Monosign

  2. Configuring the OIDC/OpenID settings on Monosign

  3. Assign a user to the Element application

  4. Configuration Single Sign-On for Synapse and Element Web

  5. Sign In Test

1- Creating an Application on Monosign

Create your application on Monosign first. Open the Applications page from the left menu and click Add New.

image-20261018-103924.png
Applications page in Monosign (1: Applications menu, 2: Add New)

Element is not in the application catalog, so click Create from scratch.

image-20261018-104010.png
Creating a new application from scratch (1: Create from scratch)

Fill in the application details on the Application tab and click Next.

image-20261018-201327.png
New Application - Application tab (1: Name, 2: Logo (optional), 3: Next)

Property

Value

Description

Name

Element

Name of the application shown to users on the Monosign portal and on the Monosign sign-in page.

Type

Web

Element Web is accessed through a web browser. Options: Web, Mobile, Desktop, API.

Url

Optional

Leave empty or enter the address of Element Web (for example https://<element-address>). The sign-in is started from Element with the Continue with Monosign button (see step 5); it cannot be started directly from the Monosign portal.

Logo

Optional

Browse and upload a logo; it is also shown on the Monosign sign-in page.

Users can see this application on their list

Enabled

Displays the application on the user portal.

On the Access tab define who can reach the application and click Create Application.

image-20261018-104203.png
New Application - Access tab (1: Profile Access Type, 2: Create Application)

Property

Value

Description

User Access Type

System Default

Defines which users can access this application. Options: Only Assigned Users, All Users, System Default.

User Group Access Type

System Default

Defines the application’s user group access.

Source Using Type

System Default

Defines which user sources the application can use.

Profile Access Type

All

Defines which user profile attributes are available to the application (Options: Restricted, All). Synapse needs the user name and the name of the user.

Synapse creates a Matrix account for every Monosign user who signs in for the first time (unless enable_registration: false is set for the provider). Make sure the effective User Access Type is Only Assigned Users and give access only to the users you assign in step 3.

After the application is created, click Keys and add a new Access Key for OIDC/OpenID access.

image-20261018-104806.png
Keys tab of the Element application (1: Keys, 2: Add New Access Key)

Select OIDC/OpenID as the key type and click Create. Monosign generates the Client Id and Client Secret automatically.

image-20261018-104856.png
Creating the OIDC/OpenID Access Key (1: Type OIDC/OpenID, 2: Create)

Property

Value

Options

Type

OIDC/OpenID

Rest API, OAuth 2.0, JWT, OIDC/OpenID, SAML, RADIUS, Access Gateway, LDAP, AuthN/Z Server

Client Id / Client Secret

Generated automatically

Use the eye icon next to the secret to reveal it. Both values are required in step 4.

Session

System Default

System Default, On-demand, Permanent

State

Enabled

Enabled, Disabled

Never Expires

Yes

Turn off to define a specific expiration date for the key.

Configuration details for the Element application are provided as follows:

image-20261021-094324.png

Monosign value

Example

Used in Synapse as

Client Id

<client-id>

client_id

Client Secret

<client-secret>

client_secret

Configuration Url

https://<monosign-host>/.well-known/openid-configuration

issuer. Synapse needs the address without the .well-known/openid-configuration part, as the issuer, for example https://<monosign-host>/. Keep the slash at the end, because the issuer of Monosign has it.

2- Configuring the OIDC/OpenID Settings on Monosign

Click the Configure button of the OpenID Connect (OIDC) key to open the OIDC/OpenID settings. Enter the scopes that Synapse requests and add the callback address of Synapse to Allowed Redirect URIs.

image-20261019-074744.png
OIDC/OpenID Settings - Scope and Allowed Redirect URIs

Synapse needs a user name to build the Matrix user ID, but Monosign does not send a preferred_username claim by default. Open the Claim Mapping tab of the OIDC/OpenID Settings, add the claim preferred_username with the value {{UserName}} and press Update.

image-20261019-075620.png
Claim Mapping (1: OIDC/OpenID Settings, 2: Claim Mapping, 3: preferred_username = {{UserName}}, 4: Update)

Property

Value

Description

Scope

openid profile email

The scopes that Synapse sends in the authorization request. They are set with the option scopes in step 4. Add each scope separated by space.

Allowed Redirect URIs

https://<synapse-address>/_synapse/client/oidc/callback

The address where Monosign sends the user back after sign-in. The path /_synapse/client/oidc/callback is fixed by Synapse. Use the public (HTTPS) address of the homeserver (the public_baseurl of Synapse), not the address of Element Web.

Claim Mapping

preferred_username = {{UserName}}

Adds the user name of Monosign to the ID token as preferred_username. Synapse uses it as the Matrix user name (localpart_template in step 4). Press Update after adding it.

Signing Key / Key Id / Password, Issuer, Audience, Resource

Empty

Optional custom JWT settings. They are not needed. Do not enter the callback address in the Resource field.

Token lifetimes, CORS

Empty

Default values are used.

Monosign sends the claims sub, name and email by default, so the display name and the e-mail address of the Matrix account need no mapping. If you do not want to add the claim mapping, you can build the Matrix user name from the e-mail address instead, see localpart_template in step 4.

3- Assign a User to the Element Application

Open the Element application in Monosign, click the Assignments tab and click Assign a User.

image-20261018-105639.png
Assignments tab of the Element application (1: Assignments, 2: Assign a User)

Search and select the users who can sign in to Element, check the Expiration Date and save. You can select more than one user.

image-20261021-094404.png

Property

Value

Description

User(s)

Selected users

Users who can sign in to Element with Monosign.

Expiration Date

Default one year

The assignment expires on this date.

4- Configuration Single Sign-On for Synapse and Element Web

As we mentioned at the start, please check out the Synapse documentation first. Add the OIDC provider to the file homeserver.yaml of Synapse and replace the placeholder values.

YAML
server_name: "<synapse-host-name>"
public_baseurl: "https://<synapse-host-name>/"

oidc_providers:
  - idp_id: monosign
    idp_name: "Monosign"
    issuer: "https://<monosign-host>/"
    client_id: "<client-id>"
    client_secret: "<client-secret>"
    scopes: ["openid", "profile", "email"]
    user_mapping_provider:
      config:
        localpart_template: "{{ user.preferred_username }}"
        display_name_template: "{{ user.name }}"
        email_template: "{{ user.email }}"

Option

Value

Description

server_name

<synapse-host-name>

Name of the Matrix server, part of every user ID. It cannot be changed after the first start.

public_baseurl

https://<synapse-host-name>/

Public HTTPS address of Synapse. The redirect address that is sent to Monosign is built from it, so it must match the Allowed Redirect URI of step 2.

idp_id

monosign

Internal identifier of the provider. It cannot be changed later, because users are linked to it.

idp_name

Monosign

Text on the sign-in button (Continue with Monosign).

issuer

https://<monosign-host>/

Issuer of Monosign. Synapse reads .well-known/openid-configuration below this address and validates the tokens with it. Keep the slash at the end. Required.

client_id / client_secret

Client Id / Client Secret

Copied from the Monosign OIDC/OpenID Access Key Details created in the first step.

scopes

["openid", "profile", "email"]

Scopes that Synapse requests. The default is only openid; add profile and email to get the name and the e-mail address.

localpart_template

{{ user.preferred_username }}

Template for the part of the Matrix user ID before the colon. It needs the claim mapping of step 2. Without the claim mapping use {{ user.email | localpart_from_email }} (the part of the e-mail address before the @). When the template is empty the user is asked to choose a user name, and when the claim is missing Synapse shows the error localpart is invalid.

display_name_template / email_template

{{ user.name }} / {{ user.email }}

Display name and e-mail address that are set at the first sign-in.

client_auth_method

client_secret_basic (default)

Optional. How Synapse authenticates to the token endpoint, client_secret_basic or client_secret_post. Monosign accepts both.

pkce_method

auto (default)

Optional. PKCE is used when Monosign announces it, which it does.

enable_registration

true (default)

Optional, set inside the provider. When false, only users that already have a Matrix account can sign in with Monosign.

allow_existing_users

false (default)

Optional. When true, a Monosign user can sign in to an existing Matrix account with the same user name.

The file homeserver.yaml contains the client secret and the secrets of the homeserver. Restrict its permissions (for example chmod 600) and do not store it in a shared repository.

In the tested deployment the top-level option enable_registration is false (users cannot register with a password, only through Monosign), the federation listener is removed and federation_domain_whitelist is empty, because the server is only for internal use. Adjust these to your needs.

Element Web needs to know the homeserver. Create a config.json for Element Web and mount it in the container:

JSON
{
  "default_server_config": {
    "m.homeserver": {
      "base_url": "https://<synapse-host-name>",
      "server_name": "<synapse-host-name>"
    }
  },
  "disable_custom_urls": true,
  "brand": "Element"
}

This is the Docker Compose file that was tested for this document. The host ports 6277 and 6278 are examples; the reverse proxy forwards the Synapse host name to 6277 and the Element Web host name to 6278. The synapse-data folder must be writable by the user 991 (chown 991:991 synapse-data) and contains homeserver.yaml.

YAML
services:
  synapse:
    image: ghcr.io/element-hq/synapse:v1.163.0
    restart: unless-stopped
    user: "991:991"
    volumes:
      - ./synapse-data:/data
    ports:
      - "6277:8008"
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
  element:
    image: ghcr.io/element-hq/element-web:v1.12.32
    restart: unless-stopped
    volumes:
      - ./element-config.json:/app/config.json:ro
    ports:
      - "6278:80"
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

Synapse and Element Web need two host names, for example <synapse-host-name> for the homeserver and <element-host-name> for Element Web, both with HTTPS. When Synapse is behind a reverse proxy, the proxy must send the headers X-Forwarded-For and X-Forwarded-Proto (and the listener of Synapse must have x_forwarded: true). After changing homeserver.yaml, restart Synapse so that the new settings are loaded:

Bash
docker compose restart synapse

Create a local administrator account before turning on the single sign-on, for example with register_new_matrix_user inside the Synapse container (it needs registration_shared_secret in homeserver.yaml). Accounts that are created through Monosign are normal users, not server administrators.

5- Sign In Test

Now try to log in to Element using Monosign SSO.

image-20261021-093704.png
image-20261019-075413.png
Synapse asks the user to continue to the account after the Monosign sign-in
image-20261019-075220.png
Element account settings: the user name, display name and e-mail address come from Monosign
  1. Open a new browser window (or a private window) and type the address of Element Web. Click Sign in. The sign-in page of Element shows the user name and password form and, below it, the Continue with Monosign button.

  2. Click the button. On the Monosign sign-in page log in passwordless with your QR code (Monofor Identity), with a Passkey or with your user name and password (Sign in with Password). If you are already signed in to Monosign, the page is skipped.

  3. After the sign-in Monosign redirects the browser to Synapse (/_synapse/client/oidc/callback). Synapse shows the page Continue to your account; click Continue.

  4. Synapse creates the Matrix account with the user name, the display name and the e-mail address from Monosign at the first sign-in and Element opens with the new account.

Troubleshooting

Symptom

Cause

Solution

The Continue with Monosign button is not shown

The provider is not in homeserver.yaml, Synapse could not load the discovery document of Monosign and refused the provider at the start, or Element Web points to another homeserver.

Check the section oidc_providers and the Synapse log after the start, and check default_server_config in the config.json of Element Web.

Synapse does not start and the log says that the issuer is not valid

The issuer is different from the issuer that Monosign announces, for example because the slash at the end is missing, or Synapse cannot reach Monosign.

Use the issuer with the slash at the end (step 4) and check the DNS and firewall rules of the Synapse host.

Monosign shows a redirect URI error

The redirect address that Synapse sends does not exactly match the Allowed Redirect URIs, for example because public_baseurl is wrong, or the address was entered in another field such as Resource.

Add https://<synapse-address>/_synapse/client/oidc/callback to Allowed Redirect URIs in Monosign (step 2) and set public_baseurl as in step 4.

An error page appears after returning from Monosign

The Client Id or Client Secret is wrong, or Synapse cannot reach the token endpoint of Monosign.

Copy the values again from the Monosign access key (step 1) and read the Synapse log.

The page Authentication failed shows the error localpart is invalid (mapping_error)

The localpart_template uses user.preferred_username, but Monosign did not send this claim, so the user name is empty.

Add the claim mapping preferred_username = {{UserName}} and press Update (step 2), or use {{ user.email | localpart_from_email }} as localpart_template and restart Synapse.

The user is asked to choose a user name

localpart_template is not set.

Set the template as in step 4.

The user cannot sign in because the user name is already taken

A Matrix account with the same user name exists and allow_existing_users is not true.

Set allow_existing_users: true for the provider, or use another user name.

The sign-in works from the Element address but the callback does not

The callback address was registered with the host name of Element Web instead of the homeserver.

Use the host name of Synapse (public_baseurl) in the Allowed Redirect URI.

SAML sign-in is required

Synapse supports SAML as a separate provider, but this document covers OpenID Connect.

Use the OIDC integration in this document.

After completing the configuration on Synapse and Monosign, it is better to test in a new private browser window if the OIDC SSO doesn’t work, because old session cookies of the Element address may cause errors.