mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 16:15:42 -06:00
OAuth: Fix token refresh failure when custom SSL settings are configured for OAuth provider (#27523)
OAuth token refresh fails when custom SSL settings are configured for oauth provider. These changes makes sure that custom SSL settings are applied for HTTP client before refreshing token. Fixes #27514
This commit is contained in:
parent
5d11d8faa3
commit
19caa100dc
@ -4,13 +4,10 @@ import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
@ -116,46 +113,14 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
return
|
||||
}
|
||||
|
||||
// handle callback
|
||||
tr := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: setting.OAuthService.OAuthInfos[name].TlsSkipVerify,
|
||||
},
|
||||
}
|
||||
oauthClient := &http.Client{
|
||||
Transport: tr,
|
||||
}
|
||||
|
||||
if setting.OAuthService.OAuthInfos[name].TlsClientCert != "" || setting.OAuthService.OAuthInfos[name].TlsClientKey != "" {
|
||||
cert, err := tls.LoadX509KeyPair(setting.OAuthService.OAuthInfos[name].TlsClientCert, setting.OAuthService.OAuthInfos[name].TlsClientKey)
|
||||
if err != nil {
|
||||
ctx.Logger.Error("Failed to setup TlsClientCert", "oauth", name, "error", err)
|
||||
hs.handleOAuthLoginError(ctx, loginInfo, LoginError{
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "login.OAuthLogin(Failed to setup TlsClientCert)",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
tr.TLSClientConfig.Certificates = append(tr.TLSClientConfig.Certificates, cert)
|
||||
}
|
||||
|
||||
if setting.OAuthService.OAuthInfos[name].TlsClientCa != "" {
|
||||
caCert, err := ioutil.ReadFile(setting.OAuthService.OAuthInfos[name].TlsClientCa)
|
||||
if err != nil {
|
||||
ctx.Logger.Error("Failed to setup TlsClientCa", "oauth", name, "error", err)
|
||||
hs.handleOAuthLoginError(ctx, loginInfo, LoginError{
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "login.OAuthLogin(Failed to setup TlsClientCa)",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
tr.TLSClientConfig.RootCAs = caCertPool
|
||||
oauthClient, err := social.GetOAuthHttpClient(name)
|
||||
if err != nil {
|
||||
ctx.Logger.Error("Failed to create OAuth http client", "error", err)
|
||||
hs.handleOAuthLoginError(ctx, loginInfo, LoginError{
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "login.OAuthLogin(" + err.Error() + ")",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
oauthCtx := context.WithValue(context.Background(), oauth2.HTTPClient, oauthClient)
|
||||
|
@ -2,6 +2,7 @@ package pluginproxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@ -311,10 +312,10 @@ func addOAuthPassThruAuth(c *models.ReqContext, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
provider := authInfoQuery.Result.AuthModule
|
||||
connect, ok := social.SocialMap[strings.TrimPrefix(provider, "oauth_")] // The socialMap keys don't have "oauth_" prefix, but everywhere else in the system does
|
||||
if !ok {
|
||||
logger.Error("Failed to find oauth provider with given name", "provider", provider)
|
||||
authProvider := authInfoQuery.Result.AuthModule
|
||||
connect, err := social.GetConnector(authProvider)
|
||||
if err != nil {
|
||||
logger.Error("Failed to get OAuth connector", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -324,8 +325,16 @@ func addOAuthPassThruAuth(c *models.ReqContext, req *http.Request) {
|
||||
RefreshToken: authInfoQuery.Result.OAuthRefreshToken,
|
||||
TokenType: authInfoQuery.Result.OAuthTokenType,
|
||||
}
|
||||
|
||||
client, err := social.GetOAuthHttpClient(authProvider)
|
||||
if err != nil {
|
||||
logger.Error("Failed to create OAuth http client", "error", err)
|
||||
return
|
||||
}
|
||||
oauthctx := context.WithValue(c.Req.Context(), oauth2.HTTPClient, client)
|
||||
|
||||
// TokenSource handles refreshing the token if it has expired
|
||||
token, err := connect.TokenSource(c.Req.Context(), persistedToken).Token()
|
||||
token, err := connect.TokenSource(oauthctx, persistedToken).Token()
|
||||
if err != nil {
|
||||
logger.Error("Failed to retrieve access token from OAuth provider", "provider", authInfoQuery.Result.AuthModule, "userid", c.UserId, "username", c.Login, "error", err)
|
||||
return
|
||||
|
@ -383,6 +383,9 @@ func TestDSRouteRule(t *testing.T) {
|
||||
Config: &oauth2.Config{},
|
||||
},
|
||||
}
|
||||
setting.OAuthService = &setting.OAuther{}
|
||||
setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo)
|
||||
setting.OAuthService.OAuthInfos["generic_oauth"] = &setting.OAuthInfo{}
|
||||
|
||||
bus.AddHandler("test", func(query *models.GetAuthInfoQuery) error {
|
||||
query.Result = &models.UserAuth{
|
||||
|
@ -1,6 +1,10 @@
|
||||
package social
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@ -13,6 +17,10 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
var (
|
||||
logger = log.New("social")
|
||||
)
|
||||
|
||||
type BasicUserInfo struct {
|
||||
Id string
|
||||
Name string
|
||||
@ -225,3 +233,58 @@ var GetOAuthProviders = func(cfg *setting.Cfg) map[string]bool {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func GetOAuthHttpClient(name string) (*http.Client, error) {
|
||||
if setting.OAuthService == nil {
|
||||
return nil, fmt.Errorf("OAuth not enabled")
|
||||
}
|
||||
// The socialMap keys don't have "oauth_" prefix, but everywhere else in the system does
|
||||
name = strings.TrimPrefix(name, "oauth_")
|
||||
info, ok := setting.OAuthService.OAuthInfos[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Could not find %s in OAuth Settings", name)
|
||||
}
|
||||
|
||||
// handle call back
|
||||
tr := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: info.TlsSkipVerify,
|
||||
},
|
||||
}
|
||||
oauthClient := &http.Client{
|
||||
Transport: tr,
|
||||
}
|
||||
|
||||
if info.TlsClientCert != "" || info.TlsClientKey != "" {
|
||||
cert, err := tls.LoadX509KeyPair(info.TlsClientCert, info.TlsClientKey)
|
||||
logger.Error("Failed to setup TlsClientCert", "oauth", name, "error", err)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to setup TlsClientCert")
|
||||
}
|
||||
|
||||
tr.TLSClientConfig.Certificates = append(tr.TLSClientConfig.Certificates, cert)
|
||||
}
|
||||
|
||||
if info.TlsClientCa != "" {
|
||||
caCert, err := ioutil.ReadFile(info.TlsClientCa)
|
||||
if err != nil {
|
||||
logger.Error("Failed to setup TlsClientCa", "oauth", name, "error", err)
|
||||
return nil, fmt.Errorf("Failed to setup TlsClientCa")
|
||||
}
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
tr.TLSClientConfig.RootCAs = caCertPool
|
||||
}
|
||||
return oauthClient, nil
|
||||
}
|
||||
|
||||
func GetConnector(name string) (SocialConnector, error) {
|
||||
// The socialMap keys don't have "oauth_" prefix, but everywhere else in the system does
|
||||
provider := strings.TrimPrefix(name, "oauth_")
|
||||
connector, ok := SocialMap[provider]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Failed to find oauth provider for %s", name)
|
||||
}
|
||||
return connector, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user