From ee7865be1b5a506f0f8a4a55ae90013d9d5ca607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20D=C3=B6ll?= Date: Fri, 9 Aug 2024 10:01:02 +0000 Subject: [PATCH] fix: setting email address --- go.mod | 7 +++-- go.sum | 6 ++-- providers/github/github.go | 61 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 7e94ebe..f637fe3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/zeiss/fiber-goth -go 1.22 +go 1.22.0 + +toolchain go1.22.5 require ( github.com/gofiber/fiber/v2 v2.52.5 @@ -10,6 +12,7 @@ require ( github.com/katallaxie/pkg v0.6.6 github.com/spf13/cobra v1.8.1 github.com/valyala/fasthttp v1.55.0 + github.com/zeiss/pkg v0.1.6 golang.org/x/oauth2 v0.22.0 gorm.io/driver/postgres v1.5.9 gorm.io/gorm v1.25.11 @@ -193,7 +196,7 @@ require ( golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect - golang.org/x/mod v0.18.0 // indirect + golang.org/x/mod v0.19.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect diff --git a/go.sum b/go.sum index 3167974..03bf71d 100644 --- a/go.sum +++ b/go.sum @@ -423,6 +423,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeiss/pkg v0.1.6 h1:VTbzKg+Yj54swWgTevnNgR7tmEqw5gGwsSsxeSIfwE0= +github.com/zeiss/pkg v0.1.6/go.mod h1:soMcxMxuhfHDni3KGF/diy90dqWhRI2uLNlKHV3IxPk= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= @@ -462,8 +464,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/providers/github/github.go b/providers/github/github.go index a4cab44..035dce3 100644 --- a/providers/github/github.go +++ b/providers/github/github.go @@ -3,16 +3,25 @@ package github import ( "context" "encoding/json" + "errors" + "fmt" "io" "net/http" "strconv" + "strings" "github.com/zeiss/fiber-goth/adapters" "github.com/zeiss/fiber-goth/providers" + "github.com/zeiss/pkg/slices" + "github.com/zeiss/pkg/utilx" "golang.org/x/oauth2" "golang.org/x/oauth2/endpoints" ) +var ErrNoVerifiedPrimaryEmail = errors.New("goth: no verified primary email found") + +const NoopEmail = "" + var _ providers.Provider = (*githubProvider)(nil) var ( @@ -155,6 +164,17 @@ func (g *githubProvider) CompleteAuth(ctx context.Context, adapter adapters.Adap }, } + if utilx.Empty(u.Email) && slices.Any(checkScope, g.config.Scopes...) { + u.Email, err = getPrivateMail(ctx, g, token) + if err != nil { + return user, err + } + } + + if utilx.Empty(u.Email) { + return user, ErrNoVerifiedPrimaryEmail + } + user, err = adapter.CreateUser(ctx, user) if err != nil { return adapters.GothUser{}, err @@ -179,3 +199,44 @@ func newConfig(p *githubProvider, scopes ...string) *oauth2.Config { return c } + +func getPrivateMail(ctx context.Context, p *githubProvider, token *oauth2.Token) (string, error) { + req, err := http.NewRequestWithContext(ctx, "GET", p.emailURL, nil) + if err != nil { + return NoopEmail, err + } + req.Header.Add("Authorization", "Bearer "+token.AccessToken) + + res, err := p.client.Do(req) + if err != nil { + return NoopEmail, err + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + return NoopEmail, fmt.Errorf("goth: GitHub API responded with a %d trying to fetch user email", res.StatusCode) + } + + var mailList []struct { + Email string `json:"email"` + Primary bool `json:"primary"` + Verified bool `json:"verified"` + } + + err = json.NewDecoder(res.Body).Decode(&mailList) + if err != nil { + return NoopEmail, err + } + + for _, v := range mailList { + if v.Primary && v.Verified { + return v.Email, nil + } + } + + return NoopEmail, ErrNoVerifiedPrimaryEmail +} + +func checkScope(scope string) bool { + return strings.TrimSpace(scope) == "user" || strings.TrimSpace(scope) == "user:email" +}