Skip to content

Linked Accounts

iderex edited this page Sep 15, 2026 · 4 revisions

Linked Accounts (admin)

On the 5.0 line (Jellyfin 12), the settings are five tabs. This page describes the build Latest points at, where every setting is on one page. On the 5.0 line the plugin's entry in the plugin list opens Overview, which shows a card per provider, the SSO-only state and what to do next, and carries no setting of its own; the other four tabs are Providers (both provider workspaces, their editors, the login-button fields and the Configuration check), Accounts (the linked-accounts panel and the account-link export and import), Policies (the provisioning-profile editor) and Server (the configuration export and import, the login-page buttons switch and single logout). So the panel this page is about is the Accounts tab.

Linked Accounts is the panel on the plugin's admin configuration page that answers "which Jellyfin accounts can sign in through SSO, and through what", and lets an administrator cut one of them off. It sits above the provider lists, between Config transfer and Login Page Buttons, and it is collapsed until you open it.

Everything it shows is read from this server's stored account links. It contacts no identity provider, and opening it changes nothing.

What a row says

Press Refresh Linked Accounts to load the roster. It is one row per account, not one per link, so an account linked to two providers reads as one account with two links.

Column What it holds
Account The Jellyfin username, or Deleted account (<user id>) when no account with that id exists any more.
SSO links One line per link: provider (protocol) - canonical name - last SSO login: ….
Action Revoke for an account that still exists; a sentence instead of a button for one that does not.

The canonical name is the identity provider's stable subject for that user - the OpenID sub or the SAML NameID - which is what a login actually resolves against. On a link made before subjects were required it is the username the link fell back to.

The protocol is on the line because the two protocols keep separate provider namespaces: an OpenID provider and a SAML provider may both be called keycloak, and the provider name alone would not say which link you are looking at.

An account that holds no SSO link is not listed at all. The panel answers "who is linked", and listing the whole user table would bury that answer. When nothing is linked it says so in a sentence rather than showing an empty table, because a blank panel reads as a failed load.

The last-login stamp is coarse on purpose

last SSO login is the last successful SSO login through that one link, in your browser's local time. Read it as "not later than", and do not build a session timeline on it: the stamp is only rewritten once the stored value has aged past an hour, so that an ordinary repeat login costs no configuration write. A login that happened forty minutes after the stamp leaves the stamp where it is.

never means exactly "no successful SSO login has been recorded through this link since the stamp existed" - a link older than the field, or an account that has not signed in since. It never means a login at an unknown time.

The revoke, and the three things to know before pressing it

Revoke removes that account's links from every configured provider, ends every session it holds on every device, and switches it back to Jellyfin's built-in password provider. It drives the same administrator endpoint as POST /sso/Unregister/<username> (see Security Model) - the panel adds no second revoke path of its own. The confirmation dialog names the consequences before it proceeds.

Three properties of that action are the sort an operator meets at the wrong moment if they have not read them first.

A revoke re-opens native password login for the account it touches. Switching the account back to the built-in password provider is what stops SSO resolving to it - and it is also what makes Jellyfin's own password form work for that account again, even on a server you otherwise run SSO-only. The server-wide SSO-only setting is not changed and no other account is affected; this one account is now a password account. If that is not what you want, disable the account rather than only revoking it.

A revoke is not durable where the provider allows existing-account linking. With AllowExistingAccountLink switched on for a provider, a login whose name matches an existing account adopts it - so the same-named account can be linked again at the next SSO login, and the cut you just made is undone by the user simply signing in. Where a cut has to hold on such a provider, disable or rename the local account as well. Under the fail-closed default, where adoption is off, the revoke is durable on its own.

A row whose account no longer exists carries no Revoke. The revoke resolves the account by its username, and an orphaned link has no account and therefore no username left - so the button would answer "not found" on exactly the rows the panel was opened for. The row carries a sentence saying so instead of a control that always fails.

Such a row is rare now: an account deleted while this plugin is loaded takes its links with it the moment the server reports the deletion, and the audit log carries the fact instead ([SSO Audit] Jellyfin user <id> was deleted; removed its N SSO link(s) from …). A row still appears for an account deleted while the plugin was not loaded, or whose removal could not be written to disk. It is reported deliberately rather than dropped, because such a link is invisible from every other surface, and the user id on the row is what you need to find it; the next SSO login for the same subject treats the link as absent and links the account it creates or adopts instead.

On the 5.0 line (Jellyfin 12), from 5.0.0-JF12-beta.87 onward, Revoke on your own row can be refused. Where your own account has no password anybody can sign in with, holds a link on an enabled provider, and no other enabled administrator holds a link on an enabled provider, the revoke is refused and nothing is changed, because it could leave the server with no administrator able to reach it. Another administrator revoking for you, linking another administrator account to a provider first, or setting a password on an administrator account from the Jellyfin dashboard each ends it. What counts as a way in is on Self-service linking. On the 4.3 line the revoke is not refused.

Waiting for Approval

Directly below the roster sits Waiting for Approval: the accounts this plugin created disabled because their provider has ProvisionNewUsersDisabled on, and that are still waiting. Refresh Linked Accounts re-reads both panels from one roster read, so the two never disagree about a link.

A row appears only while three things hold at once: this plugin's own record says it provisioned the account inert; that record still names the account the link points at, so a link rebound to another account carries no record over; and the account is still disabled. Each row names the identity the link was made under (provider (protocol) - canonical name), the instant the wait began, and an Approve button.

What it does not list, and why: an account an administrator disabled has no record here, whatever its state, and is enabled in the Jellyfin dashboard, never from this panel. The panel offers only what this plugin itself put on hold. An account that has since been enabled by hand leaves the list on the next read.

Approve enables the account and changes nothing else. Its permissions stay as the provisioning set them (the starting policy or profile the provider names), and the next SSO login mints a session. An administrator account is refused with a sentence pointing at the dashboard, so administrator access never comes from here. The action is bound to the link on the row: if the account is gone or no longer waiting when you press it, nothing is enabled and the list is re-read. Every approval is written to the audit log, naming who approved, the provider and the account id.

The panel shows the first hundred rows and says how many were cut (Showing the first 100 of N accounts waiting for approval), so a broad identity-provider audience cannot turn the page into an unbounded list; approve or revoke some to see the rest.

Privileges

All three routes behind these panels - the roster read, the revoke and the approve - require administrator privileges, so the panels are empty and their actions refused for anyone else. The revoke is additionally rate-limited, in its own unregister budget, so it neither starves nor is starved by the login flows, and the approve shares the budget of the link routes; a burst of either can be throttled and retried.

Every value on a row is rendered as literal text. A canonical name is whatever the identity provider put in its subject claim and a username is user-influenced, so nothing on this panel is ever interpreted as markup.

See also

  • Security Model - what the revoke does at the endpoint, and how account links are bound to their issuer.
  • Hardening & Options Reference - the rest of the admin surface on this page: configuration check, test connection, and configuration export / import.
  • Login Flow - how a link is created in the first place, including self-service linking.

Clone this wiki locally