Compare commits

..

12 Commits

Author SHA1 Message Date
Ersei Saggi 87edc5f90a Prepare for 3.5.2.2 2024-01-22 16:38:06 -05:00
Ersei Saggi 304170e214 Update flake.lock 2024-01-11 09:57:16 -05:00
Ersei Saggi 9321c25f20 feat: allow linking to work with new paths 2024-01-11 09:56:45 -05:00
Ersei Saggi ebf7eef83e docs: mention quick connect in README 2023-12-09 16:15:43 -05:00
Ersei Saggi 065ea8b5cd docs: mention to have both paths in redirects 2023-11-24 17:59:46 -05:00
Ersei Saggi 0476f817a6 v.3.5.2.1 2023-10-18 01:11:26 -04:00
Ersei Saggi 3bb241b6d2 Clarify docs 2023-10-18 01:11:10 -04:00
Ersei Saggi cb26ba9852 Add yet another null check in SAML 2023-10-18 01:09:33 -04:00
Ersei Saggi 1b6761bf73 fix: add another null check in SAML for the default provider 2023-09-01 15:59:13 -04:00
Ersei Saggi eeabc3cc46 Merge branch 'main' of github.com:9p4/jellyfin-plugin-sso 2023-08-29 13:06:15 -04:00
Ersei Saggi e65c5add95 fix: a few more null checks 2023-08-29 13:06:02 -04:00
Nathan Easton fce636bddd Added a section in the authentik provider (#137)
Add note about error processing request from issue #136
2023-08-22 13:29:50 -04:00
6 changed files with 53 additions and 16 deletions
+5 -3
View File
@@ -34,7 +34,7 @@ This is 100% alpha software! PRs are welcome to improve the code.
~~There is NO admin configuration! You must use the API to configure the program!~~ Added by [strazto](https://github.com/strazto) in PR [#18](https://github.com/9p4/jellyfin-plugin-sso/pull/18) and [#27](https://github.com/9p4/jellyfin-plugin-sso/pull/27).
**[This is for Jellyfin 10.8](https://github.com/9p4/jellyfin-plugin-sso/issues/3) and only on the Web UI!**
**[This is for Jellyfin 10.8](https://github.com/9p4/jellyfin-plugin-sso/issues/3) and only on the Web UI and clients supporting [Quick Connect](https://jellyfin.org/docs/general/server/quick-connect)**
**This README reflects the branch it is currently on! Switch tags to view version-specific documentation!**
@@ -91,6 +91,8 @@ The nightly build may have new features unavailable in other builds, but **be wa
## Examples
**Note that you should add both "/r/" and "/redirect/" paths to your SSO provider's configuration!**
### Creating A Login Button On The Main Page
In the Jellyfin administration UI, under "General", there is a "Branding" section. In that section, add the following code in the "Login disclaimer" block (replacing `PROVIDER_NAME` and the domain):
@@ -180,7 +182,7 @@ These all require authorization. Append an API key to the end of the request: `c
- `samlClientId`: string. The SAML client ID.
- `samlCertificate`: string. The base64 encoded SAML certificate.
- `enabled`: boolean. Determines if the provider is enabled or not.
- `enableAuthorization`: boolean: Determines if the plugin sets permissions for the user. If false, the user will start with no permissions and an administrator will add permissions. The permissions of existing users will not be rewritten on subsequent logins.
- `enableAuthorization`: boolean: Determines if the plugin sets permissions for the user. If false, the user will start with no permissions and an administrator will add permissions. If disabled, then the permissions of users will not be modified and the Jellyfin defaults will be used instead.
- `enableAllFolders`: boolean. Determines if the client logging in is allowed access to all folders.
- `enabledFolders`: array of strings. If `enableAllFolders` is set to false, then this will be used to determine what folders the users who log in through this provider are allowed to use.
- `roles`: array of strings. This validates the SAML response against the `Role` attribute. If a user has any of these roles, then the user is authenticated. Leave blank to disable role checking.
@@ -219,7 +221,7 @@ These all require authorization. Append an API key to the end of the request: `c
- `oidClientId`: string. The OpenID client ID.
- `oidSecret`: string. The OpenID secret.
- `enabled`: boolean. Determines if the provider is enabled or not.
- `enableAuthorization`: boolean: Determines if the plugin sets permissions for the user. If false, the user will start with no permissions and an administrator will add permissions. The permissions of existing users will not be rewritten on subsequent logins.
- `enableAuthorization`: boolean: Determines if the plugin sets permissions for the user. If false, the user will start with no permissions and an administrator will add permissions. If disabled, then the permissions of users will not be modified and the Jellyfin defaults will be used instead.
- `enableAllFolders`: boolean. Determines if the client logging in is allowed access to all folders.
- `enabledFolders`: array of strings. If `enableAllFolders` is set to false, then this will be used to determine what folders the users who log in through this provider are allowed to use.
- `roles`: array of strings. This validates the OpenID response against the claim set in `roleClaim`. If a user has any of these roles, then the user is authenticated. Leave blank to disable role checking. This currently only works for Keycloak (to my knowledge).
+30 -9
View File
@@ -82,13 +82,14 @@ public class SSOController : ControllerBase
if (config.Enabled)
{
var scopes = config.OidScopes == null ? new string[2] : config.OidScopes;
var options = new OidcClientOptions
{
Authority = config.OidEndpoint?.Trim(),
ClientId = config.OidClientId?.Trim(),
ClientSecret = config.OidSecret?.Trim(),
RedirectUri = GetRequestBase(config.SchemeOverride) + $"/sso/OID/{(Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase) ? "redirect" : "r")}/" + provider,
Scope = string.Join(" ", config.OidScopes.Prepend("openid profile")),
Scope = string.Join(" ", scopes.Prepend("openid profile")),
};
options.Policy.Discovery.ValidateEndpoints = !config.DoNotValidateEndpoints; // For Google and other providers with different endpoints
options.Policy.Discovery.RequireHttps = !config.DisableHttps;
@@ -101,7 +102,7 @@ public class SSOController : ControllerBase
return ReturnError(StatusCodes.Status400BadRequest, result.Error + " Try logging in again.");
}
if (!config.EnableFolderRoles)
if (!config.EnableFolderRoles && config.EnabledFolders != null)
{
StateManager[state].Folders = new List<string>(config.EnabledFolders);
}
@@ -287,12 +288,21 @@ public class SSOController : ControllerBase
if (config.Enabled)
{
bool newPath = config.NewPath;
if (!isLinking)
{
newPath = Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase);
config.NewPath = newPath;
}
string redirectUri = GetRequestBase(config.SchemeOverride) + $"/sso/OID/{(newPath ? "redirect" : "r")}/" + provider;
var options = new OidcClientOptions
{
Authority = config.OidEndpoint?.Trim(),
ClientId = config.OidClientId?.Trim(),
ClientSecret = config.OidSecret?.Trim(),
RedirectUri = GetRequestBase(config.SchemeOverride) + $"/sso/OID/{(Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase) ? "redirect" : "r")}/" + provider,
RedirectUri = redirectUri,
Scope = string.Join(" ", config.OidScopes.Prepend("openid profile")),
};
options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints
@@ -513,6 +523,14 @@ public class SSOController : ControllerBase
if (config.Enabled)
{
bool newPath = config.NewPath;
if (!isLinking)
{
newPath = Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase);
config.NewPath = newPath;
}
string redirectUri = GetRequestBase(config.SchemeOverride) + $"/sso/SAML/{(newPath ? "post" : "p")}/" + provider;
string relayState = null;
if (isLinking)
{
@@ -521,7 +539,7 @@ public class SSOController : ControllerBase
var request = new AuthRequest(
config.SamlClientId.Trim(),
GetRequestBase(config.SchemeOverride) + $"/sso/SAML/{(Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase) ? "post" : "p")}/" + provider);
redirectUri);
return Redirect(request.GetRedirectUrl(config.SamlEndpoint.Trim(), relayState));
}
@@ -599,7 +617,7 @@ public class SSOController : ControllerBase
bool liveTvManagement = config.EnableLiveTvManagement;
var samlResponse = new Response(config.SamlCertificate, response.Data);
List<string> folders;
if (!config.EnableFolderRoles)
if (!config.EnableFolderRoles && config.EnabledFolders != null)
{
folders = new List<string>(config.EnabledFolders);
}
@@ -623,11 +641,14 @@ public class SSOController : ControllerBase
if (config.EnableFolderRoles)
{
foreach (FolderRoleMap folderRoleMap in config.FolderRoleMapping)
if (config.FolderRoleMapping != null)
{
if (folderRoleMap.Role.Equals(role))
foreach (FolderRoleMap folderRoleMap in config.FolderRoleMapping)
{
folders.AddRange(folderRoleMap.Folders);
if (folderRoleMap.Role.Equals(role))
{
folders.AddRange(folderRoleMap.Folders);
}
}
}
}
@@ -660,7 +681,7 @@ public class SSOController : ControllerBase
Guid userId = await CreateCanonicalLinkAndUserIfNotExist("saml", provider, samlResponse.GetNameID());
var authenticationResult = await Authenticate(userId, isAdmin, config.EnableAuthorization, config.EnableAllFolders, folders.ToArray(), liveTv, liveTvManagement, response, config.DefaultProvider.Trim())
var authenticationResult = await Authenticate(userId, isAdmin, config.EnableAuthorization, config.EnableAllFolders, folders.ToArray(), liveTv, liveTvManagement, response, config.DefaultProvider?.Trim())
.ConfigureAwait(false);
return Ok(authenticationResult);
}
+10
View File
@@ -131,6 +131,11 @@ public class SamlConfig
/// </summary>
public string SchemeOverride { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the new, more descriptive paths are to be used.
/// </summary>
public bool NewPath { get; set; }
/// <summary>
/// Gets or sets a mapping of canonical names from the provider to jellyfin user ids.
/// </summary>
@@ -260,6 +265,11 @@ public class OidConfig
/// </summary>
public string SchemeOverride { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the new, more descriptive paths are to be used.
/// </summary>
public bool NewPath { get; set; }
/// <summary>
/// Gets or sets a mapping of canonical names from the provider to jellyfin user ids.
/// </summary>
+3 -1
View File
@@ -1,7 +1,7 @@
name: "SSO Authentication"
guid: "505ce9d1-d916-42fa-86ca-673ef241d7df"
imageUrl: "https://raw.githubusercontent.com/9p4/jellyfin-plugin-sso/main/img/logo.png"
version: "3.5.2.0"
version: "3.5.2.2"
targetAbi: "10.8.0.0"
framework: "net6.0"
owner: "9p4"
@@ -15,6 +15,8 @@ artifacts:
- "IdentityModel.OidcClient.dll"
- "IdentityModel.dll"
changelog: |
3.5.2.2: Fix linking page when using new paths
3.5.2.1: Hotfix for SAML null checks
3.5.2.0: Allow overriding the scheme used for generating URLs.
3.5.1.1: Change iframe URL to point to the web UI instead of the root
3.5.1.0: Improved paths! No more obscure "p" versus "r" URLs! Improve final redirect for automatic authentication. Add more configuration options for OpenID discovery.
Generated
+3 -3
View File
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1691218994,
"narHash": "sha256-46GJ5vLf9H+Oh7Jii2gJI9GATJHGbx2iQpon5nUSFPI=",
"lastModified": 1704842529,
"narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "0d2fb29f5071a12d7983319c2c2576be6a130582",
"rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5",
"type": "github"
},
"original": {
+2
View File
@@ -134,6 +134,8 @@ authentik:
OidScopes: ["groups"]
```
If you recieve the error `Error processing request.` from Jellyfin when attempting to login and the Jellyfin logs show `Error loading discovery document: Endpoint belongs to different authority` try setting `Do not validate endpoints` in the plugin settings.
## Keycloak OIDC
Keycloak in general is a little more complicated than other providers. Ensure that you have a realm created and have some usable users.