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.
-
Creating an application on Monosign
-
Configuring the OIDC/OpenID settings on Monosign
-
Assign a user to the Element application
-
Configuration Single Sign-On for Synapse and Element Web
-
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.
Element is not in the application catalog, so click Create from scratch.
Fill in the application details on the Application tab and click Next.
|
Property |
Value |
Description |
|---|---|---|
|
Name |
|
Name of the application shown to users on the Monosign portal and on the Monosign sign-in page. |
|
Type |
|
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 |
|
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 |
|
Displays the application on the user portal. |
On the Access tab define who can reach the application and click Create Application.
|
Property |
Value |
Description |
|---|---|---|
|
User Access Type |
|
Defines which users can access this application. Options: Only Assigned Users, All Users, System Default. |
|
User Group Access Type |
|
Defines the application’s user group access. |
|
Source Using Type |
|
Defines which user sources the application can use. |
|
Profile Access Type |
|
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.
Select OIDC/OpenID as the key type and click Create. Monosign generates the Client Id and Client Secret automatically.
|
Property |
Value |
Options |
|---|---|---|
|
Type |
|
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, On-demand, Permanent |
|
State |
|
Enabled, Disabled |
|
Never Expires |
|
Turn off to define a specific expiration date for the key. |
Configuration details for the Element application are provided as follows:
|
Monosign value |
Example |
Used in Synapse as |
|---|---|---|
|
Client Id |
|
|
|
Client Secret |
|
|
|
Configuration Url |
|
|
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.
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.
|
Property |
Value |
Description |
|---|---|---|
|
Scope |
|
The scopes that Synapse sends in the authorization request. They are set with the option |
|
Allowed Redirect URIs |
|
The address where Monosign sends the user back after sign-in. The path |
|
Claim Mapping |
|
Adds the user name of Monosign to the ID token as |
|
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.
Search and select the users who can sign in to Element, check the Expiration Date and save. You can select more than one user.
|
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.
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 |
|
Name of the Matrix server, part of every user ID. It cannot be changed after the first start. |
|
public_baseurl |
|
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 |
|
Internal identifier of the provider. It cannot be changed later, because users are linked to it. |
|
idp_name |
|
Text on the sign-in button (Continue with Monosign). |
|
issuer |
|
Issuer of Monosign. Synapse reads |
|
client_id / client_secret |
Client Id / Client Secret |
Copied from the Monosign OIDC/OpenID Access Key Details created in the first step. |
|
scopes |
|
Scopes that Synapse requests. The default is only |
|
localpart_template |
|
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 |
|
display_name_template / email_template |
|
Display name and e-mail address that are set at the first sign-in. |
|
client_auth_method |
|
Optional. How Synapse authenticates to the token endpoint, |
|
pkce_method |
|
Optional. PKCE is used when Monosign announces it, which it does. |
|
enable_registration |
|
Optional, set inside the provider. When |
|
allow_existing_users |
|
Optional. When |
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:
{
"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.
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:
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.
-
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.
-
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.
-
After the sign-in Monosign redirects the browser to Synapse (
/_synapse/client/oidc/callback). Synapse shows the page Continue to your account; click Continue. -
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 |
Check the section |
|
Synapse does not start and the log says that the issuer is not valid |
The |
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 |
Add |
|
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 |
Add the claim mapping |
|
The user is asked to choose a user name |
|
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 |
Set |
|
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 ( |
|
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.