advplyr / audiobookshelf

Self-hosted audiobook and podcast server
https://audiobookshelf.org
GNU General Public License v3.0
6.8k stars 480 forks source link

[Enhancement]: Add SSO Support (OIDC) #998

Closed DDriggs00 closed 11 months ago

DDriggs00 commented 2 years ago

Describe the feature/enhancement

The previous attempt at implementing SSO is not valid for the current version of the app.

OIDC, SAML and LDAP appear to be the most popular methods of doing this.

pto199 commented 2 years ago

I would like to see this. ODIC is the best method I think.

Im currently setting up Authentik and have some users now with Authentik usernames and passwords. It would be great if they can just visit audiobookshelf and have an account auto-create for them so I dont need to make them an account. Also they could sign on via the android/ios app with their authentik username and password. I cant bear to give my users yet another username an password for yet another app (Which they will again independently forget eventually).

2FA should be put on the backburner I say until SSO is done, cause most SSO solutions these days also do 2fa

kurokay commented 2 years ago

OIDC would be awesome !

BCNelson commented 1 year ago

I think that I'm going to take a crack at SSO. @advplyr you said in this commented that you are going to want some more design work done on this. What do you feel is the best way to get this design work done. I see a few options.

1) I write up a draft on my plan. 2) We chat about it on discord 3) We chat about it here 4) Discord call

or any combination of the above. Let me know.

Also it seems like a bit problem with the last PR was you not being able to easily setup a SSO server. I think that a vscode devcontainer could help out with that. I will set one up one the branch that I end up using.

Edit: there is also a discussion that was started since the last time I looked #1210 we could discuss there as well

advplyr commented 1 year ago

@BCNelson Your help would be great! With something like this that I'm not familiar with it's useful to highlight some self-hosted software that already has this feature. I know a few have been mentioned but I haven't looked into them yet.

It seems like the mobile app especially complicates things here. There is a related discussion here https://github.com/advplyr/audiobookshelf-app/issues/254

It's probably best to discuss on Discord to start off then if we get a PR going we could discuss there as well.

Eschguy commented 1 year ago

I'd love LDAP support

michaelkrieger commented 1 year ago

Adding my comment from another issue:

Something like Authelia adds Remote-User and Remote-Groups HTTP headers as the verify middleware is trigged. This would let you get a trusted username of the currently logged in user. This would be on the server-side of things. You'd then need the iOS/Android app to identify when authentication is required and open a web page so you can do the web-based authentication and the cookies can be grabbed. It would then need to pass the cookie with future requests. This is probably the simple way. Most other authentication backends work the same way.

The complicated/future-proof way would be to do Oath2 authentication again supported by Authelia. Same idea that the client apps would need to interface with this to prompt the user.

amuttsch commented 1 year ago

There is also an open MR to add LDAP support: https://github.com/advplyr/audiobookshelf/pull/1303

Would love to see it merged, I'm in the process on migrating all my services to LDAP / OAuth.

michaelkrieger commented 1 year ago

It may be worth noting a similar discussion here ( jellyfin-meta issue 28 ) talking about implementing it for Jellyfin.

Ultimately, a forwardauth provider like authentik/Authelia/etc behind a reverse proxy will not allow access to audiobookshelf at all prior to authenticating. So the things to consider here are:

OpenID simply protects the login and frankly is a different approach, only adding SSO. Advantage being that it doesn't need a reverse proxy.

lukeIam commented 1 year ago

General question: I read a lot here about LDAP and OpenID implementations here. Why not integrating an existing and proven authentication middleware that supports multiple auth methods? e.g. https://www.passportjs.org

I started to have a look into audiobookshelf auth code on the server side and started to do the first modifications. And integrating passport.js looks not too difficult (disclaimer: I never used passport.js before...)

tlow92 commented 1 year ago

@lukeIam I think for most people the reason is that if they host their own sever they also want their own authentication instead of relying on third party providers like google, auth0, etc. (not speaking for myself necessarily, but I understand this reasoning)

@advplyr Is there an update of current situation I might be able to help. If browser redirect on mobile is your concern, keycloak can be configured to use grant_type=password and the same forms that are currently used. This can also be combined with TOTP authenticator codes.

lukeIam commented 1 year ago

