package auth import ( "CatsOfMastodonBotGo/internal/config" "bytes" "encoding/json" "io" "net/http" "net/url" "go.uber.org/zap" ) type GiteaOAuth2Handler struct { cfg *config.Config logger *zap.Logger } func NewGiteaOauth2Token(cfg *config.Config) *GiteaOAuth2Handler { return &GiteaOAuth2Handler{cfg: cfg} } func (g *GiteaOAuth2Handler) GetGiteaLoginURL(redirectHost string) (string, error) { if g.cfg.GiteaOauthInstance == "" { return "", nil } if redirectHost == "" { g.logger.Error("Redirect host not provided") return "", nil } authUrl := g.cfg.GiteaOauthInstance + "/login/oauth/authorize?client_id=" + g.cfg.GiteaOauthClientID + "&redirect_uri=" + "http://" + redirectHost + "/admin/oauth/gitea/callback&scope=openid&response_type=code&response_mode=form_post" return authUrl, nil } func (g *GiteaOAuth2Handler) GetGiteaUserEmailByCode(code string) (string, error) { if g.cfg.GiteaOauthInstance == "" { g.logger.Error("Instance URL not provided") return "", nil } // No need to verify since we are accesing the gitea once and only for the email accessToken, err := g.getGiteaAccessTokenByCode(code) if err != nil { return "", err } userInfoUrl := g.cfg.GiteaOauthInstance + "/login/oauth/userinfo" g.logger.Info(userInfoUrl) req, err := http.NewRequest("POST", userInfoUrl, nil) if err != nil { return "", err } req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("Accept", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", err } var userInfo struct { Email string `json:"email"` } if err := json.Unmarshal(body, &userInfo); err != nil { return "", err } return userInfo.Email, nil } func (g *GiteaOAuth2Handler) getGiteaAccessTokenByCode(code string) (string, error) { form := url.Values{} form.Add("client_id", g.cfg.GiteaOauthClientID) form.Add("client_secret", g.cfg.GiteaOauthClientSecret) form.Add("code", code) form.Add("grant_type", "authorization_code") req, err := http.NewRequest("POST", g.cfg.GiteaOauthInstance+"/login/oauth/access_token", bytes.NewBufferString(form.Encode())) if err != nil { return "", err } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) var tokenResp struct { AccessToken string `json:"access_token"` } if err := json.Unmarshal(body, &tokenResp); err != nil { return "", err } return tokenResp.AccessToken, nil }