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: add generic OIDC connect #2046

Merged
merged 1 commit into from
Mar 13, 2024

Conversation

muhlba91
Copy link
Contributor

@muhlba91 muhlba91 commented Mar 3, 2024

This PR adds support for a generic OIDC authentication. Users can login and also signup using a custom OIDC server.

Administrators can deploy this by setting OIDC_CLIENT_ID , and the following environment variables are available to configure the OIDC flow:

  • CONNECT_WITH_OIDC_ICON: the icon to be shown in the UI
  • OIDC_AUTHORIZATION_URL: the OIDC auth endpoint
  • OIDC_USER_INFO_URL: the OIDC user info endpoint to retrieve the user's email and name (if signing up)
  • OIDC_TOKEN_URL: the OIDC token endpoint to exchange the code for a valid token
  • OIDC_SCOPES: the OIDC scopes to use for performing the request
  • OIDC_NAME_FIELD: the field containing the user's name (used for sign-up)
  • OIDC_CLIENT_ID: the OIDC client id
  • OIDC_CLIENT_SECRET: the OIDC client secret

This is based in the discussion in #1425 (comment).

Copy link
Contributor

@nguyenkims nguyenkims left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just left some comments.

app/auth/views/oidc.py Outdated Show resolved Hide resolved
app/config.py Outdated Show resolved Hide resolved
@acasajus
Copy link
Collaborator

acasajus commented Mar 7, 2024

Hey, thanks for the contribution. As a general rule we'd like to have tests for new code that's merged into the repo to make sure that:

  • the feature works as expected
  • future changes don't break it.

Would you mind adding tests to it?

app/auth/views/oidc.py Outdated Show resolved Hide resolved
@muhlba91 muhlba91 force-pushed the feat/generic-oidc branch from 283fed9 to 0943311 Compare March 8, 2024 10:58
@muhlba91
Copy link
Contributor Author

muhlba91 commented Mar 8, 2024

@acasajus @nguyenkims thank you for your review and comments! 😃
i have fixed your findings and added tests for the oidc.py methods.

@muhlba91 muhlba91 requested review from acasajus and nguyenkims March 8, 2024 11:18
@muhlba91
Copy link
Contributor Author

@nguyenkims @acasajus bumping this one again - would you be able to review again and get it into main? 😃

Copy link
Collaborator

@acasajus acasajus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey. LGTM! Let's merge 👍

@acasajus acasajus merged commit a608503 into simple-login:master Mar 13, 2024
@Queuecumber
Copy link

So happy to see this merged! I'm going to close my PR for external auth since this should cover it

Would this be available in a docker container soon?

@acasajus
Copy link
Collaborator

Should be already in the v4.41.2

@Queuecumber
Copy link

Queuecumber commented Mar 17, 2024

Hey I just wanted to leave some feedback that over all this works well

To make it work with Google I did have to set the environment variable OAUTHLIB_RELAX_TOKEN_SCOPE otherwise I would get a warning because apparently google changes the order of the oauth scopes and that causes an exception to be thrown. I'm not entirely sure if there's a way to fix this in code or not.

Also a lot of the environment variables can/should probably be read from the .well-known (https://accounts.google.com/.well-known/openid-configuration for example) rather than read manually

@muhlba91
Copy link
Contributor Author

@Queuecumber thank you for that feedback and info with the well-known endpoint!

do you happen to know if all OIDC provider must implement that well-known endpoint, meaning it's part of the specification?
the reason why i ask is that i would rather not like to rely reading from it if that means we potentially make it incompatible with some providers, whether self-hosted or not.
otherwise, i can see if the used oauth lib supports setting and reading from that endpoint.

@Queuecumber
Copy link

Here's the spec for it: https://openid.net/specs/openid-connect-discovery-1_0.html

It's unclear if this is mandatory for the provider to implement, it is certainly optional for the RP (see Sec. 2). Google, for example, says applications should use the well-known endpoint. The advantage is that if they change one of the underlying URLs it will be reflected in the well-known endpoint without needing to reconfigure the application. The well-known endpoint shouldn't (ideally) change. It's also a lot less typing to set up.

The way I usually see this implemented is that the user can either fill out all the fields manually (i.e., what we have now) OR they can give just the well-known URL and have the application discover the endpoints.

@muhlba91
Copy link
Contributor Author

thank you! 👍🏻

i like your proposal of deciding it dynamically based on whether the well-known endpoint is given or not.

currently, i'm on travel but i'll see how i can integrate that! 😃

@Queuecumber
Copy link

Awesome thanks, I did poke around and I don't think requests_oauthlib has support for it, but that may be intentional since it's just a simple API call and JSON parse to get the info

I'm also noticing an error when the callback URL has a query string on it, like https://<redacted>/auth/oidc/callback?next=%2Fdashboard%2F is a common one. It seems like you're not supposed to include those parameters in the query string of the callback, I can file a bug for this to keep things cleaner.

@viq
Copy link

viq commented Mar 22, 2024

FWIW (which isn't necessarily much), from quickly checking the docs, following Open Source OIDC providers (that I could think of) do expose the .well-known endpoint:

@viq
Copy link

viq commented Mar 22, 2024

Awesome thanks, I did poke around and I don't think requests_oauthlib has support for it, but that may be intentional since it's just a simple API call and JSON parse to get the info

Looks like it may not, but from a quick search, authlib in their docs for OAuth2 say:

This documentation covers the common design of a Python OAuth 2.0 client. Authlib provides three implementations of OAuth 2.0 client:

  1. requests_client.OAuth2Session implementation of OAuth for Requests, which is a replacement for requests-oauthlib.

and this example suggests they do support discovery via .well-known.

@muhlba91
Copy link
Contributor Author

#2077 should 1/ fix the redirect URL issue, and 2/ adds support for the OIDC well-known endpoint. as discussed, the endpoint takes precedence over all env variables but is an optional var.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants