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: Okta login #67

Merged
merged 7 commits into from
Sep 15, 2023
Merged

feat: Okta login #67

merged 7 commits into from
Sep 15, 2023

Conversation

scott-codecov
Copy link
Contributor

@scott-codecov scott-codecov commented Aug 4, 2023

Purpose/Motivation

Login to Codecov using Okta

Links to relevant tickets

codecov/engineering-team#145
codecov/engineering-team#146

What does this PR do?

Adds a new OAuth flow for Okta available at /login/okta

Notes to Reviewer

Unlike other OAuth providers we've integrated with, Okta requires an "issuer" which is a domain like https://{orgname}.okta.com. When clicking on a tile in Okta the issuer is passed as an iss query string param which we store in a cookie for the duration of the OAuth flow.

If we ever want to support some sort of "Single Sign On" button in Codecov then we would first need to ask for this issuer domain (or just orgname).

This will only be deployed in ECDN environments to start. We'll configure the OKTA_ISS for a specific org and set DISABLE_GIT_BASED_LOGIN to true. This will force members of that org to use Okta to login and only then can they link their Git provider account.

@scott-codecov scott-codecov changed the title Scott/okta login feat: Okta login Aug 4, 2023
@codecov
Copy link

codecov bot commented Aug 4, 2023

Codecov Report

Merging #67 (2e4bd4b) into main (aeef6b0) will increase coverage by 0.02%.
The diff coverage is 97.93%.

@@           Coverage Diff           @@
##            main     #67     +/-   ##
=======================================
+ Coverage   95.35   95.37   +0.02     
=======================================
  Files        702     704      +2     
  Lines      14965   15098    +133     
=======================================
+ Hits       14269   14399    +130     
- Misses       696     699      +3     
Flag Coverage Δ
unit 95.49% <97.93%> (?)
unit-latest-uploader 95.49% <97.93%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
codecov_auth/views/bitbucket.py 98.43% <50.00%> (-1.57%) ⬇️
codecov_auth/views/github.py 97.80% <50.00%> (-1.08%) ⬇️
codecov_auth/views/gitlab.py 98.36% <50.00%> (-1.64%) ⬇️
codecov/settings_base.py 88.13% <100.00%> (+0.34%) ⬆️
codecov_auth/migrations/0040_oktauser.py 100.00% <100.00%> (ø)
codecov_auth/models.py 98.87% <100.00%> (+0.01%) ⬆️
codecov_auth/tests/factories.py 100.00% <100.00%> (ø)
codecov_auth/urls.py 100.00% <100.00%> (ø)
codecov_auth/views/okta.py 100.00% <100.00%> (ø)
graphql_api/types/config/config.py 100.00% <100.00%> (ø)
... and 1 more

