diff --git a/connector/github/github.go b/connector/github/github.go
index 933b23ff31cb3d408255c9d704abfa5f2444915b..6cb0db09df4bb3ba2a73f4f6dde1bf5450802f21 100644
--- a/connector/github/github.go
+++ b/connector/github/github.go
@@ -39,16 +39,17 @@ var (
 
 // Config holds configuration options for github logins.
 type Config struct {
-	ClientID      string `json:"clientID"`
-	ClientSecret  string `json:"clientSecret"`
-	RedirectURI   string `json:"redirectURI"`
-	Org           string `json:"org"`
-	Orgs          []Org  `json:"orgs"`
-	HostName      string `json:"hostName"`
-	RootCA        string `json:"rootCA"`
-	TeamNameField string `json:"teamNameField"`
-	LoadAllGroups bool   `json:"loadAllGroups"`
-	UseLoginAsID  bool   `json:"useLoginAsID"`
+	ClientID             string `json:"clientID"`
+	ClientSecret         string `json:"clientSecret"`
+	RedirectURI          string `json:"redirectURI"`
+	Org                  string `json:"org"`
+	Orgs                 []Org  `json:"orgs"`
+	HostName             string `json:"hostName"`
+	RootCA               string `json:"rootCA"`
+	TeamNameField        string `json:"teamNameField"`
+	LoadAllGroups        bool   `json:"loadAllGroups"`
+	UseLoginAsID         bool   `json:"useLoginAsID"`
+	PreferredEmailDomain string `json:"preferredEmailDomain"`
 }
 
 // Org holds org-team filters, in which teams are optional.
@@ -75,14 +76,15 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
 	}
 
 	g := githubConnector{
-		redirectURI:  c.RedirectURI,
-		org:          c.Org,
-		orgs:         c.Orgs,
-		clientID:     c.ClientID,
-		clientSecret: c.ClientSecret,
-		apiURL:       apiURL,
-		logger:       logger,
-		useLoginAsID: c.UseLoginAsID,
+		redirectURI:          c.RedirectURI,
+		org:                  c.Org,
+		orgs:                 c.Orgs,
+		clientID:             c.ClientID,
+		clientSecret:         c.ClientSecret,
+		apiURL:               apiURL,
+		logger:               logger,
+		useLoginAsID:         c.UseLoginAsID,
+		preferredEmailDomain: c.PreferredEmailDomain,
 	}
 
 	if c.HostName != "" {
@@ -115,6 +117,12 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
 		return nil, fmt.Errorf("invalid connector config: unsupported team name field value `%s`", c.TeamNameField)
 	}
 
+	if c.PreferredEmailDomain != "" {
+		if strings.HasSuffix(c.PreferredEmailDomain, "*") {
+			return nil, errors.New("invalid PreferredEmailDomain: glob pattern cannot end with \"*\"")
+		}
+	}
+
 	return &g, nil
 }
 
@@ -149,6 +157,8 @@ type githubConnector struct {
 	loadAllGroups bool
 	// if set to true will use the user's handle rather than their numeric id as the ID
 	useLoginAsID bool
+	// the domain to be preferred among the user's emails. e.g. "github.com"
+	preferredEmailDomain string
 }
 
 // groupsRequired returns whether dex requires GitHub's 'read:org' scope. Dex
