From a4453dc5afb86a19fb027e6ad13a7d3c7b4ca265 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 24 Aug 2022 15:46:11 +0200 Subject: [PATCH] Implement Refresher for GitLab and refactor nits (#1031) * refactor & update gitea remote * refactor & update gitlab remote * gitlab remote: add Refresh() * change as suggested by @dsanader --- server/remote/gitea/gitea.go | 25 ++++++++++--------- server/remote/gitlab/gitlab.go | 44 ++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/server/remote/gitea/gitea.go b/server/remote/gitea/gitea.go index 3667a74c8..36d725ae8 100644 --- a/server/remote/gitea/gitea.go +++ b/server/remote/gitea/gitea.go @@ -42,7 +42,7 @@ const ( authorizeTokenURL = "%s/login/oauth/authorize" accessTokenURL = "%s/login/oauth/access_token" perPage = 50 - giteaDevVersion = "v1.17.0" + giteaDevVersion = "v1.18.0" ) type Gitea struct { @@ -84,10 +84,8 @@ func (c *Gitea) Name() string { return "gitea" } -// Login authenticates an account with Gitea using basic authentication. The -// Gitea account details are returned when the user is successfully authenticated. -func (c *Gitea) Login(ctx context.Context, w http.ResponseWriter, req *http.Request) (*model.User, error) { - config := &oauth2.Config{ +func (c *Gitea) oauth2Config() *oauth2.Config { + return &oauth2.Config{ ClientID: c.ClientID, ClientSecret: c.ClientSecret, Endpoint: oauth2.Endpoint{ @@ -96,6 +94,12 @@ func (c *Gitea) Login(ctx context.Context, w http.ResponseWriter, req *http.Requ }, RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost), } +} + +// Login authenticates an account with Gitea using basic authentication. The +// Gitea account details are returned when the user is successfully authenticated. +func (c *Gitea) Login(ctx context.Context, w http.ResponseWriter, req *http.Request) (*model.User, error) { + config := c.oauth2Config() // get the OAuth errors if err := req.FormValue("error"); err != "" { @@ -154,14 +158,9 @@ func (c *Gitea) Auth(ctx context.Context, token, secret string) (string, error) // Refresh refreshes the Gitea oauth2 access token. If the token is // refreshed the user is updated and a true value is returned. func (c *Gitea) Refresh(ctx context.Context, user *model.User) (bool, error) { - config := &oauth2.Config{ - ClientID: c.ClientID, - ClientSecret: c.ClientSecret, - Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf(authorizeTokenURL, c.URL), - TokenURL: fmt.Sprintf(accessTokenURL, c.URL), - }, - } + config := c.oauth2Config() + config.RedirectURL = "" + source := config.TokenSource(ctx, &oauth2.Token{RefreshToken: user.Secret}) token, err := source.Token() diff --git a/server/remote/gitlab/gitlab.go b/server/remote/gitlab/gitlab.go index 21b868326..62187abe1 100644 --- a/server/remote/gitlab/gitlab.go +++ b/server/remote/gitlab/gitlab.go @@ -22,6 +22,7 @@ import ( "net/http" "net/url" "strings" + "time" "github.com/rs/zerolog/log" "github.com/xanzy/go-gitlab" @@ -74,10 +75,8 @@ func (g *Gitlab) Name() string { return "gitlab" } -// Login authenticates the session and returns the -// remote user details. -func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { - config := &oauth2.Config{ +func (g *Gitlab) oauth2Config() *oauth2.Config { + return &oauth2.Config{ ClientID: g.ClientID, ClientSecret: g.ClientSecret, Scope: defaultScope, @@ -85,6 +84,12 @@ func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.R TokenURL: fmt.Sprintf("%s/oauth/token", g.URL), RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost), } +} + +// Login authenticates the session and returns the +// remote user details. +func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { + config := g.oauth2Config() // get the OAuth errors if err := req.FormValue("error"); err != "" { @@ -98,7 +103,7 @@ func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.R // get the OAuth code code := req.FormValue("code") if len(code) == 0 { - authCodeURL, err := config.AuthCodeURL("drone") + authCodeURL, err := config.AuthCodeURL("woodpecker") if err != nil { return nil, fmt.Errorf("authCodeURL error: %v", err) } @@ -139,6 +144,35 @@ func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.R return user, nil } +// Refresh refreshes the Gitlab oauth2 access token. If the token is +// refreshed the user is updated and a true value is returned. +func (g *Gitlab) Refresh(ctx context.Context, user *model.User) (bool, error) { + config := g.oauth2Config() + config.RedirectURL = "" + + trans := &oauth2.Transport{ + Config: config, + Token: &oauth2.Token{ + AccessToken: user.Token, + RefreshToken: user.Secret, + Expiry: time.Unix(user.Expiry, 0), + }, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: g.SkipVerify}, + Proxy: http.ProxyFromEnvironment, + }, + } + + if err := trans.Refresh(); err != nil { + return false, err + } + + user.Token = trans.Token.AccessToken + user.Secret = trans.Token.RefreshToken + user.Expiry = trans.Token.Expiry.UTC().Unix() + return true, nil +} + // Auth authenticates the session and returns the remote user login for the given token func (g *Gitlab) Auth(ctx context.Context, token, _ string) (string, error) { client, err := newClient(g.URL, token, g.SkipVerify)