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

feat: support OIDC authentication #184

Open
wants to merge 73 commits into
base: develop
Choose a base branch
from

Conversation

michaelhthomas
Copy link

@michaelhthomas michaelhthomas commented Jul 11, 2022

Description

Adds support for logging in using an OIDC Identity Provider (Auth0, Authentik, Keycloak, etc.).

Refactors Plex OAuth login to be in its own component, like the other identity providers.

Screenshot (if UI-related)

Login Page

Settings Page

To-Dos

  • Successful build yarn build
  • Translation keys yarn i18n:extract
  • Database migration (if required)

Issues Fixed or Closed

@john-sp
Copy link

john-sp commented Jul 14, 2022

You may want to blur some of the info in the image

@Fallenbagel
Copy link
Owner

Ah I see that you resolved the merge conflicts. Was going to ask. Thanks

@Fallenbagel
Copy link
Owner

@michaelhthomas Hi. I tried to test this PR, however, during first setup in the library step, I get this error and I am not able to continue it setup
image

@michaelhthomas
Copy link
Author

Uh oh... I'm pretty sure that means you made it to the second page but aren't logged in with Plex or Jellyfin, which probably means the login failed and I need to add some better error handling. Which one were you testing?

@Fallenbagel
Copy link
Owner

Which one were you testing?

Jellyfin. That is from the libraries setup page right after logging in

@michaelhthomas
Copy link
Author

@Fallenbagel Found the bug and am working on a fix. Got a question...right now there's a value for MediaServerType.EMBY that's essentially unused, since emby is actually treated as MediaServerType.JELLYFIN with JELLYFIN_TYPE set to "emby". Would you be ok with removing MediaServerType.EMBY to avoid confusion, or would you rather everything use MediaServerType.EMBY instead of JELLYFIN_TYPE for consistency?

@Fallenbagel
Copy link
Owner

We need the MediaServerType=Emby as the current emby implementation is temporary. We are going to be implementing emby without the env variable through api which would also allow us to have simultaneous server support. So we need it

@michaelhthomas
Copy link
Author

Ok sweet. I'll test Emby with my current implementation to make sure everything works as expected, and when it's implemented properly there will probably be some changes that need to be made to the login window / setup wizard.

@Fallenbagel
Copy link
Owner

Ok sweet. I'll test Emby with my current implementation to make sure everything works as expected, and when it's implemented properly there will probably be some changes that need to be made to the login window / setup wizard.

I have not tested yet but if it works for emby it should work for jellyfin. Will test tonight

@Fallenbagel
Copy link
Owner

Fallenbagel commented Aug 18, 2022

