@@ -32,9 +32,9 @@ import (
32
32
"strings"
33
33
"time"
34
34
35
- "github.com/coreos/go-oidc/oauth2"
36
35
"github.com/gravitational/trace"
37
36
"github.com/sirupsen/logrus"
37
+ "golang.org/x/oauth2"
38
38
39
39
"github.com/gravitational/teleport"
40
40
"github.com/gravitational/teleport/api/constants"
@@ -143,7 +143,7 @@ func (g *GithubConverter) UpdateGithubConnector(ctx context.Context, connector t
143
143
144
144
// CreateGithubAuthRequest creates a new request for Github OAuth2 flow
145
145
func (a * Server ) CreateGithubAuthRequest (ctx context.Context , req types.GithubAuthRequest ) (* types.GithubAuthRequest , error ) {
146
- connector , client , err := a .getGithubConnectorAndClient (ctx , req )
146
+ connector , err := a .getGithubConnector (ctx , req )
147
147
if err != nil {
148
148
return nil , trace .Wrap (err )
149
149
}
@@ -163,7 +163,10 @@ func (a *Server) CreateGithubAuthRequest(ctx context.Context, req types.GithubAu
163
163
if err != nil {
164
164
return nil , trace .Wrap (err )
165
165
}
166
- req .RedirectURL = client .AuthCodeURL (req .StateToken , "" , "" )
166
+
167
+ config := newGithubOAuth2Config (connector )
168
+
169
+ req .RedirectURL = config .AuthCodeURL (req .StateToken )
167
170
log .WithFields (logrus.Fields {teleport .ComponentKey : "github" }).Debugf (
168
171
"Redirect URL: %v." , req .RedirectURL )
169
172
req .SetExpiry (a .GetClock ().Now ().UTC ().Add (defaults .GithubAuthRequestTTL ))
@@ -487,86 +490,51 @@ func validateGithubAuthCallbackHelper(ctx context.Context, m githubManager, diag
487
490
return auth , nil
488
491
}
489
492
490
- func (a * Server ) getGithubConnectorAndClient (ctx context.Context , request types.GithubAuthRequest ) (types.GithubConnector , * oauth2. Client , error ) {
493
+ func (a * Server ) getGithubConnector (ctx context.Context , request types.GithubAuthRequest ) (types.GithubConnector , error ) {
491
494
if request .SSOTestFlow {
492
495
if request .ConnectorSpec == nil {
493
- return nil , nil , trace .BadParameter ("ConnectorSpec cannot be nil when SSOTestFlow is true" )
496
+ return nil , trace .BadParameter ("ConnectorSpec cannot be nil when SSOTestFlow is true" )
494
497
}
495
498
496
499
if request .ConnectorID == "" {
497
- return nil , nil , trace .BadParameter ("ConnectorID cannot be empty" )
500
+ return nil , trace .BadParameter ("ConnectorID cannot be empty" )
498
501
}
499
502
500
503
// stateless test flow
501
504
connector , err := services .NewGithubConnector (request .ConnectorID , * request .ConnectorSpec )
502
505
if err != nil {
503
- return nil , nil , trace .Wrap (err )
504
- }
505
-
506
- // construct client directly.
507
- config := newGithubOAuth2Config (connector )
508
- client , err := oauth2 .NewClient (http .DefaultClient , config )
509
- if err != nil {
510
- return nil , nil , trace .Wrap (err )
506
+ return nil , trace .Wrap (err )
511
507
}
512
508
513
- return connector , client , nil
509
+ return connector , nil
514
510
}
515
511
516
512
// regular execution flow
517
513
connector , err := a .GetGithubConnector (ctx , request .ConnectorID , true )
518
514
if err != nil {
519
- return nil , nil , trace .Wrap (err )
515
+ return nil , trace .Wrap (err )
520
516
}
521
517
connector , err = services .InitGithubConnector (connector )
522
518
if err != nil {
523
- return nil , nil , trace .Wrap (err )
524
- }
525
-
526
- client , err := a .getGithubOAuth2Client (connector )
527
- if err != nil {
528
- return nil , nil , trace .Wrap (err )
519
+ return nil , trace .Wrap (err )
529
520
}
530
521
531
- return connector , client , nil
522
+ return connector , nil
532
523
}
533
524
534
525
func newGithubOAuth2Config (connector types.GithubConnector ) oauth2.Config {
535
526
return oauth2.Config {
536
- Credentials : oauth2.ClientCredentials {
537
- ID : connector .GetClientID (),
538
- Secret : connector .GetClientSecret (),
527
+ ClientID : connector .GetClientID (),
528
+ ClientSecret : connector .GetClientSecret (),
529
+ RedirectURL : connector .GetRedirectURL (),
530
+ Scopes : GithubScopes ,
531
+ Endpoint : oauth2.Endpoint {
532
+ AuthURL : fmt .Sprintf ("%s/%s" , connector .GetEndpointURL (), GithubAuthPath ),
533
+ TokenURL : fmt .Sprintf ("%s/%s" , connector .GetEndpointURL (), GithubTokenPath ),
539
534
},
540
- RedirectURL : connector .GetRedirectURL (),
541
- Scope : GithubScopes ,
542
- AuthURL : fmt .Sprintf ("%s/%s" , connector .GetEndpointURL (), GithubAuthPath ),
543
- TokenURL : fmt .Sprintf ("%s/%s" , connector .GetEndpointURL (), GithubTokenPath ),
544
535
}
545
536
}
546
537
547
- func (a * Server ) getGithubOAuth2Client (connector types.GithubConnector ) (* oauth2.Client , error ) {
548
- config := newGithubOAuth2Config (connector )
549
-
550
- a .lock .Lock ()
551
- defer a .lock .Unlock ()
552
-
553
- cachedClient , ok := a .githubClients [connector .GetName ()]
554
- if ok && oauth2ConfigsEqual (cachedClient .config , config ) {
555
- return cachedClient .client , nil
556
- }
557
-
558
- delete (a .githubClients , connector .GetName ())
559
- client , err := oauth2 .NewClient (http .DefaultClient , config )
560
- if err != nil {
561
- return nil , trace .Wrap (err )
562
- }
563
- a .githubClients [connector .GetName ()] = & githubClient {
564
- client : client ,
565
- config : config ,
566
- }
567
- return client , nil
568
- }
569
-
570
538
// ValidateGithubAuthCallback validates Github auth callback redirect
571
539
func (a * Server ) validateGithubAuthCallback (ctx context.Context , diagCtx * SSODiagContext , q url.Values ) (* authclient.GithubAuthResponse , error ) {
572
540
logger := log .WithFields (logrus.Fields {teleport .ComponentKey : "github" })
@@ -584,19 +552,19 @@ func (a *Server) validateGithubAuthCallback(ctx context.Context, diagCtx *SSODia
584
552
585
553
// optional parameter: error_description
586
554
errDesc := q .Get ("error_description" )
587
- oauthErr := trace .OAuth2 (oauth2 . ErrorInvalidRequest , errParam , q )
555
+ oauthErr := trace .OAuth2 ("invalid_request" , errParam , q )
588
556
return nil , trace .WithUserMessage (oauthErr , "GitHub returned error: %v [%v]" , errDesc , errParam )
589
557
}
590
558
591
559
code := q .Get ("code" )
592
560
if code == "" {
593
- oauthErr := trace .OAuth2 (oauth2 . ErrorInvalidRequest , "code query param must be set" , q )
561
+ oauthErr := trace .OAuth2 ("invalid_request" , "code query param must be set" , q )
594
562
return nil , trace .WithUserMessage (oauthErr , "Invalid parameters received from GitHub." )
595
563
}
596
564
597
565
stateToken := q .Get ("state" )
598
566
if stateToken == "" {
599
- oauthErr := trace .OAuth2 (oauth2 . ErrorInvalidRequest , "missing state query param" , q )
567
+ oauthErr := trace .OAuth2 ("invalid_request" , "missing state query param" , q )
600
568
return nil , trace .WithUserMessage (oauthErr , "Invalid parameters received from GitHub." )
601
569
}
602
570
diagCtx .RequestID = stateToken
@@ -607,15 +575,15 @@ func (a *Server) validateGithubAuthCallback(ctx context.Context, diagCtx *SSODia
607
575
}
608
576
diagCtx .Info .TestFlow = req .SSOTestFlow
609
577
610
- connector , client , err := a .getGithubConnectorAndClient (ctx , * req )
578
+ connector , err := a .getGithubConnector (ctx , * req )
611
579
if err != nil {
612
580
return nil , trace .Wrap (err , "Failed to get GitHub connector and client." )
613
581
}
614
582
diagCtx .Info .GithubTeamsToLogins = connector .GetTeamsToLogins ()
615
583
diagCtx .Info .GithubTeamsToRoles = connector .GetTeamsToRoles ()
616
584
logger .Debugf ("Connector %q teams to logins: %v, roles: %v" , connector .GetName (), connector .GetTeamsToLogins (), connector .GetTeamsToRoles ())
617
585
618
- userResp , teamsResp , err := a .getGithubUserAndTeams (ctx , connector , code , client , diagCtx , logger )
586
+ userResp , teamsResp , err := a .getGithubUserAndTeams (ctx , connector , code , diagCtx , logger )
619
587
if err != nil {
620
588
return nil , trace .Wrap (err )
621
589
}
@@ -752,7 +720,6 @@ func (a *Server) getGithubUserAndTeams(
752
720
ctx context.Context ,
753
721
connector types.GithubConnector ,
754
722
code string ,
755
- client * oauth2.Client ,
756
723
diagCtx * SSODiagContext ,
757
724
logger * logrus.Entry ,
758
725
) (* GithubUserResponse , []GithubTeamResponse , error ) {
@@ -762,20 +729,26 @@ func (a *Server) getGithubUserAndTeams(
762
729
return a .GithubUserAndTeamsOverride ()
763
730
}
764
731
732
+ config := newGithubOAuth2Config (connector )
733
+
765
734
// exchange the authorization code received by the callback for an access token
766
- token , err := client . RequestToken ( oauth2 . GrantTypeAuthCode , code )
735
+ token , err := config . Exchange ( ctx , code )
767
736
if err != nil {
768
737
return nil , nil , trace .Wrap (err , "Requesting GitHub OAuth2 token failed." )
769
738
}
770
739
740
+ scope , ok := token .Extra ("scope" ).(string )
741
+ if ! ok {
742
+ return nil , nil , trace .BadParameter ("missing or invalid scope found in GitHub OAuth2 token" )
743
+ }
771
744
diagCtx .Info .GithubTokenInfo = & types.GithubTokenInfo {
772
745
TokenType : token .TokenType ,
773
- Expires : int64 ( token .Expires ) ,
774
- Scope : token . Scope ,
746
+ Expires : token .ExpiresIn ,
747
+ Scope : scope ,
775
748
}
776
749
777
750
logger .Debugf ("Obtained OAuth2 token: Type=%v Expires=%v Scope=%v." ,
778
- token .TokenType , token .Expires , token . Scope )
751
+ token .TokenType , token .ExpiresIn , scope )
779
752
780
753
// Get the Github organizations the user is a member of so we don't
781
754
// make unnecessary API requests
0 commit comments