Linkwarden OIDC Integration

This document explains how to implement Monosign with Linkwarden, the open-source, self-hosted collaborative bookmark manager that also archives the saved pages. It covers Single Sign-On with OpenID Connect (OIDC), which is built into Linkwarden. Linkwarden reads the Monosign addresses from the OIDC discovery document, uses the Authorization Code flow with PKCE and takes the user from the ID token, so the OIDC/OpenID access key of Monosign is used. Before you continue, it is better to read the Linkwarden documentation.

This configuration is done with Linkwarden 2.16.3 running on Docker (image ghcr.io/linkwarden/linkwarden:v2.16.3 with PostgreSQL and Meilisearch). If your Linkwarden version or deployment type is different, please check the Linkwarden documentation.

Linkwarden supports OpenID Connect through a generic OIDC provider and through ready-made providers (for example Authentik, Keycloak, Azure AD, Okta, Zitadel, Authelia). SAML is not available. There is no single sign-on screen in the Linkwarden interface; the provider is configured with environment variables.

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

Linkwarden is free and open source (AGPL-3.0). Single sign-on is not limited by a license, so it works in the self-hosted version without a key.

📑 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 Linkwarden application

  4. Configuration Single Sign-On for Linkwarden

  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)

Linkwarden 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-184044.png
New Application - Application tab (1: Name, 2: Logo (optional), 3: Next)

Property

Value

Description

Name

Linkwarden

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

Type

Web

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

Url

Optional

Leave empty or enter the Linkwarden address (for example https://<linkwarden-address>). The sign-in is started from the Linkwarden login page with the Monosign button (see step 5).

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). Linkwarden needs the e-mail address and the name of the user.

Linkwarden creates an account for every Monosign user who signs in for the first time (unless DISABLE_NEW_SSO_USERS=true is set). 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 Linkwarden 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 Linkwarden application are provided as follows:

image-20261021-094058.png

Monosign value

Example

Used in Linkwarden as

Client Id

<client-id>

OIDC_CLIENT_ID

Client Secret

<client-secret>

OIDC_CLIENT_SECRET

Configuration Url

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

OIDC_WELLKNOWN_URL. Linkwarden reads the Auth, Token, UserInfo and JWKS addresses from this document.

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 Linkwarden requests and add the callback address of Linkwarden to Allowed Redirect URIs, then press Update.

image-20261018-184641.png
OIDC/OpenID Settings (Scope and Allowed Redirect URIs)

Property

Value

Description

Scope

openid profile email

The scopes that Linkwarden sends in the authorization request (openid email profile is its default). Add each scope separated by space.

Allowed Redirect URIs

https://<linkwarden-address>/api/v1/auth/callback/oidc

The address where Monosign sends the user back after sign-in. The path /api/v1/auth/callback/oidc is fixed by Linkwarden. Use the public (HTTPS) address of Linkwarden.

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.

Linkwarden reads the user from the claims sub, name, email and preferred_username, which Monosign returns by default, so a claim mapping is not required. The preferred_username claim is used as the user name when it exists.

3- Assign a User to the Linkwarden Application

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

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

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

image-20261021-094142.png

Property

Value

Description

User(s)

Selected users

Users who can sign in to Linkwarden with Monosign.

Expiration Date

Default one year

The assignment expires on this date.

4- Configuration Single Sign-On for Linkwarden

As we mentioned at the start, please check out the Linkwarden documentation first. Linkwarden is configured with environment variables. In the Docker Compose deployment add the following variables to the environment file of the Linkwarden container (for example the .env file that is used with env_file) and replace the placeholder values.

Bash
NEXTAUTH_URL=https://<linkwarden-host-name>/api/v1/auth
NEXT_PUBLIC_OIDC_ENABLED=true
OIDC_CUSTOM_NAME=Monosign
OIDC_WELLKNOWN_URL=https://<monosign-host>/.well-known/openid-configuration
OIDC_CLIENT_ID=<client-id>
OIDC_CLIENT_SECRET=<client-secret>

Variable

Value

Description

NEXTAUTH_URL

https://<linkwarden-host-name>/api/v1/auth

Public HTTPS address of Linkwarden including the path /api/v1/auth. The redirect address that is sent to Monosign is built from it, so it must match the Allowed Redirect URI of step 2.

NEXT_PUBLIC_OIDC_ENABLED

true

Turns the generic OIDC provider on. The login page then shows a button for it.

OIDC_CUSTOM_NAME

Monosign

Text on the sign-in button. Default: OIDC.

OIDC_WELLKNOWN_URL

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

Configuration Url of the Monosign access key. Required.

