> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# OIDC Authentication

<Info>
  This feature is developed by [yu-i-i/overleaf-cep](https://github.com/yu-i-i/overleaf-cep). Here we offers some documents for your configuration.
</Info>

### Configuration

Internally, Overleaf OIDC module uses the [passport-openidconnect](https://github.com/jaredhanson/passport-openidconnect) library. If you are having issues configuring OpenID Connect, it is worth reading the README for `passport-openidconnect` to get a feel for the configuration it expects.

The environment variable `EXTERNAL_AUTH` is required to enable the OIDC authentication module. This environment variable specifies which external authentication methods are activated. The value of this variable is a list. If the list includes `oidc` then OIDC authentication will be activated.

For example: `EXTERNAL_AUTH=ldap oidc`

When using the OIDC authentication method, a user is redirected to the Identity Provider (IdP) authentication site. If the IdP successfully authenticates the user, the Overleaf users database is checked for a record containing a `thirdPartyIdentifiers` field structured as follows:

```text theme={null}
thirdPartyIdentifiers: [
  {
    externalUserId: "...",
    externalData: null,
    providerId: "..."
  }
]
```

The `externalUserId` must match the user ID in the profile returned by the IdP server (see the `OVERLEAF_OIDC_USER_ID_FIELD` environment variable), and `providerId` must match the ID of the OIDC provider (see the `OVERLEAF_OIDC_PROVIDER_ID`).

If no matching record is found, the database is searched for a user with the primary email address matching the email in the IdP user profile:

* If such a user is found, the `thirdPartyIdentifiers` field is updated.
* If no matching user is found and JIT account creation is not disabled, a new user is created with the email address and `thirdPartyIdentifiers` from the IdP profile.

In both cases, the user is said to be 'linked' to the external OIDC user. The user can be unlinked from the OIDC provider on the `/user/settings` page.

#### Finding the values with the discovery document

Every OpenID Provider (OP) publishes a discovery document at `<issuer>/.well-known/openid-configuration`. Copy the values from it instead of typing them by hand; one wrong character is enough to break the login.

<Steps>
  <Step title="Find the discovery URL">
    Your OP shows it on the page of the client (provider) you created for Overleaf. In Authentik, open **Applications > Providers**, select the provider and look for **OpenID Configuration URL** and **OpenID Configuration Issuer**:

    <Frame caption="Authentik: the discovery URL and the issuer of a provider (test instance)">
      <img src="https://mintcdn.com/ayakaleaf-pro/TjqwH4XzxYAkHStq/images/on-premises/oidc-authentik-provider.png?fit=max&auto=format&n=TjqwH4XzxYAkHStq&q=85&s=e3cb5603d959665472b53e39b58b2775" alt="" width="1280" height="633" data-path="images/on-premises/oidc-authentik-provider.png" />
    </Frame>

    The URL usually looks like this:

    * Keycloak: `https://keycloak.example.com/realms/<realm>/.well-known/openid-configuration`
    * Authentik: `https://authentik.example.com/application/o/<application-slug>/.well-known/openid-configuration`
  </Step>

  <Step title="Read the values">
    Open the URL in a browser, or run on the Overleaf server:

    ```shell theme={null}
    curl -s https://authentik.example.com/application/o/overleaf/.well-known/openid-configuration \
      | jq '{issuer, authorization_endpoint, token_endpoint, userinfo_endpoint, end_session_endpoint}'
    ```

    The answer of Authentik looks like this:

    ```json theme={null}
    {
      "issuer": "https://authentik.example.com/application/o/overleaf/",
      "authorization_endpoint": "https://authentik.example.com/application/o/authorize/",
      "token_endpoint": "https://authentik.example.com/application/o/token/",
      "userinfo_endpoint": "https://authentik.example.com/application/o/userinfo/",
      "end_session_endpoint": "https://authentik.example.com/application/o/overleaf/end-session/"
    }
    ```

    Authentik also lists these URLs further down on the provider page:

    <Frame caption="Authentik: the endpoints of a provider (test instance)">
      <img src="https://mintcdn.com/ayakaleaf-pro/TjqwH4XzxYAkHStq/images/on-premises/oidc-authentik-endpoints.png?fit=max&auto=format&n=TjqwH4XzxYAkHStq&q=85&s=55d130cbbbf27fd11aebafa1ab3f090c" alt="" width="1280" height="633" data-path="images/on-premises/oidc-authentik-endpoints.png" />
    </Frame>
  </Step>

  <Step title="Copy them into `variables.env`">
    | Field in the discovery document | Environment variable |
    | - | - |
    | `issuer` | `OVERLEAF_OIDC_ISSUER` |
    | `authorization_endpoint` | `OVERLEAF_OIDC_AUTHORIZATION_URL` |
    | `token_endpoint` | `OVERLEAF_OIDC_TOKEN_URL` |
    | `userinfo_endpoint` | `OVERLEAF_OIDC_USER_INFO_URL` |
    | `end_session_endpoint` | `OVERLEAF_OIDC_LOGOUT_URL` |

    ```dotenv theme={null}
    OVERLEAF_OIDC_ISSUER=https://authentik.example.com/application/o/overleaf/
    OVERLEAF_OIDC_AUTHORIZATION_URL=https://authentik.example.com/application/o/authorize/
    OVERLEAF_OIDC_TOKEN_URL=https://authentik.example.com/application/o/token/
    OVERLEAF_OIDC_USER_INFO_URL=https://authentik.example.com/application/o/userinfo/
    OVERLEAF_OIDC_LOGOUT_URL=https://authentik.example.com/application/o/overleaf/end-session/
    ```
  </Step>

  <Step title="Check that Overleaf can reach the OP">
    Overleaf calls the token and userinfo endpoints from inside its container, so the OP must be reachable from there, not only from your browser:

    ```shell theme={null}
    docker exec sharelatex curl -sS -o /dev/null -w "%{http_code}\n" \
      https://authentik.example.com/application/o/overleaf/.well-known/openid-configuration
    ```

    It should print `200`.
  </Step>
</Steps>

<Warning>
  Copy `issuer` exactly, including the trailing slash. Overleaf compares it character by character with the issuer in the ID token; any difference makes every OIDC login fail with:

  `{"message":{"message":"ID token not issued by expected OpenID provider."}}`

  In Authentik the issuer belongs to the application (`.../application/o/<application-slug>/`). It is not the address of the Authentik server, although the authorize, token and userinfo URLs are shared by all applications.
</Warning>

#### Environment Variables

The values of the following five required variables can be found using `.well-known/openid-configuration` endpoint of your OpenID Provider (OP), see above.

* `OVERLEAF_OIDC_ISSUER` <strong>(required)</strong>
* `OVERLEAF_OIDC_AUTHORIZATION_URL` <strong>(required)</strong>
* `OVERLEAF_OIDC_TOKEN_URL` <strong>(required)</strong>
* `OVERLEAF_OIDC_USER_INFO_URL` <strong>(required)</strong>
* `OVERLEAF_OIDC_LOGOUT_URL` <strong>(required)</strong>

The values of the following two required variables will be provided by the admin of your OP

* `OVERLEAF_OIDC_CLIENT_ID` <strong>(required)</strong>
* `OVERLEAF_OIDC_CLIENT_SECRET` <strong>(required)</strong>
* `OVERLEAF_OIDC_SCOPE`
  * Default: `openid profile email`
* `OVERLEAF_OIDC_PROVIDER_ID`
  * Arbitrary ID of the OP, defaults to `oidc`.
* `OVERLEAF_OIDC_PROVIDER_NAME`
  * The name of the OP, used in the `Linked Accounts` section of the `/user/settings` page, defaults to `OIDC Provider`.
* `OVERLEAF_OIDC_IDENTITY_SERVICE_NAME`
  * Display name for the identity service, used on the login page (default: `Log in with $OVERLEAF_OIDC_PROVIDER_NAME`).
* `OVERLEAF_OIDC_PROVIDER_DESCRIPTION`
  * Description of OP, used in the `Linked Accounts` section (default: `Log in with $OVERLEAF_OIDC_PROVIDER_NAME`).
* `OVERLEAF_OIDC_PROVIDER_INFO_LINK`
  * `Learn more` URL in the OP description, default: no `Learn more` link in the description.
* `OVERLEAF_OIDC_PROVIDER_HIDE_NOT_LINKED`
  * Do not show OP on the `/user/settings` page, if the user's account is not linked with the OP, default `false`.
* `OVERLEAF_OIDC_USER_ID_FIELD`
  * The value of this attribute will be used by Overleaf as the external user ID, defaults to `id`. Other possible reasonable values are `email` and `username` (corresponding to `preferred_username` OIDC claim).
* `OVERLEAF_OIDC_ALLOWED_EMAIL_DOMAINS`
  * Restricts Just-in-Time (JIT) account creation for users authenticating via OIDC. If set to a comma-separated list of domain names, a new account will be created only if the domain of the user's email address matches one in the listed domains. If the domain does not match, an admin must manually create the user account using the OIDC user’s email address, with either a strong random password or, preferably, without the `hashedPassword` field at all. Domain names may include a leading `*.` wildcard to match subdomains.
    * Example: To allow JIT account creation for users with email address like `name@example.com` and `name@math.example.com`:\
      `OVERLEAF_OIDC_ALLOWED_EMAIL_DOMAINS=example.com, *.example.com`
    * Example: To completely disable JIT account creation:\
      `OVERLEAF_OIDC_ALLOWED_EMAIL_DOMAINS=`
* `OVERLEAF_OIDC_UPDATE_USER_DETAILS_ON_LOGIN`
  * If set to `true`, updates the user `first_name` and `last_name` field on login, and disables the user details form on `/user/settings` page.
* `OVERLEAF_OIDC_IS_ADMIN_FIELD` and `OVERLEAF_OIDC_IS_ADMIN_FIELD_VALUE`
  * When both environment variables are set, the login process updates `user.isAdmin = true` if the profile returned by the OP contains the attribute specified by `OVERLEAF_OIDC_IS_ADMIN_FIELD` and its value either matches `OVERLEAF_OIDC_IS_ADMIN_FIELD_VALUE` or is an array containing `OVERLEAF_OIDC_IS_ADMIN_FIELD_VALUE` (for example the `groups` claim), otherwise `user.isAdmin` is set to `false`. If `OVERLEAF_OIDC_IS_ADMIN_FIELD` is `email` then the value of the attribute `emails[0].value` is used for match checking.

The redirect URL for your OpenID Provider is `https://my-overleaf-instance.com/oidc/login/callback`.

<Accordion title="Sample variables.env file">
  ```dotenv title="variables.env" wrap theme={null}
  OVERLEAF_APP_NAME="Our Overleaf Instance"

  ENABLED_LINKED_FILE_TYPES=project_file,project_output_file,url

  # Enables Thumbnail generation using ImageMagick
  ENABLE_CONVERSIONS=true

  # Disables email confirmation requirement
  EMAIL_CONFIRMATION_DISABLED=true

  ## Nginx
  # NGINX_WORKER_PROCESSES=4
  # NGINX_WORKER_CONNECTIONS=768

  ## Set for TLS via nginx-proxy
  # OVERLEAF_BEHIND_PROXY=true
  # OVERLEAF_SECURE_COOKIE=true

  OVERLEAF_SITE_URL=http://my-overleaf-instance.com
  OVERLEAF_NAV_TITLE=Our Overleaf Instance
  # OVERLEAF_HEADER_IMAGE_URL=http://somewhere.com/mylogo.png
  OVERLEAF_ADMIN_EMAIL=support@example.com

  OVERLEAF_LEFT_FOOTER=[{"text": "Contact your support team", "url": "mailto:support@example.com"}]
  OVERLEAF_RIGHT_FOOTER=[{"text":"Hello, I am on the Right", "url":"https://github.com/yu-i-i/overleaf-cep"}]

  OVERLEAF_EMAIL_FROM_ADDRESS=team@example.com
  OVERLEAF_EMAIL_SMTP_HOST=smtp.example.com
  OVERLEAF_EMAIL_SMTP_PORT=587
  OVERLEAF_EMAIL_SMTP_SECURE=false
  # OVERLEAF_EMAIL_SMTP_USER=
  # OVERLEAF_EMAIL_SMTP_PASS=
  # OVERLEAF_EMAIL_SMTP_NAME=
  OVERLEAF_EMAIL_SMTP_LOGGER=false
  OVERLEAF_EMAIL_SMTP_TLS_REJECT_UNAUTH=true
  OVERLEAF_EMAIL_SMTP_IGNORE_TLS=false
  OVERLEAF_CUSTOM_EMAIL_FOOTER=This system is run by department x

  OVERLEAF_PROXY_LEARN=true
  NAV_HIDE_POWERED_BY=true

  #################
  ## OIDC for CE ##
  #################

  EXTERNAL_AUTH=oidc

  OVERLEAF_OIDC_PROVIDER_ID=oidc
  OVERLEAF_OIDC_ISSUER=https://keycloak.provider.com/realms/example
  OVERLEAF_OIDC_AUTHORIZATION_URL=https://keycloak.provider.com/realms/example/protocol/openid-connect/auth
  OVERLEAF_OIDC_TOKEN_URL=https://keycloak.provider.com/realms/example/protocol/openid-connect/token
  OVERLEAF_OIDC_USER_INFO_URL=https://keycloak.provider.com/realms/example/protocol/openid-connect/userinfo
  OVERLEAF_OIDC_LOGOUT_URL=https://keycloak.provider.com/realms/example/protocol/openid-connect/logout
  OVERLEAF_OIDC_CLIENT_ID=Overleaf-OIDC
  OVERLEAF_OIDC_CLIENT_SECRET=DoNotUseThisATGgaAcTgCcATgGATTACAagGtTCaGcGTAG
  OVERLEAF_OIDC_IDENTITY_SERVICE_NAME='Log in with Keycloak OIDC Provider'
  OVERLEAF_OIDC_PROVIDER_NAME=OIDC Keycloak Provider
  OVERLEAF_OIDC_PROVIDER_INFO_LINK=https://openid.net
  OVERLEAF_OIDC_IS_ADMIN_FIELD=email
  OVERLEAF_OIDC_IS_ADMIN_FIELD_VALUE=overleaf.admin@example.com
  OVERLEAF_OIDC_UPDATE_USER_DETAILS_ON_LOGIN=false
  ```
</Accordion>

## Step-by-step: goauthentik

This walks through a setup that is tested against [goauthentik](https://goauthentik.io/). Replace `https://overleaf.example.com` with your `OVERLEAF_SITE_URL` and `https://authentik.example.com` with the address of your Authentik.

<Steps>
  <Step title="Create the provider">
    In Authentik, open **Applications > Providers**, click **New Provider**, choose **OAuth2/OpenID Provider** and click **Next**.

    * **Client Type**: `Confidential`.
    * **Redirect URIs** (under **Protocol settings**): add `https://overleaf.example.com/oidc/login/callback` with the matching mode `Strict`.
    * Copy **Client ID** and **Client Secret** now, into `OVERLEAF_OIDC_CLIENT_ID` and `OVERLEAF_OIDC_CLIENT_SECRET`.

    <Frame caption="Authentik: Client ID and Client Secret of a new provider">
      <img src="https://mintcdn.com/ayakaleaf-pro/TjqwH4XzxYAkHStq/images/on-premises/oidc-authentik-create.png?fit=max&auto=format&n=TjqwH4XzxYAkHStq&q=85&s=f127a92eaf3063714e9af515fe97c263" alt="" width="1120" height="808" data-path="images/on-premises/oidc-authentik-create.png" />
    </Frame>

    <Warning>
      Authentik shows the client secret only while you create the provider. Later the edit form only offers **Modify**, which replaces the secret with a new one.
    </Warning>
  </Step>

  <Step title="Create the application">
    Open **Applications > Applications**, create a new application, give it a name and a slug, for example `overleaf`, and select the provider. The slug becomes part of the issuer: `https://authentik.example.com/application/o/overleaf/`.
  </Step>

  <Step title="Copy the URLs">
    Follow [Finding the values with the discovery document](#finding-the-values-with-the-discovery-document) above to fill in the five URLs.
  </Step>

  <Step title="Map the admins (optional)">
    Authentik sends the user's groups as the `groups` claim, an array. To make the members of the Authentik group `Admins` admins of Overleaf:

    ```dotenv theme={null}
    OVERLEAF_OIDC_IS_ADMIN_FIELD=groups
    OVERLEAF_OIDC_IS_ADMIN_FIELD_VALUE=Admins
    ```

    <Warning>
      The admin flag is updated on every OIDC login. With a wrong field or value, every admin who logs in through OIDC loses the admin rights, including the admin created in the launchpad. Test the mapping with a second admin account first.
    </Warning>
  </Step>
</Steps>

<Accordion title="Tested variables.env for goauthentik">
  ```dotenv title="variables.env" wrap theme={null}
  EXTERNAL_AUTH=oidc
  OVERLEAF_OIDC_PROVIDER_ID=authentik
  OVERLEAF_OIDC_IDENTITY_SERVICE_NAME=Log in with Authentik
  OVERLEAF_OIDC_ISSUER=https://authentik.example.com/application/o/overleaf/
  OVERLEAF_OIDC_AUTHORIZATION_URL=https://authentik.example.com/application/o/authorize/
  OVERLEAF_OIDC_TOKEN_URL=https://authentik.example.com/application/o/token/
  OVERLEAF_OIDC_USER_INFO_URL=https://authentik.example.com/application/o/userinfo/
  OVERLEAF_OIDC_LOGOUT_URL=https://authentik.example.com/application/o/overleaf/end-session/
  OVERLEAF_OIDC_CLIENT_ID=<Client ID>
  OVERLEAF_OIDC_CLIENT_SECRET=<Client Secret>
  OVERLEAF_OIDC_USER_ID_FIELD=username
  OVERLEAF_OIDC_IS_ADMIN_FIELD=groups
  OVERLEAF_OIDC_IS_ADMIN_FIELD_VALUE=Admins
  OVERLEAF_OIDC_UPDATE_USER_DETAILS_ON_LOGIN=true
  ```
</Accordion>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.