github.com/kubeshop/testkube@v1.17.23/internal/app/api/v1/slack_oauth.go (about) 1 package v1 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 9 "github.com/gofiber/fiber/v2" 10 11 thttp "github.com/kubeshop/testkube/pkg/http" 12 ) 13 14 const slackAccessUrl = "https://slack.com/api/oauth.v2.access" 15 16 var ( 17 SlackBotClientID = "" 18 SlackBotClientSecret = "" 19 ) 20 21 type oauthResponse struct { 22 Ok bool `json:"ok"` 23 AppID string `json:"app_id"` 24 AuthedUser struct { 25 ID string `json:"id"` 26 } `json:"authed_user"` 27 Scope string `json:"scope"` 28 TokenType string `json:"token_type"` 29 AccessToken string `json:"access_token"` 30 BotUserID string `json:"bot_user_id"` 31 Team struct { 32 ID string `json:"id"` 33 Name string `json:"name"` 34 } `json:"team"` 35 Enterprise interface{} `json:"enterprise"` 36 IsEnterpriseInstall bool `json:"is_enterprise_install"` 37 } 38 39 // OauthHandler creates a handler for slack authentication 40 func (s TestkubeAPI) OauthHandler() fiber.Handler { 41 return func(c *fiber.Ctx) error { 42 43 errStr := c.Query("error", "") 44 if errStr != "" { 45 c.Status(http.StatusUnauthorized) 46 _, err := c.WriteString(errStr) 47 return err 48 } 49 code := c.Query("code", "") 50 if code == "" { 51 return s.Error(c, http.StatusBadRequest, fmt.Errorf("Code was not provided")) 52 } 53 54 if SlackBotClientID == "" && SlackBotClientSecret == "" { 55 return s.Error(c, http.StatusInternalServerError, fmt.Errorf("\nSlack secrets are not set\n")) 56 } 57 58 var slackClient = thttp.NewClient() 59 60 req, err := http.NewRequest(http.MethodGet, slackAccessUrl, nil) 61 if err != nil { 62 return s.Error(c, http.StatusInternalServerError, fmt.Errorf("\nFailed to create request: %+v\n", err)) 63 } 64 65 req.SetBasicAuth(SlackBotClientID, SlackBotClientSecret) 66 q := req.URL.Query() 67 q.Add("code", code) 68 req.URL.RawQuery = q.Encode() 69 req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 70 71 resp, err := slackClient.Do(req) 72 if err != nil { 73 return s.Error(c, http.StatusInternalServerError, fmt.Errorf("\nFailed to get access token: %+v\n", err)) 74 } 75 defer resp.Body.Close() 76 77 body, err := io.ReadAll(resp.Body) 78 79 if err != nil { 80 return s.Error(c, http.StatusInternalServerError, fmt.Errorf("\nInvalid format for access token: %+v", err)) 81 } 82 83 oResp := oauthResponse{} 84 err = json.Unmarshal(body, &oResp) 85 86 if err != nil { 87 return s.Error(c, http.StatusInternalServerError, fmt.Errorf("\nUnable to unmarshal the response: %+v", err)) 88 } 89 90 if len(oResp.AccessToken) == 0 { 91 return s.Error(c, http.StatusInternalServerError, fmt.Errorf("Unable to get the response from the slack oauth endpoint")) 92 } 93 94 _, err = c.WriteString(fmt.Sprintf("Authentification was succesfull!\nPlease use the following token in the helm values for slackToken : %s", oResp.AccessToken)) 95 return err 96 } 97 }