SSO login for an existing admin whose token lacked the admin role was silently demoting the account, locking admins out of the dashboard. Missing admin role now leaves the flag alone unless RevokeAdminWithoutRole is enabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
128 lines
7.0 KiB
HTML
128 lines
7.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>OIDC Auth</title>
|
|
</head>
|
|
<body>
|
|
<div id="OidcAuthConfigPage" data-role="page" class="page type-interior pluginConfigurationPage" data-require="emby-input,emby-button,emby-checkbox">
|
|
<div data-role="content">
|
|
<div class="content-primary">
|
|
<form id="OidcAuthConfigForm">
|
|
<div class="verticalSection verticalSection-extrabottompadding">
|
|
<div class="sectionTitleContainer flex align-items-center">
|
|
<h2 class="sectionTitle">OIDC Auth</h2>
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="OidIssuer" type="url" label="Issuer URL" />
|
|
<div class="fieldDescription">Base URL of your OIDC provider, e.g. https://auth.example.com. The discovery document is loaded from <issuer>/.well-known/openid-configuration.</div>
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="OidClientId" type="text" label="Client ID" />
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="OidClientSecret" type="password" label="Client Secret" autocomplete="new-password" />
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="OidScopes" type="text" label="Scopes" />
|
|
<div class="fieldDescription">Space separated. Default: openid profile email. Add e.g. "groups" if your provider needs it for the role claim.</div>
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="UsernameClaim" type="text" label="Username claim" />
|
|
<div class="fieldDescription">Claim used as Jellyfin username. Default: preferred_username. Falls back to "sub".</div>
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="RoleClaim" type="text" label="Role claim" />
|
|
<div class="fieldDescription">Claim containing groups/roles. Default: groups.</div>
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="AllowedRoles" type="text" label="Allowed roles" />
|
|
<div class="fieldDescription">Comma separated. Only users with one of these roles may log in. Empty = everyone.</div>
|
|
</div>
|
|
|
|
<div class="inputContainer">
|
|
<input is="emby-input" id="AdminRoles" type="text" label="Admin roles" />
|
|
<div class="fieldDescription">Comma separated. Users with one of these roles become Jellyfin administrators. Empty = never touch admin flag.</div>
|
|
</div>
|
|
|
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
<label class="emby-checkbox-label">
|
|
<input is="emby-checkbox" id="RevokeAdminWithoutRole" type="checkbox" />
|
|
<span>Also revoke admin when the admin role is missing (careful: can demote your existing admin account on SSO login)</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
<label class="emby-checkbox-label">
|
|
<input is="emby-checkbox" id="CreateUsersIfMissing" type="checkbox" />
|
|
<span>Create users on first login</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
<label class="emby-checkbox-label">
|
|
<input is="emby-checkbox" id="SetRandomPasswordOnCreate" type="checkbox" />
|
|
<span>Set random password for auto-created users (recommended — without it, anyone can log in as them with a blank password)</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
<label class="emby-checkbox-label">
|
|
<input is="emby-checkbox" id="DisableEndpointValidation" type="checkbox" />
|
|
<span>Disable strict endpoint validation (needed for Google and other providers whose endpoints are on a different host than the issuer)</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div>
|
|
<button is="emby-button" type="submit" class="raised button-submit block emby-button">
|
|
<span>Save</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="fieldDescription" style="margin-top: 1em;">
|
|
Login URL: <code><your jellyfin address>/OidcAuth/login</code> —
|
|
register <code><your jellyfin address>/OidcAuth/callback</code> as redirect URI at your provider.
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<script type="text/javascript">
|
|
(function () {
|
|
var pluginId = '96badb44-9940-4ff0-befc-5f987159152c';
|
|
var textFields = ['OidIssuer', 'OidClientId', 'OidClientSecret', 'OidScopes', 'UsernameClaim', 'RoleClaim', 'AllowedRoles', 'AdminRoles'];
|
|
var boolFields = ['RevokeAdminWithoutRole', 'CreateUsersIfMissing', 'SetRandomPasswordOnCreate', 'DisableEndpointValidation'];
|
|
|
|
document.querySelector('#OidcAuthConfigPage').addEventListener('pageshow', function () {
|
|
Dashboard.showLoadingMsg();
|
|
ApiClient.getPluginConfiguration(pluginId).then(function (config) {
|
|
textFields.forEach(function (f) { document.querySelector('#' + f).value = config[f] || ''; });
|
|
boolFields.forEach(function (f) { document.querySelector('#' + f).checked = !!config[f]; });
|
|
Dashboard.hideLoadingMsg();
|
|
});
|
|
});
|
|
|
|
document.querySelector('#OidcAuthConfigForm').addEventListener('submit', function (e) {
|
|
e.preventDefault();
|
|
Dashboard.showLoadingMsg();
|
|
ApiClient.getPluginConfiguration(pluginId).then(function (config) {
|
|
textFields.forEach(function (f) { config[f] = document.querySelector('#' + f).value; });
|
|
boolFields.forEach(function (f) { config[f] = document.querySelector('#' + f).checked; });
|
|
ApiClient.updatePluginConfiguration(pluginId, config).then(function (result) {
|
|
Dashboard.processPluginConfigurationUpdateResult(result);
|
|
});
|
|
});
|
|
return false;
|
|
});
|
|
})();
|
|
</script>
|
|
</div>
|
|
</body>
|
|
</html>
|