@tlow92 I totally understand this - I'm currently starting setting up my own auth server ;) But passport.js supports many auth providers (also custom hosted ones) and it's easy to add (or remove) them. Here's a list: https://www.passportjs.org/packages/

e.g. openidconnect, authentiq or ldap

This would give audiobookshelf the possiblity to support multiple (selected) auth methods/provides without much hassle and it would profit from a commonly used and maintained solution/code.

lukeIam commented 1 year ago

sorry for not writing for three weeks - I started with a passportjs integration PoC but then got ill... Today I finally was able to finish it: https://github.com/advplyr/audiobookshelf/pull/1636

please let me know what you think...

lukeIam commented 1 year ago

I've added the openIDConnect strategy and was able to authenticate using Authentik with a OAuth2/OpenID provider.

The next step would be bringing it to the client - but here I need help to understand how it currently works (e.g. interaction between api and web server) and how we could integrate it.

High level plan:

  1. Add additional buttons for each enabled auth method to the login screen
  2. Clicking the button directs the client to [api-server]/auth/[method]
  3. Client is redirected to the auth provider (with required parameters)
  4. User login or existing session is used
  5. Client is redirected back to a client server callback url (currently we are redirecting to api callback url)
  6. Client extracts the token and sends it to the api callback url
  7. Api callback url returns the userinfo json including JWT token (+ optional set auth cookie)
  8. Use the token in all requests or use the auth cookie
josephholsten commented 1 year ago

Hey there, I’m one of the contributors to the openid and oauth specs, and have done tons of auth integration in ruby, consulted for c# & Java customers. I’d strongly support @lukeIam’s approach of using authentication middleware for the first implementation.

The reason being: different auth[nz] require different state to be managed on the server side. Some things need a consumer id & secret, some things need a nonce, some things have multiple records to keep track of to refresh auth. It’s basically whack a mole for your user, group & session data structures until you get a decent handful implemented.

But once you’ve implemented delegated auth with a decent middleware framework, sometimes you will want to rip it out to replace it with something custom that better suits your needs. Usually, this has to do with group membership and resource access control. (And I’m wanting groups and access control so I can limit my kids access to some of my audiobook library ;-) Still, you’ll want the last common denominator in place before you tackle it.

Sadly, I’m about a decade out of date when it comes to node app dev, so I’m not a reliable code reviewer.

GamerClassN7 commented 1 year ago

Hello, Are there any plans for SSO Integration ? or estimated timeframe of integration ? thank you in advance"

BTW this piece of software is tonally awesome :D

lukeIam commented 1 year ago

Hello, Are there any plans for SSO Integration ? or estimated timeframe of integration ? thank you in advance"

BTW this piece of software is tonally awesome :D

maybe next week I'll have some time to further investigate (but can't promise that I get it running)

knurhp commented 1 year ago

For those looking for it - booksonic has LDAP support, might have to use that in the interim while ABS implements it's version of it...

Hopefully it won't be long as personally I prefer ABS to booksonic

lukeIam commented 1 year ago

sorry - took a bit longer but made some progress (still some stuff to do)

advplyr commented 12 months ago

OIDC support has been added. This issue will be for OIDC specifically, #185 can be the issue for LDAP, and SAML can be put in as a separate issue if that is still wanted.

OIDC is available now on the edge docker image. A new page for authentication settings has been added where you can enable and configure OIDC.

If anyone wants to help test this before it is released that would be helpful to ensure we didn't miss anything for your SSO setup. There is no guide written yet but you can see screenshots in the original PR https://github.com/advplyr/audiobookshelf/pull/1636#issuecomment-1793833884

The current mobile app will not work but if you build the mobile app from source it will work. The working mobile app will probably be released this weekend and the server shortly after.

igor47 commented 12 months ago

for Authentik:

  1. add a provider. under Providers, select Create, then OAuth2/OpenID Provider. I picked the implicit authorization flow, and left all other settings at their defaults. Note down the Client ID and Client Secret from the provider.
  2. add an application. under Applications, select Create, then give it a name, a slug, and link it to your new provider from step 1. note down the slug
  3. in Audiobookshelf settings, under Authentication, select OpenID Connect Authentication. paste the Client ID and the Client Secret into the relevant fields. For the Issuer URL field, it will be https://your.authentik.url/application/o/your-application-slug/.