OIDC_CLIENT_ID / OIDC_CLIENT_SECRET

Client Id / Client Secret

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

OIDC_SCOPES

openid email profile (default)

Optional. Scopes that Linkwarden requests, separated by space.

DISABLE_NEW_SSO_USERS

false (default)

Optional. When true, no new account is created through single sign-on. Only users that already exist can sign in.

NEXT_PUBLIC_DISABLE_REGISTRATION

false (default)

Optional. Disables the registration form with e-mail and password.

NEXT_PUBLIC_CREDENTIALS_ENABLED

true (default)

Optional. The local user name and password login stays available next to Monosign. Set it to false to allow the single sign-on only.

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

The first account that is created in Linkwarden (user id 1) is the server administrator. Register this local administrator account on the sign-up page before turning on the single sign-on, so that the first Monosign user does not become the administrator by accident. Without an e-mail server, sign in to this account with its user name.

If a local account with the same e-mail address already exists, Linkwarden links the Monosign sign-in to it only when the identity provider sends the claim email_verified as true. Otherwise the sign-in is refused. New users are not affected.

Linkwarden also needs the basic variables of every installation:

Bash
NEXTAUTH_SECRET=<random-string>
POSTGRES_PASSWORD=<database-password>
MEILI_MASTER_KEY=<random-string>

Generate the random strings for example with openssl rand -base64 32. The Compose file below builds the database address from POSTGRES_PASSWORD, and Linkwarden reaches Meilisearch at http://meilisearch:7700 by default.

For reference, this is the Docker Compose file that was used for this document. All three containers run with all capabilities dropped; only PostgreSQL gets back the few capabilities that it needs to set the owner of its data directory.

YAML
services:
  postgres:
    image: postgres:16-alpine
    env_file: .env
    restart: unless-stopped
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - FOWNER
      - SETUID
      - SETGID
    security_opt:
      - no-new-privileges:true
  linkwarden:
    env_file: .env
    environment:
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
    restart: unless-stopped
    image: ghcr.io/linkwarden/linkwarden:v2.16.3
    ports:
      - "6277:3000"
    volumes:
      - ./data:/data/data
    depends_on:
      - postgres
      - meilisearch
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
  meilisearch:
    image: getmeili/meilisearch:v1.13.3
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./meili_data:/meili_data
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

When Linkwarden is behind a reverse proxy, the proxy must send the header X-Forwarded-Proto: https. After changing the environment file, recreate the container so that the new variables are loaded:

Bash
docker compose up -d --force-recreate linkwarden

5- Sign In Test

Now try to log in to Linkwarden using Monosign SSO.

  1. Open a new browser window (or a private window) and type the Linkwarden address. The login page of Linkwarden shows the user name and password form and, below it, the Monosign button (the text of OIDC_CUSTOM_NAME).

image-20261018-184447.png
Linkwarden login page with the Monosign button
  1. 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.

  2. After the sign-in Monosign redirects the browser back to Linkwarden (/api/v1/auth/callback/oidc). At the first sign-in Linkwarden creates the account with the name and the e-mail address from Monosign and opens the dashboard.

image-20261021-093035.png

Troubleshooting

Symptom

Cause

Solution

The Monosign button is not shown

NEXT_PUBLIC_OIDC_ENABLED is not true, or the container was not recreated after the change.

Set the variable (step 4) and run docker compose up -d --force-recreate linkwarden.

Monosign shows a redirect URI error

The redirect address that Linkwarden sends does not exactly match the Allowed Redirect URIs, for example because NEXTAUTH_URL is wrong or has no /api/v1/auth path, or the address was entered in another field such as Resource.

Add https://<linkwarden-address>/api/v1/auth/callback/oidc to Allowed Redirect URIs in Monosign (step 2) and set NEXTAUTH_URL as in step 4.

An error page appears after returning from Monosign

The Client Id or Client Secret is wrong, or the container cannot reach Monosign.

Copy the values again from the Monosign access key (step 1), check the DNS and firewall rules of the Linkwarden host and read the Linkwarden container log.

The sign-in is refused for an e-mail address that already has a local account

Linkwarden links the accounts only when the identity provider sends email_verified as true.

Sign in with the local account, or use a user with a new e-mail address.

A new user cannot sign in

DISABLE_NEW_SSO_USERS=true is set, or the user is not assigned to the application.

Remove the variable, create the user first, and assign the user in step 3.

SAML sign-in is required

Linkwarden supports OpenID Connect, not SAML.

Use the OIDC integration in this document.

After completing the configuration on Linkwarden 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 Linkwarden address may cause errors.