Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
2 tasks
strazto opened this issue Apr 21, 2022 · 21 comments
Closed
2 tasks
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@strazto
Copy link
Collaborator

strazto commented Apr 21, 2022

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.

@strazto
Copy link
Collaborator Author

strazto commented Apr 21, 2022

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 */
}

@9p4
Copy link
Owner

9p4 commented Apr 21, 2022

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?

@fservida
Copy link

fservida commented Apr 23, 2022

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

@9p4
Copy link
Owner

9p4 commented Apr 23, 2022

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

@strazto
Copy link
Collaborator Author

strazto commented Apr 24, 2022

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.

@9p4 9p4 added documentation Improvements or additions to documentation enhancement New feature or request labels Apr 24, 2022
@strazto
Copy link
Collaborator Author

strazto commented May 13, 2022

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

@9p4
Copy link
Owner

9p4 commented May 13, 2022

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.

@strazto
Copy link
Collaborator Author

strazto commented May 14, 2022

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

@FirbyKirby
Copy link

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.

@NeroPcStation
Copy 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.

@FirbyKirby
Copy link

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

@adamzvolanek
Copy link
Contributor

"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!

@9p4
Copy link
Owner

9p4 commented Jul 11, 2023

yes that looks correct

@9p4
Copy link
Owner

9p4 commented Aug 6, 2023

Fixed in 076cb1b

@9p4 9p4 closed this as completed Aug 6, 2023
@hendrik1120
Copy link
Contributor

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?

@9p4
Copy link
Owner

9p4 commented Sep 12, 2023

It's hardcoded into the Jellyfin web interface code.

#16 (comment)

@isavegas
Copy link

isavegas commented Nov 26, 2023

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;
}

@nibblerrick
Copy link

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.

I just tested this with authentik. On IOS it logs in fine, on Android I have the same, hangs at "logging in..."

Thanks for the idea with the form, at least on IOS SSO login seems possible this way (direct SSO without Quickconnect, that option remains, of course).

@LeVraiRoiDHyrule
Copy link

button.raised.button-sso {
  background: #00a4dc;
}

You are my savior, thank you so much. This makes SSO work in Jellyfin Media Player, which my users have to use because most of my files are HEVC and can't be played on most browsers. Then quick connect will do the trick for the very few that use Kodi with the Jellyfin addon.

@Sapd
Copy link

Sapd commented Sep 26, 2024

If someone finds it useful. There is also a way to directly redirect to SSO if not logged in. Skipping the login-form completely.

I injected JS with nginx:

    location /login-redirect.js {
        default_type application/javascript;
        add_header Content-Disposition "inline; filename=login-redirect.js";
        return 200 '
	    let timer
            function isAndroidDevice() {
                return /Android/i.test(navigator.userAgent);
            }

            function checkForSignIn() {
	        const isLoginPage = window.location.href.includes("login.html")
		if (isLoginPage) {
		    clearInterval(timer)
                    window.location.href = "/sso/OID/start/authentik"; // Change to your desired URL
                }
	        const isLoggedIn = window.location.href.includes("index.html")
		if (isLoggedIn) clearInterval(timer)
            }
            if (!isAndroidDevice())
                timer = setInterval(checkForSignIn, 10);
        ';
    }

Then inside location /web:

        sub_filter
        '</head>'
        '<script plugin="intro-skipper" src="configurationpage?name=skip-intro-button.js"></script>
        <script src="/login-redirect.js"></script>
	</head>';

It will simply periodically check if the user is at the Jellyfin login url. If yes it will redirect for authentication to SSO. If it detects that the user is at index.html (which is never called when not logged in) it will simply delete the timer.

In my test it even worked in the mobile app. Edit: Only worked in iOS, I simply added code to exclude Android

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.