From defab9c4e8558d347314bb9a8b74ce673c5dede4 Mon Sep 17 00:00:00 2001 From: Ersei Saggi Date: Sun, 6 Aug 2023 14:32:05 -0400 Subject: [PATCH] feat: clarify redirect paths (#84) --- README.md | 16 ++++++++-------- SSO-Auth/Api/SSOController.cs | 10 +++++++--- providers.md | 10 +++++----- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index fe101f0..ba43912 100644 --- a/README.md +++ b/README.md @@ -104,9 +104,9 @@ The SAML provider must have the following configuration (I am using Keycloak, an - Sign Documents on - Sign Assertions off - Client Signature Required off -- Redirect URI: [https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME](https://myjellyfin.example.com/sso/OID/p/PROVIDER_NAME) +- Redirect URI: [https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME) - Base URL: [https://myjellyfin.example.com](https://myjellyfin.example.com) -- Master SAML processing URL: [https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME) +- Master SAML processing URL: [https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME) Make sure that `clientid` is replaced with the actual client ID and `PROVIDER_NAME` is replaced with the chosen provider name! @@ -120,7 +120,7 @@ The OpenID provider must have the following configuration (again, I am using Key - Access Type: Confidential - Standard Flow Enabled -- Redirect URI: [https://myjellyfin.example.com/sso/OID/r/PROVIDER_NAME](https://myjellyfin.example.com/sso/OID/r/PROVIDER_NAME) +- Redirect URI: [https://myjellyfin.example.com/sso/OID/redirect/PROVIDER_NAME](https://myjellyfin.example.com/sso/OID/redirect/PROVIDER_NAME) - Base URL: [https://myjellyfin.example.com](https://myjellyfin.example.com) Make sure that `clientid` is replaced with the actual client ID and `PROVIDER_NAME` is replaced with the chosen provider name! @@ -133,8 +133,8 @@ The API is all done from a base URL of `/sso/` #### Flow -- POST `SAML/p/PROVIDER_NAME`: This is the SAML POST endpoint. It accepts a form response from the SAML provider and returns HTML and JavaScript for the client to login with a given provider name. -- GET `SAML/p/PROVIDER_NAME`: This is the SAML initiator: it will begin the authorization flow for SAML with a given provider name. +- POST `SAML/start/PROVIDER_NAME`: This is the SAML POST endpoint. It accepts a form response from the SAML provider and returns HTML and JavaScript for the client to login with a given provider name. +- GET `SAML/start/PROVIDER_NAME`: This is the SAML initiator: it will begin the authorization flow for SAML with a given provider name. - POST `SAML/Auth/PROVIDER_NAME`: This is the SAML client-side API: the HTML and JavaScript client will call this endpoint to receive Jellyfin credentials given a provider name. Post format is in JSON with the following keys: - `deviceId`: string. Device ID. - `deviceName`: string. Device name. @@ -171,8 +171,8 @@ These all require authorization. Append an API key to the end of the request: `c #### Flow -- GET `OID/r/PROVIDER_NAME`: This is the OpenID callback path. This will return HTML and JavaScript for the client to login with a given provider name. -- GET `OID/p/PROVIDER_NAME`: This is the OpenID initiator: it will begin the authorization flow for OpenID with a given provider name. +- GET `OID/redirect/PROVIDER_NAME`: This is the OpenID callback path. This will return HTML and JavaScript for the client to login with a given provider name. +- GET `OID/start/PROVIDER_NAME`: This is the OpenID initiator: it will begin the authorization flow for OpenID with a given provider name. - POST `OID/Auth/PROVIDER_NAME`: This is the OpenID client-side API: the HTML and JavaScript client will call this endpoint to receive Jellyfin credentials for a given provider name. Post format is in JSON with the following keys: - `deviceId`: string. Device ID. - `deviceName`: string. Device name. @@ -218,7 +218,7 @@ These all require authorization. Append an API key to the end of the request: `c ## Limitations -There is no GUI to sign in. You have to make it yourself! The buttons should redirect to something like this: [https://myjellyfin.example.com/sso/SAML/p/clientid](https://myjellyfin.example.com/sso/SAML/p/clientid) replacing `clientid` with the provider client ID and `SAML` with the auth scheme (either `SAML` or `OID`). +There is no GUI to sign in. You have to make it yourself! The buttons should redirect to something like this: [https://myjellyfin.example.com/sso/SAML/start/clientid](https://myjellyfin.example.com/sso/SAML/start/clientid) replacing `clientid` with the provider client ID and `SAML` with the auth scheme (either `SAML` or `OID`). ~~Furthermore, there is no functional admin page (yet). PRs for this are welcome. In the meantime, you have to interact with the API to add or remove configurations.~~ 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). diff --git a/SSO-Auth/Api/SSOController.cs b/SSO-Auth/Api/SSOController.cs index c3d7e9e..75981fc 100644 --- a/SSO-Auth/Api/SSOController.cs +++ b/SSO-Auth/Api/SSOController.cs @@ -65,6 +65,7 @@ public class SSOController : ControllerBase /// A webpage that will complete the client-side flow. // Actually a GET: https://github.com/IdentityModel/IdentityModel.OidcClient/issues/325 [HttpGet("OID/r/{provider}")] + [HttpGet("OID/redirect/{provider}")] public async Task OidPost( [FromRoute] string provider, [FromQuery] string state) // Although this is a GET function, this function is called `Post` for consistency with SAML @@ -86,7 +87,7 @@ public class SSOController : ControllerBase Authority = config.OidEndpoint?.Trim(), ClientId = config.OidClientId?.Trim(), ClientSecret = config.OidSecret?.Trim(), - RedirectUri = GetRequestBase() + "/sso/OID/r/" + provider, + RedirectUri = GetRequestBase() + $"/sso/OID/{(Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase) ? "redirect" : "r")}/" + provider, Scope = string.Join(" ", config.OidScopes.Prepend("openid profile")), }; options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints @@ -269,6 +270,7 @@ public class SSOController : ControllerBase /// Whether or not this request is to link accounts (Rather than authenticate). /// An asynchronous result for the authentication. [HttpGet("OID/p/{provider}")] + [HttpGet("OID/start/{provider}")] public async Task OidChallenge(string provider, [FromQuery] bool isLinking = false) { Invalidate(); @@ -289,7 +291,7 @@ public class SSOController : ControllerBase Authority = config.OidEndpoint?.Trim(), ClientId = config.OidClientId?.Trim(), ClientSecret = config.OidSecret?.Trim(), - RedirectUri = GetRequestBase() + "/sso/OID/r/" + provider, + RedirectUri = GetRequestBase() + $"/sso/OID/{(Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase) ? "redirect" : "r")}/" + provider, Scope = string.Join(" ", config.OidScopes.Prepend("openid profile")), }; options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints @@ -423,6 +425,7 @@ public class SSOController : ControllerBase /// /// A webpage that will complete the client-side flow. [HttpPost("SAML/p/{provider}")] + [HttpPost("SAML/start/{provider}")] public ActionResult SamlPost(string provider, [FromQuery] string relayState = null) { SamlConfig config; @@ -494,6 +497,7 @@ public class SSOController : ControllerBase /// Whether this flow intends to link an account, or initiate auth. /// A redirect to the SAML provider's auth page. [HttpGet("SAML/p/{provider}")] + [HttpGet("SAML/start/{provider}")] public RedirectResult SamlChallenge(string provider, [FromQuery] bool isLinking = false) { SamlConfig config; @@ -516,7 +520,7 @@ public class SSOController : ControllerBase var request = new AuthRequest( config.SamlClientId.Trim(), - GetRequestBase() + "/sso/SAML/p/" + provider); + GetRequestBase() + $"/sso/SAML/{(Request.Path.Value.Contains("/start/", StringComparison.InvariantCultureIgnoreCase) ? "start" : "p")}/" + provider); return Redirect(request.GetRedirectUrl(config.SamlEndpoint.Trim(), relayState)); } diff --git a/providers.md b/providers.md index d5a3654..c14367c 100644 --- a/providers.md +++ b/providers.md @@ -52,7 +52,7 @@ identity_providers: secret: authorization_policy: one_factor redirect_uris: - - https://jellyfin.example.com/sso/OID/r/authelia + - https://jellyfin.example.com/sso/OID/redirect/authelia ``` ### Jellyfin's Config @@ -113,7 +113,7 @@ Now we can add this property mapping to authentik's Jellyfin OAuth provider: ![image](img/authentik-config-04.jpg) - Edit / Update your Jellyfin OAuth provider -- Verify your **"Redirect URIs/Origins (RegEx)"** follows the format: `https://domain.tld/sso/OID/r/Authentik`. +- Verify your **"Redirect URIs/Origins (RegEx)"** follows the format: `https://domain.tld/sso/OID/redirect/Authentik`. - Under **"Advanced Protocol Settings"**, add the **Group Membership** Scope ![image](img/authentik-config-05.jpg) @@ -145,7 +145,7 @@ Ensure that the following configuration options are set: - Access Type: Confidential - Standard Flow Enabled -- Redirect URI: https://myjellyfin.example.com/sso/OID/r/PROVIDER_NAME +- Redirect URI: https://myjellyfin.example.com/sso/OID/redirect/PROVIDER_NAME - Base URL: https://myjellyfin.example.com Press the "Save" button at the bottom of the page and open the "Credentials" tab. Note down the secret. @@ -179,9 +179,9 @@ Ensure that the following configuration options are set: - Sign Documents on - Sign Assertions off - Client Signature Required off -- Redirect URI: [https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME) +- Redirect URI: [https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME) - Base URL: [https://myjellyfin.example.com](https://myjellyfin.example.com) -- Master SAML processing URL: [https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/p/PROVIDER_NAME) +- Master SAML processing URL: [https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME](https://myjellyfin.example.com/sso/SAML/start/PROVIDER_NAME) Press the "Save" button at the bottom of the page.