Merge pull request #1396 from jtnord/useLoginId-dexidp
Use github login as the id
This commit is contained in:
		@@ -67,6 +67,9 @@ connectors:
 | 
				
			|||||||
    #   - ['acme:site-reliability-engineers'] for 'slug'
 | 
					    #   - ['acme:site-reliability-engineers'] for 'slug'
 | 
				
			||||||
    #   - ['acme:Site Reliability Engineers', 'acme:site-reliability-engineers'] for 'both'
 | 
					    #   - ['acme:Site Reliability Engineers', 'acme:site-reliability-engineers'] for 'both'
 | 
				
			||||||
    teamNameField: slug
 | 
					    teamNameField: slug
 | 
				
			||||||
 | 
					    # flag which will switch from using the internal GitHub id to the users handle (@mention) as the user id.
 | 
				
			||||||
 | 
					    # It is possible for a user to change their own user name but it is very rare for them to do so
 | 
				
			||||||
 | 
					    useLoginAsID: false
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## GitHub Enterprise
 | 
					## GitHub Enterprise
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,7 @@ type Config struct {
 | 
				
			|||||||
	RootCA        string `json:"rootCA"`
 | 
						RootCA        string `json:"rootCA"`
 | 
				
			||||||
	TeamNameField string `json:"teamNameField"`
 | 
						TeamNameField string `json:"teamNameField"`
 | 
				
			||||||
	LoadAllGroups bool   `json:"loadAllGroups"`
 | 
						LoadAllGroups bool   `json:"loadAllGroups"`
 | 
				
			||||||
 | 
						UseLoginAsID  bool   `json:"useLoginAsID"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Org holds org-team filters, in which teams are optional.
 | 
					// Org holds org-team filters, in which teams are optional.
 | 
				
			||||||
@@ -83,6 +84,7 @@ func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector
 | 
				
			|||||||
		clientSecret: c.ClientSecret,
 | 
							clientSecret: c.ClientSecret,
 | 
				
			||||||
		apiURL:       apiURL,
 | 
							apiURL:       apiURL,
 | 
				
			||||||
		logger:       logger,
 | 
							logger:       logger,
 | 
				
			||||||
 | 
							useLoginAsID: c.UseLoginAsID,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c.HostName != "" {
 | 
						if c.HostName != "" {
 | 
				
			||||||
@@ -148,6 +150,8 @@ type githubConnector struct {
 | 
				
			|||||||
	teamNameField string
 | 
						teamNameField string
 | 
				
			||||||
	// if set to true and no orgs are configured then connector loads all user claims (all orgs and team)
 | 
						// if set to true and no orgs are configured then connector loads all user claims (all orgs and team)
 | 
				
			||||||
	loadAllGroups bool
 | 
						loadAllGroups bool
 | 
				
			||||||
 | 
						// if set to true will use the users handle rather than their numeric id as the ID
 | 
				
			||||||
 | 
						useLoginAsID bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// groupsRequired returns whether dex requires GitHub's 'read:org' scope. Dex
 | 
					// groupsRequired returns whether dex requires GitHub's 'read:org' scope. Dex
 | 
				
			||||||
@@ -260,12 +264,16 @@ func (c *githubConnector) HandleCallback(s connector.Scopes, r *http.Request) (i
 | 
				
			|||||||
	if username == "" {
 | 
						if username == "" {
 | 
				
			||||||
		username = user.Login
 | 
							username = user.Login
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	identity = connector.Identity{
 | 
						identity = connector.Identity{
 | 
				
			||||||
		UserID:        strconv.Itoa(user.ID),
 | 
							UserID:        strconv.Itoa(user.ID),
 | 
				
			||||||
		Username:      username,
 | 
							Username:      username,
 | 
				
			||||||
		Email:         user.Email,
 | 
							Email:         user.Email,
 | 
				
			||||||
		EmailVerified: true,
 | 
							EmailVerified: true,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if c.useLoginAsID {
 | 
				
			||||||
 | 
							identity.UserID = user.Login
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Only set identity.Groups if 'orgs', 'org', or 'groups' scope are specified.
 | 
						// Only set identity.Groups if 'orgs', 'org', or 'groups' scope are specified.
 | 
				
			||||||
	if c.groupsRequired(s.Groups) {
 | 
						if c.groupsRequired(s.Groups) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -124,10 +124,11 @@ func TestUserGroupsWithTeamNameAndSlugFieldConfig(t *testing.T) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// tests that the users login is used as their username when they have no username set
 | 
				
			||||||
func TestUsernameIncludedInFederatedIdentity(t *testing.T) {
 | 
					func TestUsernameIncludedInFederatedIdentity(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s := newTestServer(map[string]testResponse{
 | 
						s := newTestServer(map[string]testResponse{
 | 
				
			||||||
		"/user": {data: user{Login: "some-login"}},
 | 
							"/user": {data: user{Login: "some-login", ID: 12345678}},
 | 
				
			||||||
		"/user/emails": {data: []userEmail{{
 | 
							"/user/emails": {data: []userEmail{{
 | 
				
			||||||
			Email:    "some@email.com",
 | 
								Email:    "some@email.com",
 | 
				
			||||||
			Verified: true,
 | 
								Verified: true,
 | 
				
			||||||
@@ -154,6 +155,7 @@ func TestUsernameIncludedInFederatedIdentity(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	expectNil(t, err)
 | 
						expectNil(t, err)
 | 
				
			||||||
	expectEquals(t, identity.Username, "some-login")
 | 
						expectEquals(t, identity.Username, "some-login")
 | 
				
			||||||
 | 
						expectEquals(t, identity.UserID, "12345678")
 | 
				
			||||||
	expectEquals(t, 0, len(identity.Groups))
 | 
						expectEquals(t, 0, len(identity.Groups))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c = githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient(), loadAllGroups: true}
 | 
						c = githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient(), loadAllGroups: true}
 | 
				
			||||||
@@ -161,8 +163,41 @@ func TestUsernameIncludedInFederatedIdentity(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	expectNil(t, err)
 | 
						expectNil(t, err)
 | 
				
			||||||
	expectEquals(t, identity.Username, "some-login")
 | 
						expectEquals(t, identity.Username, "some-login")
 | 
				
			||||||
 | 
						expectEquals(t, identity.UserID, "12345678")
 | 
				
			||||||
	expectEquals(t, identity.Groups, []string{"org-1"})
 | 
						expectEquals(t, identity.Groups, []string{"org-1"})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestLoginUsedAsIDWhenConfigured(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s := newTestServer(map[string]testResponse{
 | 
				
			||||||
 | 
							"/user": {data: user{Login: "some-login", ID: 12345678, Name: "Joe Bloggs"}},
 | 
				
			||||||
 | 
							"/user/emails": {data: []userEmail{{
 | 
				
			||||||
 | 
								Email:    "some@email.com",
 | 
				
			||||||
 | 
								Verified: true,
 | 
				
			||||||
 | 
								Primary:  true,
 | 
				
			||||||
 | 
							}}},
 | 
				
			||||||
 | 
							"/login/oauth/access_token": {data: map[string]interface{}{
 | 
				
			||||||
 | 
								"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9",
 | 
				
			||||||
 | 
								"expires_in":   "30",
 | 
				
			||||||
 | 
							}},
 | 
				
			||||||
 | 
							"/user/orgs": {
 | 
				
			||||||
 | 
								data: []org{{Login: "org-1"}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						defer s.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostURL, err := url.Parse(s.URL)
 | 
				
			||||||
 | 
						expectNil(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req, err := http.NewRequest("GET", hostURL.String(), nil)
 | 
				
			||||||
 | 
						expectNil(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient(), useLoginAsID: true}
 | 
				
			||||||
 | 
						identity, err := c.HandleCallback(connector.Scopes{Groups: true}, req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expectNil(t, err)
 | 
				
			||||||
 | 
						expectEquals(t, identity.UserID, "some-login")
 | 
				
			||||||
 | 
						expectEquals(t, identity.Username, "Joe Bloggs")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newTestServer(responses map[string]testResponse) *httptest.Server {
 | 
					func newTestServer(responses map[string]testResponse) *httptest.Server {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user