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

Github connector #1512

Merged
merged 5 commits into from
Dec 15, 2017
Merged

Github connector #1512

merged 5 commits into from
Dec 15, 2017

Conversation

r0mant
Copy link
Collaborator

@r0mant r0mant commented Dec 14, 2017

Add support for Github connector. Closes #1445.

constants.go Outdated
SAML = "saml"

// Github means authentication will happen remotely using a Github connector.
Github = "github"
Copy link
Contributor

Choose a reason for hiding this comment

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

why not Github = ConnectorGithub


// GithubAuthResponse represents Github auth callback validation response
type GithubAuthResponse struct {
// Username is the name of authorized user
Copy link
Contributor

Choose a reason for hiding this comment

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

authenticated

if err != nil {
return nil, trace.Wrap(err)
}
// exchange the authorization code we got in the callback for access token
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of using we everywhere, can you please refer tot he code path, e.g. `exchange authorization code auth service got in the callback" here and below.

if err != nil {
return nil, trace.Wrap(err)
}
if len(connector.GetTeamsToLogins()) != 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

should return error and log to the logs with Warning if there is not GetTeamsToLogins to simplify troubleshooting.

Kind: services.KindUser,
Version: services.V2,
Metadata: services.Metadata{
Name: claims.Email,
Copy link
Contributor

Choose a reason for hiding this comment

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

why not github username and email? github username should be unique and not every user has email set?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am pretty sure email is mandatory for every Github account. We can use a username instead I think, should not be an issue.

Copy link
Collaborator Author

@r0mant r0mant Dec 15, 2017

Choose a reason for hiding this comment

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

Only in this case we'd have to request the scope user:read which is a bit broader than user:email which we request now (and which grants permissions to read only email addresses).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've updated the code to use Github username instead of email. Actually username is public information so we don't need any additional scopes for it, so we only request read:org now.

logger := log.WithFields(log.Fields{trace.Component: "github"})
logger.Debug("Web login start")
clientRedirectURL := r.URL.Query().Get("redirect_url")
if clientRedirectURL == "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

was there a problem with random redirect_url that we had to check by stripping off the domain part and using relative vs absolute redirects?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ConnectorID: req.ConnectorID,
PublicKey: req.PublicKey,
CertTTL: req.CertTTL,
CheckUser: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

why check user is true here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've originally implemented it similar to OIDC but then realized that this parameter was always true anyway, so I've just removed it now.

logger.Warnf("Unable to verify CSRF token: %v", err)
return nil, trace.AccessDenied("access denied")
}
logger.Infof("Callback redirecting to web browser")
Copy link
Contributor

Choose a reason for hiding this comment

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

missing dots at the end of log lines

httplib.SafeRedirect(w, r, response.Req.ClientRedirectURL)
return nil, nil
}
logger.Infof("Callback redirecting to console login")
Copy link
Contributor

Choose a reason for hiding this comment

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

Callback is redirecting

@@ -16,6 +16,23 @@ limitations under the License.

package ui

const (
// WebConfigAuthProviderOIDCType is OIDC provider type
WebConfigAuthProviderOIDCType = "oidc"
Copy link
Contributor

Choose a reason for hiding this comment

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

duplicate constant

@@ -197,6 +197,11 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*RewritingHandler, error) {
h.GET("/webapi/saml/sso", httplib.MakeHandler(h.samlSSO))
h.POST("/webapi/saml/login/console", httplib.MakeHandler(h.samlSSOConsole))

// Github connector handlers
h.GET("/webapi/github/login/web", httplib.MakeHandler(h.githubLoginWeb))
Copy link
Contributor

Choose a reason for hiding this comment

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

if we have time, i suggest to use 1 endpoint for handling all types of oauth. web logins.
/webapi/oauth?type=XXX&rest...

It should remove duplicate code (which duplicates csrf checks) and make it easier to add a new type in the future (no need to modify web app code).

This is going to be a safe change as it's used only by web app.

Copy link
Contributor

Choose a reason for hiding this comment

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

we don't have any other oauth logins at the moment, so this is not relevant.

Copy link
Contributor

Choose a reason for hiding this comment

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

h.GET("/webapi/oidc/login/web", httplib.MakeHandler(h.oidcLoginWeb))
h.GET("/webapi/saml/sso", httplib.MakeHandler(h.samlSSO))
h.GET("/webapi/github/login/web", httplib.MakeHandler(h.githubLoginWeb))

all of them do the same thing for the most part. my suggestion is to use 1 endpoint and pass a provider type

Copy link
Contributor

Choose a reason for hiding this comment

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

@alex-kovoy from Golang's URL router's perspective there's no difference between /one/two and /one?arg=two. you can route all 3 to the same function.

Copy link
Contributor

Choose a reason for hiding this comment

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

@kontsevoy this is about code duplication. We have 3 functions doing the same thing for each above route. The suggestion is to have 1 function to reduce code duplication.

We do not need to have 3 different routes either.

Copy link
Contributor

Choose a reason for hiding this comment

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

there are similar, but not the same, so let's keep it as is for now.

@@ -534,10 +577,26 @@ func (h *Handler) getWebConfig(w http.ResponseWriter, r *http.Request, p httprou
// get all SAML connectors
samlConnectors, err := h.cfg.ProxyClient.GetSAMLConnectors(false)
if err != nil {
log.Infof("Cannot retrieve SAML connectors: %v", err)
log.Errorf("Cannot retrieve SAML connectors: %v.", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

will it log an error if SAML connectors are not configured? (in which case this is not an error)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nope, it's not an error.

@kontsevoy
Copy link
Contributor

LGTM. I will move the docs to 2.4 manually later.

@r0mant r0mant merged commit 9b18790 into master Dec 15, 2017
@r0mant r0mant deleted the roman/github branch December 15, 2017 23:49
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