I tested the setup and it indeed worked. However, as I have no way of testing OIDC, I will deploy this as a preview tag (:preview-pr184 for testing for now

@Fallenbagel Fallenbagel added the merge conflict Cannot merge due to merge conflicts label Sep 7, 2022
@michaelhthomas
Copy link
Author

@Fallenbagel resolved the merge conflicts. OIDC is working great for me (using authentik) but would love to have some others test with different OIDC providers.

@Fallenbagel
Copy link
Owner

Fallenbagel commented Sep 18, 2022

@Fallenbagel resolved the merge conflicts. OIDC is working great for me (using authentik) but would love to have some others test with different OIDC providers.

Is LDAP possible with this? (I don't really know OIDCs and stuff so)

@michaelhthomas
Copy link
Author

@Fallenbagel resolved the merge conflicts. OIDC is working great for me (using authentik) but would love to have some others test with different OIDC providers.

Is LDAP possible with this? (I don't really know OIDCs and stuff so)

Not directly. A number of oauth2 / OIDC providers do integrate with LDAP (including authentik) for authentication, but oauth2 is much higher level. Where LDAP acts more like an external users database, an OIDC/oauth provider handles all the sign in and authentication logic. Plex SSO actually uses oauth2 afaik, it just doesn't conform to the OIDC standard.

@BoBeR182
Copy link

I can test with Keycloak, just learning how to compile and run this build still.

@Fallenbagel
Copy link
Owner

Fallenbagel commented Sep 22, 2022

I can test with Keycloak, just learning how to compile and run this build still.

If you want to compile it natively to test instead of the deployed docker snapshot, pull this PR and try it

And please provide feedback. Feedback is very much needed (since this is kind of a big feature)

@atropos112
Copy link

atropos112 commented Sep 23, 2022

Howdy,

I am excited to see this MR, its certainly something that is missing in my setup and hence i (somewhat selfishly) want to help.


My relevant setup:
I am running Sonarr, Radarr, Jellyfin and of course Jellyseerr. I am also running Authelia which I currently use as my OpenID solution for ArgoCD, WikiJs, Grafana, Harbor and Gitlab.


I have never implemented open id login mechanism but I have connected few applications to OpenID that Authelia provides (as outlined above), I am happy to test and provide feedback. I have ran your branch locally and have few questions.

A typical config in Authelia looks something like this

- id: <user-picked-id-here>
  pre_configured_consent_duration: '365d'
  description: idk
  secret: <SECRETHERE>
  public: false
  authorization_policy: one_factor
  audience: []
  scopes:
    - openid
    - email
    - profile
  redirect_uris:
    - <CALLBACKURL>
   response_modes:
        - form_post 

(I believe data needed to setup is somewhat similar for KeyCloak +- some small details)

In particular both Authelia and the app (Jellyseerr in this case) need to have id and the secret, both of which are chosen by the client.. In addition authelia (keycloak also) needs the callback url and the required scopes. In your implementation I see place for id but not the secret, is there a way of adding this ? I also do not know (maybe i am missing something obvious) what the callback url is and what scopes are required.

@michaelhthomas
Copy link
Author

Howdy,

I am excited to see this MR, its certainly something that is missing in my setup and hence i (somewhat selfishly) want to help.

My relevant setup: I am running Sonarr, Radarr, Jellyfin and of course Jellyseerr. I am also running Authelia which I currently use as my OpenID solution for ArgoCD, WikiJs, Grafana, Harbor and Gitlab.

I have never implemented open id login mechanism but I have connected few applications to OpenID that Authelia provides (as outlined above), I am happy to test and provide feedback. I have ran your branch locally and have few questions.

A typical config in Authelia looks something like this

- id: <user-picked-id-here>
  pre_configured_consent_duration: '365d'
  description: idk
  secret: <SECRETHERE>
  public: false
  authorization_policy: one_factor
  audience: []
  scopes:
    - openid
    - email
    - profile
  redirect_uris:
    - <CALLBACKURL>
   response_modes:
        - form_post 

(I believe data needed to setup is somewhat similar for KeyCloak +- some small details)

In particular both Authelia and the app (Jellyseerr in this case) need to have id and the secret, both of which are chosen by the client.. In addition authelia (keycloak also) needs the callback url and the required scopes. In your implementation I see place for id but not the secret, is there a way of adding this ? I also do not know (maybe i am missing something obvious) what the callback url is and what scopes are required.

Because Jellyseerr is a SPA (single page app), it uses the OAuth PKCE authorization flow instead of the traditional authorization flow. Since all of the login and (most of) the validation logic occurs on the client when using this flow, the client secret is not used. This is a "public" authorization flow, so the configuration will look a little bit different from apps using the traditional authorization flow. This looks to be the relevant configuration option for Authelia, and other providers should have similar options. In order to maintain security with this mechanism, be sure that the redirect URLs are limited only to your Jellyseerr instance (https://your-jellyseerr-instance.xyz/login). Also, the openid, profile, and email scopes are all used so that Jellyseer can view users' names and email addresses. Thanks for being open to testing this out!

@atropos112
Copy link

atropos112 commented Sep 24, 2022

That makes a lot of sense! I take it then I need something like this

      - id: jellyseerr
        public: true
        authorization_policy: two_factor
        audience: []
        scopes:
        - openid
        - email
        - profile
        redirect_uris:
        - https://jellyserrr-instance.xyz/login
        userinfo_signing_algorithm: none
        response_modes:
        - form_post 

I am building the docker image now, will shortly deploy and update.

@Fallenbagel
Copy link
Owner

That makes a lot of sense! I take it then I need something like this

      - id: jellyseerr
        public: true
        authorization_policy: two_factor
        audience: []
        scopes:
        - openid
        - email
        - profile
        redirect_uris:
        - https://jellyserrr-instance.xyz/login
        userinfo_signing_algorithm: none
        response_modes:
        - form_post 

I am building the docker image now, will shortly deploy and update.

Docker image is already built tho. Can be access through preview-prxxx where xxx is this PRs number

@atropos112
Copy link

atropos112 commented Sep 24, 2022

I wanted to test it further so I ran

docker build -t oicd-jellyseerr -f Dockerfile .
docker tag oidc-jellyseerr:latest myharbor.xyz/testing/oidc-jellyseerr:develop
docker push myharbor.xyz/testing/oidc-jellyseerr:develop

but when i run a pod with the above image I get
image
(pressing reload refreshes the page and this pop-up appears again)
this is strange, I tried running on the normal develop branch to see if its something with your changes (which I doubted) but I get the same issue. Data seems to need to be reloaded but even if i start on fresh pvc i still get this. Is there some variable I am missing ?

@michaelhthomas
Copy link
Author

I wanted to test it further so I ran

docker build -t oicd-jellyseerr -f Dockerfile .
docker tag oidc-jellyseerr:latest myharbor.xyz/testing/oidc-jellyseerr:develop
docker push myharbor.xyz/testing/oidc-jellyseerr:develop

but when i run a pod with the above image I get
image
(pressing reload refreshes the page and this pop-up appears again)
this is strange, I tried running on the normal develop branch to see if its something with your changes (which I doubted) but I get the same issue. Data seems to need to be reloaded but even if i start on fresh pvc i still get this. Is there some variable I am missing ?

What happens when you press the reload button? That just looks like your browser still has the old version of the web interface cached

@crltc
Copy link

crltc commented May 4, 2024

On the latest preview (as of the date of this post) I am running into the http redirect uri issue that a few others mentioned. My Jellyseerr instance is configured with a valid cert and the URL in the settings is set to https. In my case restarting and reconfiguring did not resolve the issue. Below is what I see from authentik server logs:

"redirect_uri_expected": ["https://jellyseerr.domain.com/login/oidc/callback"], "redirect_uri_given": "http://jellyseerr.domain.com/login/oidc/callback",

@4WaYDp
Copy link

4WaYDp commented May 4, 2024

On the latest preview (as of the date of this post) I am running into the http redirect uri issue that a few others mentioned. My Jellyseerr instance is configured with a valid cert and the URL in the settings is set to https. In my case restarting and reconfiguring did not resolve the issue. Below is what I see from authentik server logs:

"redirect_uri_expected": ["https://jellyseerr.domain.com/login/oidc/callback"], "redirect_uri_given": "http://jellyseerr.domain.com/login/oidc/callback",

You should enable 'Enable Proxy Support' in jellyseeerr settings.

@crltc
Copy link

crltc commented May 5, 2024

On the latest preview (as of the date of this post) I am running into the http redirect uri issue that a few others mentioned. My Jellyseerr instance is configured with a valid cert and the URL in the settings is set to https. In my case restarting and reconfiguring did not resolve the issue. Below is what I see from authentik server logs:
"redirect_uri_expected": ["https://jellyseerr.domain.com/login/oidc/callback"], "redirect_uri_given": "http://jellyseerr.domain.com/login/oidc/callback",

You should enable 'Enable Proxy Support' in jellyseeerr settings.

Thank you! That fixed my issue and everything is now working as expected with Authentik.

@chinyongcy
Copy link

On the latest preview (as of the date of this post) I am running into the http redirect uri issue that a few others mentioned. My Jellyseerr instance is configured with a valid cert and the URL in the settings is set to https. In my case restarting and reconfiguring did not resolve the issue. Below is what I see from authentik server logs:
"redirect_uri_expected": ["https://jellyseerr.domain.com/login/oidc/callback"], "redirect_uri_given": "http://jellyseerr.domain.com/login/oidc/callback",

You should enable 'Enable Proxy Support' in jellyseeerr settings.

Thank you! That fixed my issue and everything is now working as expected with Authentik.

How did you get it to work with Authentik?

  1. I have created a custom property mapping
    `if ak_is_group_member(request.user, name="Jellyfin_Users"):
    return {"jellyfinuser": True} ‘

  2. In my Application Provider, I added to scope
    IMG_4448

  3. Then in jellyseer added the scope and required claims
    IMG_4450

  4. But in the docker logs when I try to log in I will get something like ‘jellyfinusers’ is a required field

  5. I decoded the token and ‘jellyfinuser’ is not shown. But in my authentik Jellyfin provider I can see that the preview for user ‘jellyfinuser’ is there

Try for the whole night as for now I’m just using ‘email_verified’ for the claims as a workaround. Am trying to set it up the right way

@crltc
Copy link

crltc commented May 7, 2024

On the latest preview (as of the date of this post) I am running into the http redirect uri issue that a few others mentioned. My Jellyseerr instance is configured with a valid cert and the URL in the settings is set to https. In my case restarting and reconfiguring did not resolve the issue. Below is what I see from authentik server logs:
"redirect_uri_expected": ["https://jellyseerr.domain.com/login/oidc/callback"], "redirect_uri_given": "http://jellyseerr.domain.com/login/oidc/callback",

You should enable 'Enable Proxy Support' in jellyseeerr settings.

Thank you! That fixed my issue and everything is now working as expected with Authentik.

How did you get it to work with Authentik?

1. I have created a custom property mapping
   `if ak_is_group_member(request.user, name="Jellyfin_Users"):
   return {"jellyfinuser": True} ‘

2. In my Application Provider, I added to scope
   ![IMG_4448](https://private-user-images.githubusercontent.com/55968202/328050794-e7360cdc-a30c-4adf-b09b-dc6c2dd68b23.jpeg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTUwNDk0NDgsIm5iZiI6MTcxNTA0OTE0OCwicGF0aCI6Ii81NTk2ODIwMi8zMjgwNTA3OTQtZTczNjBjZGMtYTMwYy00YWRmLWIwOWItZGM2YzJkZDY4YjIzLmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNTA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDUwN1QwMjMyMjhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1jMzAzYjM2YWZjNTUwMmY0YjIzN2NkNmM5MjA3OTUyMWVhNDhhZDE4YTM3YTVlM2FlZGVlOWFiMWI0OTEwZjhjJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.MxYdhWGKRJhKcxoNYMPwnYwcp3xpKviCbTFk2luaJ4s)

3. Then in jellyseer added the scope and required claims
   ![IMG_4450](https://private-user-images.githubusercontent.com/55968202/328051096-7e394943-cc65-4de2-a713-76652721e5a7.jpeg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTUwNDk0NDgsIm5iZiI6MTcxNTA0OTE0OCwicGF0aCI6Ii81NTk2ODIwMi8zMjgwNTEwOTYtN2UzOTQ5NDMtY2M2NS00ZGUyLWE3MTMtNzY2NTI3MjFlNWE3LmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNTA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDUwN1QwMjMyMjhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04M2ZhZmMzZmVkYjkwYTBkMjE0Njc0MGI4OGNiMmM2Njg4ZWJhYmFmNDMyNWVmZGFjNTZiMjAwYmE1ZDBhYTRmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.1Dh9s0bKUbiN5ZfFVBA7PtLOcefA6cLLYz33Y_YFp34)

4. But in the docker logs when I try to log in I will get something like ‘jellyfinusers’ is a required field

5. I decoded the token and ‘jellyfinuser’ is not shown. But in my authentik Jellyfin provider I can see that the preview for user ‘jellyfinuser’ is there

Try for the whole night as for now I’m just using ‘email_verified’ for the claims as a workaround. Am trying to set it up the right way

Below are the settings that worked for me. Don't forget to add your user to the group (it's obvious but easy to overlook).

Jellyseerr OpenID Connect Configuration
Scopes: email openid profile jellyfin
Identification Claims: preferred_username
Required Claims: jellyfin

Authentik Custom Property Mapping
Name: authentik OAuth Mapping: OpenID 'jellyfin'
Scope Name: jellyfin
Expression:

jellyfin_claims = {}
if request.user.ak_groups.filter(name="jellyfin").exists():
    jellyfin_claims["jellyfin"]= True
return jellyfin_claims

@chinyongcy
Copy link

chinyongcy commented May 7, 2024

On the latest preview (as of the date of this post) I am running into the http redirect uri issue that a few others mentioned. My Jellyseerr instance is configured with a valid cert and the URL in the settings is set to https. In my case restarting and reconfiguring did not resolve the issue. Below is what I see from authentik server logs:
"redirect_uri_expected": ["https://jellyseerr.domain.com/login/oidc/callback"], "redirect_uri_given": "http://jellyseerr.domain.com/login/oidc/callback",

You should enable 'Enable Proxy Support' in jellyseeerr settings.

Thank you! That fixed my issue and everything is now working as expected with Authentik.

How did you get it to work with Authentik?

1. I have created a custom property mapping
   `if ak_is_group_member(request.user, name="Jellyfin_Users"):
   return {"jellyfinuser": True} ‘

2. In my Application Provider, I added to scope
   ![IMG_4448](https://private-user-images.githubusercontent.com/55968202/328050794-e7360cdc-a30c-4adf-b09b-dc6c2dd68b23.jpeg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTUwNDk0NDgsIm5iZiI6MTcxNTA0OTE0OCwicGF0aCI6Ii81NTk2ODIwMi8zMjgwNTA3OTQtZTczNjBjZGMtYTMwYy00YWRmLWIwOWItZGM2YzJkZDY4YjIzLmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNTA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDUwN1QwMjMyMjhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1jMzAzYjM2YWZjNTUwMmY0YjIzN2NkNmM5MjA3OTUyMWVhNDhhZDE4YTM3YTVlM2FlZGVlOWFiMWI0OTEwZjhjJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.MxYdhWGKRJhKcxoNYMPwnYwcp3xpKviCbTFk2luaJ4s)

3. Then in jellyseer added the scope and required claims
   ![IMG_4450](https://private-user-images.githubusercontent.com/55968202/328051096-7e394943-cc65-4de2-a713-76652721e5a7.jpeg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTUwNDk0NDgsIm5iZiI6MTcxNTA0OTE0OCwicGF0aCI6Ii81NTk2ODIwMi8zMjgwNTEwOTYtN2UzOTQ5NDMtY2M2NS00ZGUyLWE3MTMtNzY2NTI3MjFlNWE3LmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNTA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDUwN1QwMjMyMjhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04M2ZhZmMzZmVkYjkwYTBkMjE0Njc0MGI4OGNiMmM2Njg4ZWJhYmFmNDMyNWVmZGFjNTZiMjAwYmE1ZDBhYTRmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.1Dh9s0bKUbiN5ZfFVBA7PtLOcefA6cLLYz33Y_YFp34)

4. But in the docker logs when I try to log in I will get something like ‘jellyfinusers’ is a required field

5. I decoded the token and ‘jellyfinuser’ is not shown. But in my authentik Jellyfin provider I can see that the preview for user ‘jellyfinuser’ is there

Try for the whole night as for now I’m just using ‘email_verified’ for the claims as a workaround. Am trying to set it up the right way

Below are the settings that worked for me. Don't forget to add your user to the group (it's obvious but easy to overlook).

Jellyseerr OpenID Connect Configuration Scopes: email openid profile jellyfin Identification Claims: preferred_username Required Claims: jellyfin

Authentik Custom Property Mapping Name: authentik OAuth Mapping: OpenID 'jellyfin' Scope Name: jellyfin Expression:

jellyfin_claims = {}
if request.user.ak_groups.filter(name="jellyfin").exists():
    jellyfin_claims["jellyfin"]= True
return jellyfin_claims

Thank you for the settings. I did almost the same as well, but still not able to get it.
In Authentik:
Property Mappings:
image

Provider Scope:
image

JWT Preview Payload:
image

Go to my Profile -> Consent -> Remove Jellyseer first. (To start fresh without consent, not sure if it matters)

In Jellyseer:
image

I am still getting auth error.
image

This is what I get in logs
Failed OIDC login attempt {"cause":"Invalid jwt or missing claims","ip":"10.0.0.70","idToken":"","errorMessage":"jellyfin is a required field"}
Decoded in jwt.io
image

Been trying the same since 2 days back, tried restarting both authentik and jellyseer container.
Seems like the scope is not getting updated, if not I think that my previous settings should have worked as well.

Just in case i use the wrong image tag. This is what I use "fallenbagel/jellyseerr:preview-OIDC" in my docker compose.

@crltc
Copy link

crltc commented May 7, 2024

It looks right to me and matches my setup, the only other thing I could say to check is the include_claims_in_id_token value in your oauth2 provider in Authentik for Jellyseerr. This is a snippet of what mine looks like (Terraform):

  client_type                = "confidential"
  include_claims_in_id_token = true
  issuer_mode                = "per_provider"
  jwks_sources               = []
  sub_mode                   = "hashed_user_id"

If not that then I'm not sure, hopefully someone else can take a look.

edit: I doubt the above is the issue but I'm out of ideas.

@chinyongcy
Copy link

It looks right to me and matches my setup, the only other thing I could say to check is the include_claims_in_id_token value in your oauth2 provider in Authentik for Jellyseerr. This is a snippet of what mine looks like (Terraform):

  client_type                = "confidential"
  include_claims_in_id_token = true
  issuer_mode                = "per_provider"
  jwks_sources               = []
  sub_mode                   = "hashed_user_id"

If not that then I'm not sure, hopefully someone else can take a look.

edit: I doubt the above is the issue but I'm out of ideas.
Ah that's cool, didn't know it can be configured with terraform. Love the idea, one more thing to my to do list!
Anyway I have the same setting in the UI
image

I guess the issue could be I upgrade "jellyseer:latest" directly to "preview-OIDC". Maybe over the weekend I will do a clean install and start over again.

Thank you so much!

@maarten-vdb
Copy link

I've tried getting it to work with Authelia, but trying to set it up myself as well as using the configs mentioned above all result in a 401 error response. Does anyone have a working example config?

@gregismotion
Copy link

It would work for me, but Jellyseer wants to redirect me to my local ip address+port combo, but it is under a reverse proxy.

(I ticked on the proxy support and set the App URL correctly)

@gregismotion
Copy link

It would work for me, but Jellyseer wants to redirect me to my local ip address+port combo, but it is under a reverse proxy.

(I ticked on the proxy support and set the App URL correctly)

Solved, had to add this to NGINX:

    proxy_set_header Referer $http_referer;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Real-Port $remote_port;
    proxy_set_header X-Forwarded-Host $host:$remote_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-Port $remote_port;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Ssl on;

@NovaPreem
Copy link

NovaPreem commented May 20, 2024

fwiw am on Authelia and it doesn't work due to the error above a lot of the time.
Gotten around it somewhat but requires DB intervention.

** WARNING: I recommend backing up your DB + config before attempting this if you do. **

  1. Server is configured to matchJellyfinAccounts=true
  2. Someone logs in, it creates a local user account. You want to turn that into a jellyfin account.
  3. Shut down server, copy the 3 db files to another folder.
  4. Edit them using sqlite db editor: change their users entry to match the jellyfin accounts. Fill in dummy data in the other fields, and make sure the jellyfin mapping name is correct.
  5. Write DB Changes, replace file. Start Jellyfin.
  6. Fixed. Not sure how the login flow doesn't break the server the same way, but ok.

The unfortunate part is that you keep having to do this. It wouldn't surprise me if the fix is related to #183 (comment)

But at this point I just needed it work.

@goodguybane
Copy link

goodguybane commented May 22, 2024

This works perfectly for me using Authentik and Plex including automatic login. I started from scratch and do not have any advanced config settings in NPM.

Jellyseerr:
Issuer URL: https://auth.example.com/application/o/applicationname

Authentik Provider:
Redirect URI: https://jellyseerr.example.com/login/oidc/callback

image

Copy link

This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged.

@github-actions github-actions bot added the merge conflict Cannot merge due to merge conflicts label May 23, 2024
@NetDude12
Copy link

NetDude12 commented May 24, 2024

This works perfectly for me using Authentik and Plex including automatic login. I started from scratch and do not have any advanced config settings in NPM.

Jellyseerr: Issuer URL: https://auth.example.com/application/o/applicationname

Authentik Provider: Redirect URI: https://jellyseerr.example.com/login/oidc/callback

image

Just wanted to confirm that this worked for me right out of the box. (cloudflair tunnel, no NPM)

@crltc
Copy link

crltc commented May 28, 2024

Interestingly enough, I have not touched my jellyseerr setup for a few weeks after getting it working using the parameters I included my previous posts. Now when I logged in I noticed that that my OIDC settings reset to default and among changing them back to what I originally had working - I get the same error that @chinyongcy has. Not sure where to start troubleshooting. Note that my volumes are static and haven't been reset.

@emielpopla
Copy link

emielpopla commented May 28, 2024

I have tried the implementation with Zitadel.
It seems to work well but there is just one little issue.
The redirect_uri I get is a http:// url instead of https:// : http://jellyseer.example.om/login/oidc/callback
If I add this one to my redirect URIs it works but I have to put my project in Development Mode, which I don't want to do.

@emielpopla
Copy link

I have tried the implementation with Zitadel. It seems to work well but there is just one little issue. The redirect_uri I get is a http:// url instead of https:// : http://jellyseer.example.om/login/oidc/callback If I add this one to my redirect URIs it works but I have to put my project in Development Mode, which I don't want to do.

EDIT: Nevermind I enabled 'Proxy Support' and 'CSRF Protection' and that seems to solve that issue. Can confirm that for Zitadel as OIDC provider it works nicely

@4WaYDp
Copy link

4WaYDp commented May 28, 2024

I have set up oidc with Authelia; everything works fine except that Full Library Scan and Recently Added Scan stopped working. There are no errors thrown, not on Jellyseeerr and not Emby. The owner-user can login with oidc and is of type Emby user (3). Is anybody else having these problems?

@jorti
Copy link

jorti commented May 29, 2024

I have set up oidc with Authelia; everything works fine except that Full Library Scan and Recently Added Scan stopped working. There are no errors thrown, not on Jellyseeerr and not Emby. The owner-user can login with oidc and is of type Emby user (3). Is anybody else having these problems?

I have the same problem. Jellyseerr fails to access the Jellyfin API, so things like the sync or scan of the Jellyfin libraries don't work.

@Fallenbagel
Copy link
Owner

I have set up oidc with Authelia; everything works fine except that Full Library Scan and Recently Added Scan stopped working. There are no errors thrown, not on Jellyseeerr and not Emby. The owner-user can login with oidc and is of type Emby user (3). Is anybody else having these problems?

I have the same problem. Jellyseerr fails to access the Jellyfin API, so things like the sync or scan of the Jellyfin libraries don't work.

Can you share your logs. When you press sync or scan. Need more info.

@jorti
Copy link

jorti commented May 29, 2024

I have set up oidc with Authelia; everything works fine except that Full Library Scan and Recently Added Scan stopped working. There are no errors thrown, not on Jellyseeerr and not Emby. The owner-user can login with oidc and is of type Emby user (3). Is anybody else having these problems?

I have the same problem. Jellyseerr fails to access the Jellyfin API, so things like the sync or scan of the Jellyfin libraries don't work.

Can you share your logs. When you press sync or scan. Need more info.

I'm using the latest container image docker.io/fallenbagel/jellyseerr:preview-OIDC.
The only message I get when I click on "Sync libraries" is:

2024-05-29T08:37:37.111Z [error][Jellyfin API]: Something went wrong while getting libraries from the Jellyfin server: Request failed with status code 404

If I configure the Jellyfin internal URL to be my reverse proxy, I can see that the failed request goes to the /Users//Views Jellyfin endpoint:

192.168.1.1 - - [29/May/2024:08:48:27 +0000] "GET /Users//Views HTTP/1.1" 404 988 "-" "-" 104003 "jellyfin@docker" "http://10.89.0.117:80" 1ms

It looks like the double slash is causing problems:

# curl -I https://jellyfin.example.com/Users//View
HTTP/2 404 
accept-ranges: bytes
alt-svc: h3=":443"; ma=2592000
content-type: text/html
date: Wed, 29 May 2024 08:51:52 GMT
etag: "65b785cb-3dc"
last-modified: Mon, 29 Jan 2024 11:02:35 GMT
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=63072000; includeSubDomains; preload
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-robots-tag: noindex, nofollow
x-xss-protection: 1; mode=block
content-length: 988

# curl -I https://jellyfin.example.com/Users/View
HTTP/2 405 
allow: DELETE, GET, POST
alt-svc: h3=":443"; ma=2592000
date: Wed, 29 May 2024 08:51:54 GMT
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=63072000; includeSubDomains; preload
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-response-time-ms: 7.4041
x-robots-tag: noindex, nofollow
x-xss-protection: 1; mode=block

The relevant parts of the settings.json file:

 "main": {
  "apiKey": "REDACTED",
  "applicationTitle": "Jellyseerr",
  "applicationUrl": "https://jellyseerr.example.com",
  "csrfProtection": true,
  "cacheImages": false,
  "defaultPermissions": 71303200,
  "defaultQuotas": {
   "movie": {
    "quotaLimit": 0,
    "quotaDays": 7
   },
   "tv": {
    "quotaLimit": 0,
    "quotaDays": 7
   }
  },
  "hideAvailable": false,
  "localLogin": false,
  "mediaServerLogin": true,
  "newPlexLogin": true,
  "oidcLogin": true,
  "oidc": {
   "providerName": "Authelia",
   "providerUrl": "https://auth.example.com",
   "clientId": "jellyseerr",
   "clientSecret": "REDACTED",
   "userIdentifier": "preferred_username",
   "requiredClaims": "email_verified",
   "scopes": "email openid profile groups",
   "matchJellyfinUsername": true,
   "automaticLogin": false
  },
  "region": "ES",
  "originalLanguage": "",
  "trustProxy": true,
  "mediaServerType": 2,
  "partialRequestsEnabled": true,
  "locale": "es"
 },
 "jellyfin": {
  "name": "",
  "hostname": "http://jellyfin:8096",
  "externalHostname": "https://jellyfin.example.com",
  "jellyfinForgotPasswordUrl": "https://auth.example.com/reset-password/step1",
  "libraries": [
   {
    "id": "ed2a25286c558a96e1424971742ca350",
    "name": "Movies",
    "enabled": true,
    "type": "movie"
   },
   {
    "id": "5ddaa59a73205234890fdcfc683e14ef",
    "name": "Shows",
    "enabled": true,
    "type": "show"
   }
  ],
  "serverId": "a0c6a6aff1ce4463c0a2eda775a310f9"
 },

In addition to that, I had to grant myself owner permissions by editing the database manually:

# sqlite3 /var/lib/containers/storage/volumes/jellyseerr/_data/db/db.sqlite3

sqlite> select id, email, username, permissions from user;
sqlite> update user set permissions = 3 where id = 1;
sqlite> .exit

@jorti
Copy link

jorti commented May 29, 2024

After a bit more digging I've found a workaround for the 404 errors when accessing the Jellyfin API. The problem is that Jellyseerr doesn't know my Jellyfin user id, so the call to /Users/JELLYFIN_USER_ID/View is incorrect.

I've discovered my user id and created an API key in Jellyfin, then added them to my user in Jellyseerr:

sqlite> select id, email, username, jellyfinUsername, jellyfinAuthToken, jellyfinUserId, jellyfinDeviceId from user;
1|username@example.com|username||||

sqlite> update user set jellyfinUsername = 'username', jellyfinUserId = 'JELLYFIN_USER_ID', jellyfinAuthToken = 'REDACTED'  where id = 1;

After that, the library scan works.

I think this Jellyfin API key setting should be a global option and not per-user.

@Fallenbagel
Copy link
Owner

Fallenbagel commented May 29, 2024

I think this Jellyfin API key setting should be a global option and not per-user.

We dont use apikeys. We use auth tokens (specifically the auth token of the owner account for syncing). So whatever apikey you generate on jellyfin doesn't matter as we only use authTokens. Which is something that's designed to be automatically retrieved when logging in. Sounds like your jellyfinUserId changed (which should never happen) but that was causing jellyseerr to not update your authtoken(?) but im not sure why you were getting a 404.

Just an fyi, the behavior of login, authtokens are already very different from this PR (I think this pr is about 2 versions old).

@github-actions github-actions bot removed the merge conflict Cannot merge due to merge conflicts label May 29, 2024
@michaelhthomas
Copy link
Author

Just an fyi, the behavior of login, authtokens are already very different from this PR (I think this pr is about 2 versions old).

Yeah.... I'm thinking of just making a new PR based on the one upstream (sct/overseerr#3746) with some tweaks and additional features from this one. Since that might have a smaller scope, hopefully it could end up being merged more quickly. I could then make some smaller PRs with additional user interface and functionality improvements that aren't strictly necessary to get the feature released.

@Fallenbagel
Copy link
Owner

Fallenbagel commented May 29, 2024

Just an fyi, the behavior of login, authtokens are already very different from this PR (I think this pr is about 2 versions old).

Yeah.... I'm thinking of just making a new PR based on the one upstream (sct/overseerr#3746) with some tweaks and additional features from this one. Since that might have a smaller scope, hopefully it could end up being merged more quickly. I could then make some smaller PRs with additional user interface and functionality improvements that aren't strictly necessary to get the feature released.

That would be great. Specifically the biggest change we're gonna get on auth is #773 and apikeys (we're gonna stop authtokens)

@Sapd
Copy link

Sapd commented May 31, 2024

There is a bug at least in the latest build:

When a user has an email like John.Doe@gmail.com in Authentik (watch at the upper-cases) and then trys to login, he will get an error and the log report:

SQLITE_CONSTRAINT: UNIQUE constraint failed: user.email"

Changing his email to lower case in Authentik fixes it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
preview PRs deployed for testing with tag `:preview-prxx`
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Support login with OIDC [Feature request] SSO