after filling out the Issuer URL, i hit Auto-populate and the rest of the fields filled in automagically. I was able to log in via SSO in an incognito window. Afterwards, i disabled password authentication in Authentication settings. Now, the login screen doesn't even prompt for the password. I do, however, still have password settings if I access my account info by clicking on my username in the upper-right (at /account). the SSO still doesn't work in mobile (see https://github.com/advplyr/audiobookshelf-app/issues/949 ) but this might be because my app version is still too old (i didn't build from source)

Sapd commented 12 months ago

for Authentik:

To add to this, in Authentik or other SSO software the redirect uri has to be set to:

https://youraudiobookdomain/auth/openid/callback
audiobookshelf://oauth

Don't use wildcards like .*, they are not required. (In Authentik its seperated by new line, in Keycloak by comma afaik).

Also make sure your reverse proxy creates a X-Forwarded-Proto header correctly, otherwise you might receive a redirect_uri mismatch, because the redirect_uri is set to http even when the request was made using https.

igor47 commented 12 months ago

the redirect uri has to be set

ah thanks for that! in Authentik, it says:

If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved.

so in my case, since i tested with the web version first it saved my web URI. it would then have failed on mobile with an 'invalid redirect' error

adepssimius commented 12 months ago

Tested and functional with Authelia. That discovery button is a very welcome addition. Are there docs that I can contribute to for Authelia setup?

nichwall commented 12 months ago

Tested and functional with Authelia. That discovery button is a very welcome addition. Are there docs that I can contribute to for Authelia setup?

There is not an existing guide yet, but it would be great if you wanted to help out with the documentation. You can copy one of the existing guides as a template in the below directory to add a new User Guide to the website.

https://github.com/advplyr/audiobookshelf-web/tree/master/content%2Fguides

It would probably be best to have all of the different OIDC on the same page, sort of like how the reverse proxies are on the GH readme.

Nuuki9 commented 12 months ago

Tested and functional with Authelia. That discovery button is a very welcome addition. Are there docs that I can contribute to for Authelia setup?

Any chance you could share your Authelia config @adepssimius? This is what I'm trying currently:

      - id: audiobookshelf
        secret: SECRET
        public: false
        authorization_policy: one_factor
        scopes:
          - openid
          - email
          - profile
        redirect_uris:
        - https://URL/auth/openid/callback
        grant_types:
          - authorization_code

It brings up the OIDC page but then I get an internal server error.

adepssimius commented 12 months ago

@Nuuki9 Here is a WIP version of the guide I'm writing for SSO config, which includes excerpts from my functional Authelia config.

https://github.com/adepssimius/audiobookshelf-web/blob/master/content/guides/11.sso_configuration.md

Do you have Authelia confirmed to work as an OIDC provider with anything else already?

Nuuki9 commented 12 months ago

Many thanks - I'll take a look.

I use OIDC via Authelia with Immich, so I at least got some practice in getting that up and running :-)

Nuuki9 commented 12 months ago

That worked great - many thanks!

lukeIam commented 11 months ago

Tested with the edge container and Authentik -> is working smooth so far 👍

advplyr commented 11 months ago

Added in v2.6.0

skyzuma commented 6 months ago

is there a working guide for authentik?

DDriggs00 commented 6 months ago

Igor posted one earlier in this thread.

skyzuma commented 6 months ago

with nginx proxy manager?

edit: saved info was 3 error ... but 4th time was successfull but cant outh ...

skyzuma commented 6 months ago

it worked but websocket failed cause of an nginx proxy manager problem

image

https://github.com/NginxProxyManager/nginx-proxy-manager/issues/3474

if i delete the connection_upgrade_keepalive section, npm will work but WebSocket will not work ... i think we need to wait for an npm update in general ...

Sapd commented 6 months ago

The reverse proxy should not matter/affect with the oidc feature (except that the right X-Forwarded-For must be there).

Personally, I advise not using NPM, and instead traefik, caddy (very easy) or nginx directly.

skyzuma commented 6 months ago

it work now ... i forgot to delete the entry in the advanced tab (npm gui) for an authentik proxy-provider ... no its a oidc-provider and dont need this entry ...