-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Add generic OIDC authentication flow #6783
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6783 +/- ##
==========================================
- Coverage 63.82% 63.17% -0.65%
==========================================
Files 161 164 +3
Lines 13060 13285 +225
Branches 1803 1834 +31
==========================================
+ Hits 8335 8393 +58
- Misses 4425 4592 +167
Partials 300 300
|
- Added a generic authentication flow for OIDC. - Modified some templates to display OIDC login button. - Added new env variables to support the OIDC auth flow. Mainly, OIDC discovery endpoint is configurable now. - Added new routs for OIDC auth. - Manually tested same flow with Google (without domain verification) and AWS Cognito.
- Fixed typo - Added unit tests cases
Hi @arikfr, |
if response.status_code == 401: | ||
logger.warning("Failed getting user profile (response code 401).") | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about something like:
if not response.ok:
logger.warning(f"Failed getting user profile (response code {response.status_code}) - {response.text}.")
return None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for responding so late.
I think checking for 401 is important. But I get your point, it should also handle other non 200 HTTP status code.
if resp.status_code != 200: | ||
logger.warning( | ||
f"Unable to get configuration details (response code {resp.status_code}). Configuration URL: {url}" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Let's consistently use
response
(I prefer) orresp
.
if not response.ok:
logger.warning(
f"Unable to get configuration details (response code {resp.status_code}). Configuration URL: {url} - {response.text}"
)
name="oidc", | ||
server_metadata_url=settings.OIDC_ISSUER_URL, | ||
client_kwargs={ | ||
"scope": "openid email profile", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we make the needed scopes a var too?
([Future PR?] propagate/sync groups or roles for "redash_admin
"?)
}, | ||
) | ||
|
||
def get_user_profile(access_token): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the canonical get_userinfo
instead of get_user_profile
as profile
is just one of the possible scopes. let's to avoid confusion.
access_token = resp["access_token"] | ||
|
||
if access_token is None: | ||
logger.warning("Access token missing in call back request.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo call back
-> callback
else: | ||
org = current_org | ||
|
||
user = create_and_login_user(org, profile["name"], profile["email"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- maybe allow choosing what field to use as the
name
? - if email not verified, should we allow user creation? (avoid possible future CVE)
What type of PR is this?
Description
Generic OIDC login
Note: Seeking feedback
Problem
Currently, Redash is limited to supporting authentication via Google's OIDC. Expanding the authentication support to a generic OIDC flow increases Redash's accessibility and flexibility, making it a more inclusive tool for diverse environments.
Implementation Steps
To fully implement and integrate the generic OIDC authentication flow into Redash, the following steps need to be taken (Open for feedback):
Make OIDC Discovery Endpoint Configurable: This flexibility allows Redash to dynamically adapt to different IdPs by simply modifying configuration parameters.
Implement Routes for OIDC Authentication: Develop new routes within the application to handle the authentication process via OIDC.
Modify Login Templates: Update the UI components, specifically the login page templates, to include an OIDC login button.
Manual Testing with Multiple OIDC IdPs: To ensure compatibility and robustness, manually test the new authentication flow with multiple OIDC IdPs, including but not limited to Google, AWS, Okta, and Auth0. (Tested with Google and AWS Cognito)
Implement Unit Tests
Write Documentation for OIDC Configuration: Create detailed documentation to assist users in configuring OIDC with Redash. This documentation should cover configuration steps for different IdPs.
Mutate OIDC to include domain check: (not sure about this one) Current Google OIDC flow has domain verification, see if this can be made generic.
Replace Google OIDC with generic one
How is this tested?
For testing manually, following steps should be more are less common among different IdPs.
Related Tickets & Documents
#6781
Mobile & Desktop Screenshots/Recordings (if there are UI changes)