9p4 / jellyfin-plugin-sso

This plugin allows users to sign in through an SSO provider (such as Google, Microsoft, or your own provider). This enables one-click signin.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Document How to set login disclaimer + branding css to add SSO links to frontpage

strazto opened this issue · comments

Originally posted by @matthewstrasiotto in #2 (comment)

  • Optionally, (and later) write frontend that autmatically injects this into the user's disclaimer settings
    • can probably use css to distinguish provider graphics

An example - Here, I:

  • add links that I style to match the native buttons (Forgot password, Quick Connect, etc),
    • Password Reset via authelia,
    • Server homepage
  • use css to hide the Forgot Password button, since my Audentity Provider is LDAP, and authelia provides password reset functionality (There's no setting for this)
<a href="https://authelia.example.com/reset-password/step1" class="raised cancel block emby-button">Forgot Password</a>
<a href="https://example.com" class="raised cancel block emby-button">
   <span class="material-icons home" aria-hidden="true"></span>
   <span>Server Homepage</span>
</a>
/* Hide this in lieu of authelia link */
.emby-button.block.btnForgotPassword {
   display: none;
}

/* Make links look like buttons */
a.raised.emby-button { 
   padding: 0.9em 1em;
   color: inherit !important;
}


/* Let disclaimer take full width */
.disclaimerContainer {
   display: block;
}

This renders out like so:

image

"Manual Login" and "Quick Connect" are both builtin by jellyfin, "Forgot Password" is actually my own link to authelia.

to begin with, supporting "Sign on with authelia" would look like:

Login Disclaimer:

<a href="https://myjellyfin.example.com/sso/OID/p/authelia" class="raised cancel block emby-button authelia-sso">Sign in with Authelia</a>

Custom CSS code:

/* Make links look like buttons */
a.raised.emby-button { 
   padding: 0.9em 1em;
   color: inherit !important;
}


/* Let disclaimer take full width */
.disclaimerContainer {
   display: block;
}

/* Optionally, apply some styling to the `.authelia-sso` class, probably let users configure this */
.authelia-sso {
   /* idk set a background image or something lol */
}
commented

I'm planning on restructuring the login flow just a little to accommodate this (as well as solve the issue of when the web frontend is on a different domain than the JF server). The plan is to have everything work as a programmatic API, so instead of returning a webpage, it'll return JSON or something similar and other endpoints can use that API to set cookies or whatever. Then, with this, we can set it so that the button loads some JS that interacts with the API and sets the relevant information instead. The flow would look something like this:

  1. User loads JF, presses on button
  2. Button executes some JS to send a "start auth" to SSO API
  3. SSO API returns a URL to load to auth with
  4. Button JS opens URL in new tab
  5. Once the URL has finished authentication, it will redirect back to the API
  6. Button JS has been polling API "is auth done yet" and finally gets response once callback has occurred
  7. Button JS gets data and uses it to log the user in

I think it can be simplified at some points. What do you think?

Just putting also my input as I’ve been working hard to implement sso in different services, I’m not sure opening a secondary tab is the best UX in term of sso.

Also, and maybe more important, make sure automatic sso can still be available, either with something similar to the current endpoints, or (and probably better) a configuration point telling the JS script to automatically start the login flow.
I’ve contributed something similar (although using headers and not saml/oidc) to ombi.

edit: also, I can try to help once I understand the architecture of JF and the plugins

edit 2: you can probably just skip the polling and: on load check if auth is already done, if yes poll the data and login, if no, and automatic login is implemented or the user clicks a button, start the flow, redirect just as you are doing now, and then when you redirect back to JF, it would reload the script but this time it would be in the logged in branch

commented

So the flow would be something like this:

  1. User loads JF, presses on button
  2. Button executes some JS to send a "start auth" to SSO API
  3. Button JS sets a cookie with the ID of the SSO "start"
  4. SSO API returns a URL to load to auth with
  5. Button JS opens URL
  6. Once the URL has finished authentication, it will redirect back to the API, which will redirect to the frontend
  7. Button JS checks if cookie for "start" exists, and if so, it will use the token in the cookie to get information. If not, nothing happens (step 1)
  8. Button JS gets data and uses it to log the user in

Ah sorry - I think i mean to reply with my own take on how to approach SSO flow but I must have forgotten to submit the comment.

Basically - it seems that you're implying that we add some custom javascript to the login page that handles some aspects of the flow.

Although this sounds nice, I do not believe there exists an API that would allow a plugin to inject javascript / <script> elements to arbitrary pages, which would make this challenging.

The webui (correctly) runs DOMPurify on any user created html, before it's rendered (For example, the login disclaimer).

For now, I'm unsure how to address this, but the new-tab approach should be "good enough" for a while.

Matrix conversation exerpt

Matthew Strasiotto
As I understand it, Jellyfin presently doesn't allow plugins to inject JavaScript to any page except their own plugin pages.
I'm curious if the Devs would consider allowing plugins to do that?
lakerssuperman2 joined the room.
Niels
What would your use case for such a feature be?
Matthew Strasiotto
Niels https://github.com/9p4/jellyfin-plugin-sso , for example, js based flows for authenticating with OIDC

GitHub - 9p4/jellyfin-plugin-sso: This plugin allows users to sign in through an SSO provider (such as Google, Microsoft, or your own provider). This enables one-click signin. - GitHub
This plugin allows users to sign in through an SSO provider (such as Google, Microsoft, or your own provider). This enables one-click signin. - GitHub - 9p4/jellyfin-plugin-sso: This plugin allows ...
Niels
I don't think supporting such a thing with js plugins in the frontend is really feasible
Matthew Strasiotto
what do you mean by that?
Niels
You want to inject a complete user interface with javascript, that's not going to work when the UI is managed by React. It would also 100% break for every release
Matthew Strasiotto
I'm aware that it would only apply to the web-ui & web-wrapper apps, but that doesn't bother me as that means that the same client-side plugin code can apply to the same view across like 4 platforms
hm, I don't think I'd want to inject a complete UI with JS, it'd be more along the lines of "check headers, perform auth", maybe inject an ivew for a redirect (if that's feasible)
i don't actually know how feasible that specific scenario is for OIDC flows in general, I'd need to double check
so specifics of that scenario i put forward aside, imagine someone just wants to add a button that performs some action, for example, generates a share link for a file, or triggers an opensubtitle download for the currently viewed item
am i right in thinking that there's currently no mechanic within the plugin api to perform these actions?
Niels
That's not possible no, it would be very difficult to support
Matthew Strasiotto
ok, fair enough

