feat: clarify redirect paths (#84)

This commit is contained in:
Ersei Saggi
2023-08-06 14:32:05 -04:00
parent 2ead846ed8
commit defab9c4e8
3 changed files with 20 additions and 16 deletions
+8 -8
View File
@@ -104,9 +104,9 @@ The SAML provider must have the following configuration (I am using Keycloak, an
- Sign Documents on - Sign Documents on
- Sign Assertions off - Sign Assertions off
- Client Signature Required 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) - 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! 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 - Access Type: Confidential
- Standard Flow Enabled - 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) - 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! 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 #### 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. - 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/p/PROVIDER_NAME`: This is the SAML initiator: it will begin the authorization flow for SAML 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: - 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. - `deviceId`: string. Device ID.
- `deviceName`: string. Device name. - `deviceName`: string. Device name.
@@ -171,8 +171,8 @@ These all require authorization. Append an API key to the end of the request: `c
#### Flow #### 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/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/p/PROVIDER_NAME`: This is the OpenID initiator: it will begin the authorization flow for OpenID 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: - 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. - `deviceId`: string. Device ID.
- `deviceName`: string. Device name. - `deviceName`: string. Device name.
@@ -218,7 +218,7 @@ These all require authorization. Append an API key to the end of the request: `c
## Limitations ## 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). ~~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).
+7 -3
View File
@@ -65,6 +65,7 @@ public class SSOController : ControllerBase
/// <returns>A webpage that will complete the client-side flow.</returns> /// <returns>A webpage that will complete the client-side flow.</returns>
// Actually a GET: https://github.com/IdentityModel/IdentityModel.OidcClient/issues/325 // Actually a GET: https://github.com/IdentityModel/IdentityModel.OidcClient/issues/325
[HttpGet("OID/r/{provider}")] [HttpGet("OID/r/{provider}")]
[HttpGet("OID/redirect/{provider}")]
public async Task<ActionResult> OidPost( public async Task<ActionResult> OidPost(
[FromRoute] string provider, [FromRoute] string provider,
[FromQuery] string state) // Although this is a GET function, this function is called `Post` for consistency with SAML [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(), Authority = config.OidEndpoint?.Trim(),
ClientId = config.OidClientId?.Trim(), ClientId = config.OidClientId?.Trim(),
ClientSecret = config.OidSecret?.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")), Scope = string.Join(" ", config.OidScopes.Prepend("openid profile")),
}; };
options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints
@@ -269,6 +270,7 @@ public class SSOController : ControllerBase
/// <param name="isLinking">Whether or not this request is to link accounts (Rather than authenticate).</param> /// <param name="isLinking">Whether or not this request is to link accounts (Rather than authenticate).</param>
/// <returns>An asynchronous result for the authentication.</returns> /// <returns>An asynchronous result for the authentication.</returns>
[HttpGet("OID/p/{provider}")] [HttpGet("OID/p/{provider}")]
[HttpGet("OID/start/{provider}")]
public async Task<ActionResult> OidChallenge(string provider, [FromQuery] bool isLinking = false) public async Task<ActionResult> OidChallenge(string provider, [FromQuery] bool isLinking = false)
{ {
Invalidate(); Invalidate();
@@ -289,7 +291,7 @@ public class SSOController : ControllerBase
Authority = config.OidEndpoint?.Trim(), Authority = config.OidEndpoint?.Trim(),
ClientId = config.OidClientId?.Trim(), ClientId = config.OidClientId?.Trim(),
ClientSecret = config.OidSecret?.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")), Scope = string.Join(" ", config.OidScopes.Prepend("openid profile")),
}; };
options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints options.Policy.Discovery.ValidateEndpoints = false; // For Google and other providers with different endpoints
@@ -423,6 +425,7 @@ public class SSOController : ControllerBase
/// </param> /// </param>
/// <returns>A webpage that will complete the client-side flow.</returns> /// <returns>A webpage that will complete the client-side flow.</returns>
[HttpPost("SAML/p/{provider}")] [HttpPost("SAML/p/{provider}")]
[HttpPost("SAML/start/{provider}")]
public ActionResult SamlPost(string provider, [FromQuery] string relayState = null) public ActionResult SamlPost(string provider, [FromQuery] string relayState = null)
{ {
SamlConfig config; SamlConfig config;
@@ -494,6 +497,7 @@ public class SSOController : ControllerBase
/// <param name="isLinking">Whether this flow intends to link an account, or initiate auth.</param> /// <param name="isLinking">Whether this flow intends to link an account, or initiate auth.</param>
/// <returns>A redirect to the SAML provider's auth page.</returns> /// <returns>A redirect to the SAML provider's auth page.</returns>
[HttpGet("SAML/p/{provider}")] [HttpGet("SAML/p/{provider}")]
[HttpGet("SAML/start/{provider}")]
public RedirectResult SamlChallenge(string provider, [FromQuery] bool isLinking = false) public RedirectResult SamlChallenge(string provider, [FromQuery] bool isLinking = false)
{ {
SamlConfig config; SamlConfig config;
@@ -516,7 +520,7 @@ public class SSOController : ControllerBase
var request = new AuthRequest( var request = new AuthRequest(
config.SamlClientId.Trim(), 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)); return Redirect(request.GetRedirectUrl(config.SamlEndpoint.Trim(), relayState));
} }
+5 -5
View File
@@ -52,7 +52,7 @@ identity_providers:
secret: <redacted> secret: <redacted>
authorization_policy: one_factor authorization_policy: one_factor
redirect_uris: redirect_uris:
- https://jellyfin.example.com/sso/OID/r/authelia - https://jellyfin.example.com/sso/OID/redirect/authelia
``` ```
### Jellyfin's Config ### 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) ![image](img/authentik-config-04.jpg)
- Edit / Update your Jellyfin OAuth provider - 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 - Under **"Advanced Protocol Settings"**, add the **Group Membership** Scope
![image](img/authentik-config-05.jpg) ![image](img/authentik-config-05.jpg)
@@ -145,7 +145,7 @@ Ensure that the following configuration options are set:
- Access Type: Confidential - Access Type: Confidential
- Standard Flow Enabled - 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 - 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. 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 Documents on
- Sign Assertions off - Sign Assertions off
- Client Signature Required 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) - 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. Press the "Save" button at the bottom of the page.