codecov_auth/views/okta.py Fixed Show resolved Hide resolved
* main: (74 commits)
  Fix indentation error (#133)
  Add cache cleanup (#130)
  Feature/lint pre commit (#134)
  feat: trigger label analysis task after update (#131)
  Filter file comparisons by flags (#129)
  chore: Remove hard-coded dev BB redirect URL (#132)
  feat: Validate OIDC ID token during Sentry OAuth flow (#52)
  Adding beginnings of GHA CI (#127)
  feat: Filter flags by flags for pathContents (#128)
  Create checkbox in Owner form in Django admin to set uses_invoice (#109)
  build(deps): bump certifi from 2020.6.20 to 2023.7.22 (#32)
  Feature/no compile (#126)
  Bump django from 4.2.2 to 4.2.3 (#42)
  Don't compile since source is available (#106)
  feat: Add firstPull resolver to GraphQL pull type (#108)
  chore: Upgrade requests and redis dependencies (#124)
  Update LICENSE (#122)
  Attempt migration (#121)
  359 adjust monthly uploads for trialled customers (#119)
  Add changes for monthly uploads to account for trialing customer (#101)
  ...
codecov_auth/views/okta.py Dismissed Show dismissed Hide dismissed
fields=[
("id", models.BigAutoField(primary_key=True, serialize=False)),
("external_id", models.UUIDField(default=uuid.uuid4, editable=False)),
("created_at", models.DateTimeField(auto_now_add=True)),
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm, when we use the BaseCodecovModel, we don't save this with the ...WithoutTZField, we okay with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's probably fine. We're extending from BaseCodecovModel in a lot of other models as well.

if request.GET.get("code"):
return self._perform_login(request)
else:
iss = settings.OKTA_ISS or request.GET.get("iss")
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional: not sure if iss over issuer is understandable if you're familiar with OIDC, but otherwise I'd push for the latter for readability

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The query string param has to be iss since that's what Okta sends. I think since it's referred to as iss elsewhere (i.e. in the ID token, query param, etc.) then I'm inclined to keep it as iss so you know it's the same thing. I expect you'd need some familiarity with OIDC to fully follow this code anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotchaa, yeap that makes sense! We can keep it as is

def _perform_login(self, request: HttpRequest) -> HttpResponse:
code = request.GET.get("code")
iss = settings.OKTA_ISS or request.COOKIES.get("_okta_iss")
if iss is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we ever hit this? Since at the very least we'd have the iss from _redirect_to_consent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd say this would be unexpected. IDK - maybe somebody has cookies disabled or something.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeaah that's fair, asking in case this could be dead code that adds complexity, but I think that's fair. In that scenario they wouldn't be able to use okta hmmm, unlikely, but we can keep it in here and see if we hit this

okta_user = OktaUser.objects.filter(okta_id=okta_id).first()

current_user = None
if request.user is not None and not request.user.is_anonymous:
Copy link
Contributor

Choose a reason for hiding this comment

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

Say a user log in with Okta, and eventually with Github. Woul that user be connected to both? (that would make sense to me)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, they'll have a single users record and then an okta_users record + owners record that both reference that single user.

response = redirect(f"{settings.CODECOV_DASHBOARD_URL}/{service}")
else:
# user has not connected any owners yet
response = redirect(f"{settings.CODECOV_DASHBOARD_URL}/sync")
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a new url? I don't think I've seen this sync endpoint 👀

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah a new page that Nick created to support "Login with Sentry". Once a user is authenticated but doesn't have any linked Git providers we send them to this page (where they can sync a Git provider).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh it's not merged yet: codecov/gazebo#2235

@codecov-staging
Copy link

@codecov-public-qa
Copy link

codecov-public-qa bot commented Sep 15, 2023

Codecov Report

❗ No coverage uploaded for pull request base (main@aeef6b0). Click here to learn what that means.
The diff coverage is 97.93%.

Impacted file tree graph

@@           Coverage Diff           @@
##             main      #67   +/-   ##
=======================================
  Coverage        ?   95.49%           
=======================================
  Files           ?      590           
  Lines           ?    14886           
  Branches        ?        0           
=======================================
  Hits            ?    14215           
  Misses          ?      671           
  Partials        ?        0           
Flag Coverage Δ
unit 95.49% <97.93%> (?)
unit-latest-uploader 95.49% <97.93%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
codecov_auth/views/bitbucket.py 98.43% <50.00%> (ø)
codecov_auth/views/github.py 97.80% <50.00%> (ø)
codecov_auth/views/gitlab.py 98.36% <50.00%> (ø)
codecov/settings_base.py 85.31% <100.00%> (ø)
codecov_auth/migrations/0040_oktauser.py 100.00% <100.00%> (ø)
codecov_auth/models.py 98.87% <100.00%> (ø)
codecov_auth/tests/factories.py 100.00% <100.00%> (ø)
codecov_auth/urls.py 100.00% <100.00%> (ø)
codecov_auth/views/okta.py 100.00% <100.00%> (ø)
graphql_api/types/config/config.py 100.00% <100.00%> (ø)
... and 1 more

Impacted file tree graph

@codecov-staging
Copy link

codecov-staging bot commented Sep 15, 2023

@scott-codecov scott-codecov merged commit e8d9790 into main Sep 15, 2023
20 of 23 checks passed
@scott-codecov scott-codecov deleted the scott/okta-login branch September 15, 2023 13:05
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.

None yet

2 participants