@@ -548,7 +558,13 @@ type userEmail struct {
 // The HTTP client is expected to be constructed by the golang.org/x/oauth2 package,
 // which inserts a bearer token as part of the request.
 func (c *githubConnector) userEmail(ctx context.Context, client *http.Client) (string, error) {
+	var (
+		primaryEmail    userEmail
+		preferredEmails []userEmail
+	)
+
 	apiURL := c.apiURL + "/user/emails"
+
 	for {
 		// https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user
 		var (
@@ -575,7 +591,17 @@ func (c *githubConnector) userEmail(ctx context.Context, client *http.Client) (s
 			}
 
 			if email.Verified && email.Primary {
-				return email.Email, nil
+				primaryEmail = email
+			}
+
+			if c.preferredEmailDomain != "" {
+				_, domainPart, ok := strings.Cut(email.Email, "@")
+				if !ok {
+					return "", errors.New("github: invalid format email is detected")
+				}
+				if email.Verified && c.isPreferredEmailDomain(domainPart) {
+					preferredEmails = append(preferredEmails, email)
+				}
 			}
 		}
 
@@ -584,7 +610,36 @@ func (c *githubConnector) userEmail(ctx context.Context, client *http.Client) (s
 		}
 	}
 
-	return "", errors.New("github: user has no verified, primary email")
+	if len(preferredEmails) > 0 {
+		return preferredEmails[0].Email, nil
+	}
+
+	if primaryEmail.Email != "" {
+		return primaryEmail.Email, nil
+	}
+
+	return "", errors.New("github: user has no verified, primary email or preferred-domain email")
+}
+
+// isPreferredEmailDomain checks the domain is matching with preferredEmailDomain.
+func (c *githubConnector) isPreferredEmailDomain(domain string) bool {
+	if domain == c.preferredEmailDomain {
+		return true
+	}
+
+	preferredDomainParts := strings.Split(c.preferredEmailDomain, ".")
+	domainParts := strings.Split(domain, ".")
+
+	if len(preferredDomainParts) != len(domainParts) {
+		return false
+	}
+
+	for i, v := range preferredDomainParts {
+		if domainParts[i] != v && v != "*" {
+			return false
+		}
+	}
+	return true
 }
 
 // userInOrg queries the GitHub API for a users' org membership.
diff --git a/connector/github/github_test.go b/connector/github/github_test.go
index 76d7463cf60d2763e3c52a6bd46d2b2cfe6e8538..af8099e9c76e3ac84e0431eb60c57df35d8132a4 100644
--- a/connector/github/github_test.go
+++ b/connector/github/github_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"crypto/tls"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"net/http/httptest"
@@ -198,6 +199,290 @@ func TestLoginUsedAsIDWhenConfigured(t *testing.T) {
 	expectEquals(t, identity.Username, "Joe Bloggs")
 }
 
+func TestPreferredEmailDomainConfigured(t *testing.T) {
+	ctx := context.Background()
+	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,
+				},
+				{
+					Email:    "another@email.com",
+					Verified: true,
+					Primary:  false,
+				},
+				{
+					Email:    "some@preferred-domain.com",
+					Verified: true,
+					Primary:  false,
+				},
+				{
+					Email:    "another@preferred-domain.com",
+					Verified: true,
+					Primary:  false,
+				},
+			},
+		},
+	})
+	defer s.Close()
+
+	hostURL, err := url.Parse(s.URL)
+	expectNil(t, err)
+
+	client := newClient()
+	c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: client, preferredEmailDomain: "preferred-domain.com"}
+
+	u, err := c.user(ctx, client)
+	expectNil(t, err)
+	expectEquals(t, u.Email, "some@preferred-domain.com")
+}
+
+func TestPreferredEmailDomainConfiguredWithGlob(t *testing.T) {
+	ctx := context.Background()
+	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,
+				},
+				{
+					Email:    "another@email.com",
+					Verified: true,
+					Primary:  false,
+				},
+				{
+					Email:    "some@another.preferred-domain.com",
+					Verified: true,
+					Primary:  false,
+				},
+				{
+					Email:    "some@sub-domain.preferred-domain.co",
+					Verified: true,
+					Primary:  false,
+				},
+			},
+		},
+	})
+	defer s.Close()
+
+	hostURL, err := url.Parse(s.URL)
+	expectNil(t, err)
+
+	client := newClient()
+	c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: client, preferredEmailDomain: "*.preferred-domain.co"}
+
+	u, err := c.user(ctx, client)
+	expectNil(t, err)
+	expectEquals(t, u.Email, "some@sub-domain.preferred-domain.co")
+}
+
+func TestPreferredEmailDomainConfigured_UserHasNoPreferredDomainEmail(t *testing.T) {
+	ctx := context.Background()
+	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,
+				},
+				{
+					Email:    "another@email.com",
+					Verified: true,
+					Primary:  false,
+				},
+			},
+		},
+	})
+	defer s.Close()
+
+	hostURL, err := url.Parse(s.URL)
+	expectNil(t, err)
+
+	client := newClient()
+	c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: client, preferredEmailDomain: "preferred-domain.com"}
+
+	u, err := c.user(ctx, client)
+	expectNil(t, err)
+	expectEquals(t, u.Email, "some@email.com")
+}
+
+func TestPreferredEmailDomainNotConfigured(t *testing.T) {
+	ctx := context.Background()
+	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,
+				},
+				{
+					Email:    "another@email.com",
+					Verified: true,
+					Primary:  false,
+				},
+				{
+					Email:    "some@preferred-domain.com",
+					Verified: true,
+					Primary:  false,
+				},
+			},
+		},
+	})
+	defer s.Close()
+
+	hostURL, err := url.Parse(s.URL)
+	expectNil(t, err)
+
+	client := newClient()
+	c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: client}
+
+	u, err := c.user(ctx, client)
+	expectNil(t, err)
+	expectEquals(t, u.Email, "some@email.com")
+}
+
+func TestPreferredEmailDomainConfigured_Error_BothPrimaryAndPreferredDomainEmailNotFound(t *testing.T) {
+	ctx := context.Background()
+	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:  false,
+				},
+				{
+					Email:    "another@email.com",
+					Verified: true,
+					Primary:  false,
+				},
+				{
+					Email:    "some@preferred-domain.com",
+					Verified: true,
+					Primary:  false,
+				},
+			},
+		},
+	})
+	defer s.Close()
+
+	hostURL, err := url.Parse(s.URL)
+	expectNil(t, err)
+
+	client := newClient()
+	c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: client, preferredEmailDomain: "foo.bar"}
+
+	_, err = c.user(ctx, client)
+	expectNotNil(t, err, "Email not found error")
+	expectEquals(t, err.Error(), "github: user has no verified, primary email or preferred-domain email")
+}
+
+func Test_isPreferredEmailDomain(t *testing.T) {
+	client := newClient()
+	tests := []struct {
+		preferredEmailDomain string
+		email                string
+		expected             bool
+	}{
+		{
+			preferredEmailDomain: "example.com",
+			email:                "test@example.com",
+			expected:             true,
+		},
+		{
+			preferredEmailDomain: "example.com",
+			email:                "test@another.com",
+			expected:             false,
+		},
+		{
+			preferredEmailDomain: "*.example.com",
+			email:                "test@my.example.com",
+			expected:             true,
+		},
+		{
+			preferredEmailDomain: "*.example.com",
+			email:                "test@my.another.com",
+			expected:             false,
+		},
+		{
+			preferredEmailDomain: "*.example.com",
+			email:                "test@my.domain.example.com",
+			expected:             false,
+		},
+		{
+			preferredEmailDomain: "*.example.com",
+			email:                "test@sub.domain.com",
+			expected:             false,
+		},
+		{
+			preferredEmailDomain: "*.*.example.com",
+			email:                "test@sub.my.example.com",
+			expected:             true,
+		},
+		{
+			preferredEmailDomain: "*.*.example.com",
+			email:                "test@a.my.google.com",
+			expected:             false,
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.preferredEmailDomain, func(t *testing.T) {
+			c := githubConnector{apiURL: "apiURL", hostName: "github.com", httpClient: client, preferredEmailDomain: test.preferredEmailDomain}
+			_, domainPart, _ := strings.Cut(test.email, "@")
+			res := c.isPreferredEmailDomain(domainPart)
+
+			expectEquals(t, res, test.expected)
+		})
+	}
+}
+
+func Test_Open_PreferredDomainConfig(t *testing.T) {
+	tests := []struct {
+		preferredEmailDomain string
+		email                string
+		expected             error
+	}{
+		{
+			preferredEmailDomain: "example.com",
+			expected:             nil,
+		},
+		{
+			preferredEmailDomain: "*.example.com",
+			expected:             nil,
+		},
+		{
+			preferredEmailDomain: "*.*.example.com",
+			expected:             nil,
+		},
+		{
+			preferredEmailDomain: "example.*",
+			expected:             errors.New("invalid PreferredEmailDomain: glob pattern cannot end with \"*\""),
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.preferredEmailDomain, func(t *testing.T) {
+			c := Config{
+				PreferredEmailDomain: test.preferredEmailDomain,
+			}
+			_, err := c.Open("id", nil)
+
+			expectEquals(t, err, test.expected)
+		})
+	}
+}
+
 func newTestServer(responses map[string]testResponse) *httptest.Server {
 	var s *httptest.Server
 	s = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -231,6 +516,12 @@ func expectNil(t *testing.T, a interface{}) {
 	}
 }
 
+func expectNotNil(t *testing.T, a interface{}, msg string) {
+	if a == nil {
+		t.Errorf("Expected %+v to not to be nil", msg)
+	}
+}
+
 func expectEquals(t *testing.T, a interface{}, b interface{}) {
 	if !reflect.DeepEqual(a, b) {
 		t.Errorf("Expected %+v to equal %+v", a, b)