Skip to content

Commit 2e2cf96

Browse files
authored
Merge pull request #69 from ConductorOne/fix_1_hour_secret_expire_issue
baton-github: refresh app token once it expires
2 parents 7d06df0 + bbceef3 commit 2e2cf96

File tree

1 file changed

+61
-17
lines changed

1 file changed

+61
-17
lines changed

pkg/connector/connector.go

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,14 @@ func (gh *GitHub) validateAppCredentials(ctx context.Context) (annotations.Annot
176176
}
177177

178178
// newGitHubClient returns a new GitHub API client authenticated with an access token via oauth2.
179-
func newGitHubClient(ctx context.Context, instanceURL string, accessToken string) (*github.Client, error) {
179+
func newGitHubClient(ctx context.Context, instanceURL string, ts oauth2.TokenSource) (*github.Client, error) {
180180
httpClient, err := uhttp.NewClient(ctx, uhttp.WithLogger(true, ctxzap.Extract(ctx)))
181181
if err != nil {
182182
return nil, err
183183
}
184184

185185
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
186186

187-
ts := oauth2.StaticTokenSource(
188-
&oauth2.Token{AccessToken: accessToken},
189-
)
190187
tc := oauth2.NewClient(ctx, ts)
191188
gc := github.NewClient(tc)
192189

@@ -205,13 +202,23 @@ func New(ctx context.Context, ghc *cfg.Github, appKey string) (*GitHub, error) {
205202
return nil, err
206203
}
207204

208-
var appClient *github.Client
205+
var (
206+
appClient *github.Client
207+
ts = oauth2.StaticTokenSource(
208+
&oauth2.Token{AccessToken: patToken},
209+
)
210+
)
209211
if jwttoken != "" {
210212
if len(ghc.Orgs) != 1 {
211213
return nil, fmt.Errorf("github-connector: only one org should be specified")
212214
}
213215

214-
appClient, err = newGitHubClient(ctx, ghc.InstanceUrl, jwttoken)
216+
appClient, err = newGitHubClient(ctx,
217+
ghc.InstanceUrl,
218+
oauth2.StaticTokenSource(
219+
&oauth2.Token{AccessToken: jwttoken},
220+
),
221+
)
215222
if err != nil {
216223
return nil, err
217224
}
@@ -224,14 +231,26 @@ func New(ctx context.Context, ghc *cfg.Github, appKey string) (*GitHub, error) {
224231
if err != nil {
225232
return nil, err
226233
}
227-
patToken = token
234+
235+
ts = oauth2.ReuseTokenSource(
236+
&oauth2.Token{
237+
AccessToken: token.GetToken(),
238+
Expiry: token.GetExpiresAt().Time,
239+
},
240+
&appTokenRefresher{
241+
ctx: ctx,
242+
instanceURL: ghc.InstanceUrl,
243+
installationID: installation.GetID(),
244+
jwttoken: jwttoken,
245+
},
246+
)
228247
}
229248

230-
client, err := newGitHubClient(ctx, ghc.InstanceUrl, patToken)
249+
client, err := newGitHubClient(ctx, ghc.InstanceUrl, ts)
231250
if err != nil {
232251
return nil, err
233252
}
234-
graphqlClient, err := newGitHubGraphqlClient(ctx, ghc.InstanceUrl, patToken)
253+
graphqlClient, err := newGitHubGraphqlClient(ctx, ghc.InstanceUrl, ts)
235254
if err != nil {
236255
return nil, err
237256
}
@@ -248,17 +267,14 @@ func New(ctx context.Context, ghc *cfg.Github, appKey string) (*GitHub, error) {
248267
return gh, nil
249268
}
250269

251-
func newGitHubGraphqlClient(ctx context.Context, instanceURL string, accessToken string) (*githubv4.Client, error) {
270+
func newGitHubGraphqlClient(ctx context.Context, instanceURL string, ts oauth2.TokenSource) (*githubv4.Client, error) {
252271
httpClient, err := uhttp.NewClient(ctx, uhttp.WithLogger(true, ctxzap.Extract(ctx)))
253272
if err != nil {
254273
return nil, err
255274
}
256275

257276
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
258277

259-
ts := oauth2.StaticTokenSource(
260-
&oauth2.Token{AccessToken: accessToken},
261-
)
262278
tc := oauth2.NewClient(ctx, ts)
263279

264280
instanceURL = strings.TrimSuffix(instanceURL, "/")
@@ -331,16 +347,44 @@ func findInstallation(ctx context.Context, c *github.Client, orgName string) (*g
331347
return installation, resp, nil
332348
}
333349

334-
func getInstallationToken(ctx context.Context, c *github.Client, id int64) (string, error) {
350+
func getInstallationToken(ctx context.Context, c *github.Client, id int64) (*github.InstallationToken, error) {
335351
token, resp, err := c.Apps.CreateInstallationToken(ctx, id, &github.InstallationTokenOptions{})
336352
if err != nil {
337-
return "", err
353+
return nil, err
338354
}
339355

340356
if resp.StatusCode != http.StatusCreated {
341357
body, _ := io.ReadAll(resp.Body)
342-
return "", fmt.Errorf("GitHub API error: %s", body)
358+
return nil, fmt.Errorf("GitHub API error: %s", body)
343359
}
344360

345-
return token.GetToken(), nil
361+
return token, nil
362+
}
363+
364+
type appTokenRefresher struct {
365+
ctx context.Context
366+
jwttoken string
367+
instanceURL string
368+
installationID int64
369+
}
370+
371+
func (r *appTokenRefresher) Token() (*oauth2.Token, error) {
372+
appClient, err := newGitHubClient(r.ctx,
373+
r.instanceURL,
374+
oauth2.StaticTokenSource(
375+
&oauth2.Token{AccessToken: r.jwttoken},
376+
),
377+
)
378+
if err != nil {
379+
return nil, err
380+
}
381+
382+
token, err := getInstallationToken(r.ctx, appClient, r.installationID)
383+
if err != nil {
384+
return nil, err
385+
}
386+
return &oauth2.Token{
387+
AccessToken: token.GetToken(),
388+
Expiry: token.GetExpiresAt().Time,
389+
}, nil
346390
}

0 commit comments

Comments
 (0)