()
| 139 | } |
| 140 | |
| 141 | func (tp *TokenProvider) refreshToken() errors.Error { |
| 142 | if tp.refreshFn != nil { |
| 143 | return tp.refreshFn(tp) |
| 144 | } |
| 145 | tp.logger.Info("Refreshing GitHub token for connection %d", tp.conn.ID) |
| 146 | |
| 147 | data := map[string]string{ |
| 148 | "refresh_token": tp.conn.RefreshToken, |
| 149 | "grant_type": "refresh_token", |
| 150 | "client_id": tp.conn.AppId, |
| 151 | "client_secret": tp.conn.SecretKey, |
| 152 | } |
| 153 | jsonData, _ := json.Marshal(data) |
| 154 | |
| 155 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) |
| 156 | defer cancel() |
| 157 | |
| 158 | req, err := http.NewRequestWithContext(ctx, "POST", tp.refreshURL, bytes.NewBuffer(jsonData)) |
| 159 | if err != nil { |
| 160 | return errors.Convert(err) |
| 161 | } |
| 162 | req.Header.Set("Content-Type", "application/json") |
| 163 | req.Header.Set("Accept", "application/json") |
| 164 | |
| 165 | resp, err := tp.httpClient.Do(req) |
| 166 | if err != nil { |
| 167 | return errors.Convert(err) |
| 168 | } |
| 169 | defer resp.Body.Close() |
| 170 | |
| 171 | body, err := io.ReadAll(resp.Body) |
| 172 | if err != nil { |
| 173 | return errors.Convert(err) |
| 174 | } |
| 175 | |
| 176 | if resp.StatusCode != http.StatusOK { |
| 177 | // Log the response body to aid in debugging token refresh failures. |
| 178 | if tp.logger != nil { |
| 179 | tp.logger.Error(nil, "failed to refresh token from GitHub, status=%d, body=%s", resp.StatusCode, string(body)) |
| 180 | } |
| 181 | return errors.Default.New(fmt.Sprintf("failed to refresh token: %d, body: %s", resp.StatusCode, string(body))) |
| 182 | } |
| 183 | var result struct { |
| 184 | AccessToken string `json:"access_token"` |
| 185 | RefreshToken string `json:"refresh_token"` |
| 186 | ExpiresIn int `json:"expires_in"` |
| 187 | RefreshTokenExpiresIn int `json:"refresh_token_expires_in"` |
| 188 | } |
| 189 | if err := json.Unmarshal(body, &result); err != nil { |
| 190 | return errors.Convert(err) |
| 191 | } |
| 192 | |
| 193 | if result.AccessToken == "" { |
| 194 | bodyStr := string(body) |
| 195 | const maxBodySnippet = 512 |
| 196 | if len(bodyStr) > maxBodySnippet { |
| 197 | bodyStr = bodyStr[:maxBodySnippet] + "…" |
| 198 | } |
no test coverage detected