commented

The ideal option would be to integrate this plugin as part of the official JF spec for better frontend support, but that would be complex to maintain, and I don't know if I can manage that.

In the meantime, web-based auth in conjunction with Quick-Connect should handle 99% of the use-case.

The ideal option would be to integrate this plugin as part of the official JF spec for better frontend support, but that would be complex to maintain, and I don't know if I can manage that.

Yep, the maintainers seem pretty resistant since it would imply that every since client would have to bring its own implementation of OIDC auth

In the meantime, web-based auth in conjunction with Quick-Connect should handle 99% of the use-case.

yeah, when 10.8 gets full-released, pretty much all major clients will have implemented quick-connect

I've implemented an additional button using the method outlined in this issue to automate the SSO login, rather then just lining back to the Server homepage. Specifically, I am hitting the auth proxy redirect URL for Jellyfin. So, if I set "Name of OID Provider" in the Jellyfin's SSO settings to "authentik" the redirect would be /sso/OID/r/authentik. Anyway, this works great! However, it does launch this URL in a separate tab, which is not ideal.

So, is there any way to configure the button to open in the same tab? I've tried adding target="_self" to the link.

So, is there any way to configure the button to open in the same tab? I've tried adding target="_self" to the link.

It is hardcoded in Jellyfin web interface.

Awww. Bummer. But thanks for the quick answer! Still way better then nothing.

"authentik" the redirect would be /sso/OID/r/authentik

Did you add the redirect like this to Authentik?

image

I am still trying to verify if the Authentik/JellyFin integration is working. So any help would be greatly appreciated!

commented

yes that looks correct

commented

Fixed in 076cb1b

Hi, is it possible for the SSO Login button to follow the link in the same tab?
href should do that by default, but at least in safari and chrome it always opens in a new tab.
Is it possible to overwrite that somehow?

commented

It's hardcoded into the Jellyfin web interface code.

#16 (comment)

Hi, is it possible for the SSO Login button to follow the link in the same tab? href should do that by default, but at least in safari and chrome it always opens in a new tab. Is it possible to overwrite that somehow?

You can use a form + button to cause the URL to be opened in the current tab. Works well on browsers, although the official Jellyfin app for Android hangs on "Logging in..." when using Authelia.

<form action="https://jellyfin.example.com/sso/OID/start/PROVIDER"><button class="raised button-sso block emby-button" type="submit">Sign In with SSO</button></form>
button.raised.button-sso {
  background: #00a4dc;
}