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

Refactor redeemCode and support a Provider-wide EnrichSessionState method #796

Merged
merged 8 commits into from Oct 21, 2020

Conversation

NickMeves
Copy link
Member

@NickMeves NickMeves commented Sep 26, 2020

Split out session enrichment from OAuth Redeem functionality in redeemCode

Add EnrichSessionState provider method to unify use cases previous done with GetUserName & GetEmailAddress. Begin refactoring migrating few GetUserName providers to EnrichSessionState as a starting point.

Motivation and Context

Codeclimate refactoring.

Simplify the provider interface and give an appropriate method to enrich sessions after Oauth2 redeem step. (A lot of providers seem to have hacked in AuthZ logic unrelated to emails into GetEmailAddress since it was the only viable hook).

How Has This Been Tested?

New unit tests added.

GitHub provider test suite cleaned up to fix test bugs.

Checklist:

  • My change requires a change to the documentation or CHANGELOG.
  • I have updated the documentation/CHANGELOG accordingly.
  • I have created a feature (non-master) branch for my PR.

@NickMeves NickMeves requested a review from a team as a code owner September 26, 2020 21:08
@NickMeves NickMeves changed the title Refactor redeem code Refactor redeemCode Sep 26, 2020
b := testGitHubBackend(map[string][]string{
"/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
"/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": false, "primary": true} ]`},
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm assuming the test wanted to test NotVerified like the name implies, hence the change in test behavior.

assert.NotEqual(t, nil, err)
assert.Equal(t, "", email)
err := p.getEmail(context.Background(), session)
assert.NoError(t, err)
Copy link
Member Author

Choose a reason for hiding this comment

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

This test was broken before -- The error catch was catching an error in the testGitHubBackend by having an empty []string{} for /repo/oauth2-proxy/oauth2-proxy.

I disagree with the underlying behavior of hasRepo -- getEmail raises an error and doesn't set an Email on an error in this method or a false return. In the false case, the email that used to be returned was "" and nil error was raised.

This refactor now at least makes it so "" won't be returned and clobber a session.Email that might already be set. But I wonder if it is best to return an actual error? (I imagine this worked in the past to restrict access accidentally by setting the session.Email to "" which failed the email domain validation.

Copy link
Member

Choose a reason for hiding this comment

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

To clarify, if hasRepo fails, ie the user has failed the authorization check, what happens presently?

Copy link
Member Author

Choose a reason for hiding this comment

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

if ok, err := p.hasRepo(ctx, s.AccessToken); err != nil || !ok {

It looks like it will return "", err is either hasRepo errors or returns false. This is fine at the moment, but not great -- and got accidental security from from our email validator not allowing empty emails. But that will change with this PR: #770

Copy link
Member Author

Choose a reason for hiding this comment

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

Even though it goes beyond a refactor, I'm thinking we need to make hasRepo returning false return an error so the security logic is completely contained here appropriately.

Copy link
Member Author

@NickMeves NickMeves Oct 9, 2020

Choose a reason for hiding this comment

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

This pattern is all over the place in this provider:

err != nil || !ok {
  return err
}

A lot of nil errors are potentially returned in auth codepaths. Punting for now, but this will need to be refactored later once we have the better Authorization scheme.

@NickMeves NickMeves changed the title Refactor redeemCode Refactor redeemCode and support a Provider-wide EnrichSessionState method Sep 27, 2020
@NickMeves
Copy link
Member Author

The GetEmailAddress method I renamed as getEmail is the source of the CodeClimate issues. It is a giant monster and needs refactoring. But it should wait until Authorize in #797 is merged -- alot of the bloat is from it doing all the authorization logic that didn't belong in GetEmailAddress.

I'll wait until a later PR to take on that refactoring.

Copy link
Member

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

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

Looks good, left a couple of comments for you when you're back from vacation!

Comment on lines -171 to -184
func (p *GitLabProvider) verifyEmailDomain(userInfo *gitlabUserInfo) error {
if len(p.EmailDomains) == 0 || p.EmailDomains[0] == "*" {
return nil
}

for _, domain := range p.EmailDomains {
if strings.HasSuffix(userInfo.Email, domain) {
return nil
}
}

return fmt.Errorf("user email is not one of the valid domains '%v'", p.EmailDomains)
}

Copy link
Member

Choose a reason for hiding this comment

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

Is this covered by the main email verification?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup - this code seemed completely redundant to our email validator check that happens right after the redeemCode section that used to perform this check.

func (p *ProviderData) GetUserName(ctx context.Context, s *sessions.SessionState) (string, error) {
return "", errors.New("not implemented")
// DEPRECATED: Migrate to EnrichSessionState
func (p *ProviderData) GetEmailAddress(_ context.Context, _ *sessions.SessionState) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Does this PR remove all use of GetEmailAddress? Do we need to keep this in?

Copy link
Member Author

Choose a reason for hiding this comment

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

Still a bunch of GetEmailAddress uses unfortunately. There were only 2 GetUserName uses, so I refactored those now while still keeping the PR small.

My goal is to go GetEmailAddress over time and have the few authorization related PRs for Keycloak and Gitlab coming in clean this up as a start.

assert.NotEqual(t, nil, err)
assert.Equal(t, "", email)
err := p.getEmail(context.Background(), session)
assert.NoError(t, err)
Copy link
Member

Choose a reason for hiding this comment

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

To clarify, if hasRepo fails, ie the user has failed the authorization check, what happens presently?

@NickMeves
Copy link
Member Author

@JoelSpeed Bump on this one when you are available.

I want to get this and #797 soon since we have a few Provider refactor PRs from the community for Keycloak & Gitlab waiting on these 2 to merge.

Copy link
Member

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

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

If we can get the changelog fixed I'm happy for this to merge

CHANGELOG.md Outdated
@@ -26,9 +26,11 @@
## Changes since v6.1.1

- [#825](https://github.com/oauth2-proxy/oauth2-proxy/pull/825) Fix code coverage reporting on GitHub actions(@JoelSpeed)
- [#767](https://github.com/oauth2-proxy/oauth2-proxy/pull/796) Deprecate GetUserName & GetEmailAdress for EnrichSessionState (@NickMeves)
Copy link
Member

Choose a reason for hiding this comment

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

We have duplicate entries here by the looks of it

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch - I even had the wrong issue # as the link text 😅

I rebased and fixed it

Copy link
Member

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @NickMeves

@JoelSpeed JoelSpeed merged commit 2aa04c9 into oauth2-proxy:master Oct 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants