Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 32bada3

Browse files
committed
oidc client auth provider: cache OpenID Connect clients to prevent reinitialization
1 parent 55f13b5 commit 32bada3

1 file changed

Lines changed: 80 additions & 41 deletions

File tree

plugin/pkg/client/auth/oidc/oidc.go

Lines changed: 80 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"net/http"
2424
"strings"
25+
"sync"
2526
"time"
2627

2728
"github.com/coreos/go-oidc/jose"
@@ -44,19 +45,53 @@ const (
4445
cfgRefreshToken = "refresh-token"
4546
)
4647

48+
func init() {
49+
if err := restclient.RegisterAuthProviderPlugin("oidc", newOIDCAuthProvider); err != nil {
50+
glog.Fatalf("Failed to register oidc auth plugin: %v", err)
51+
}
52+
}
53+
4754
var (
4855
backoff = wait.Backoff{
4956
Duration: 1 * time.Second,
5057
Factor: 2,
5158
Jitter: .1,
5259
Steps: 5,
5360
}
61+
cache = clientCache{cache: make(map[cacheKey]*oidc.Client)}
5462
)
5563

56-
func init() {
57-
if err := restclient.RegisterAuthProviderPlugin("oidc", newOIDCAuthProvider); err != nil {
58-
glog.Fatalf("Failed to register oidc auth plugin: %v", err)
59-
}
64+
// Like TLS transports, keep a cache of OIDC clients indexed by issuer URL.
65+
type clientCache struct {
66+
mu sync.RWMutex
67+
cache map[cacheKey]*oidc.Client
68+
}
69+
70+
type cacheKey struct {
71+
// Canonical issuer URL string of the provider.
72+
issuerURL string
73+
74+
// TODO(ericchiang): github.com/coreos/go-oidc/oidc can't create a client without
75+
// associating a client ID and secret. When we switch to the new go-oidc, we can
76+
// switch this key to only use the issuer URL.
77+
clientID string
78+
clientSecret string
79+
80+
// Don't use CA as cache key because we only add a cache entry if we can connect
81+
// to the issuer in the first place. A valid CA is a prerequisite.
82+
}
83+
84+
func (c *clientCache) getClient(issuer, clientID, clientSecret string) (*oidc.Client, bool) {
85+
c.mu.RLock()
86+
defer c.mu.RUnlock()
87+
client, ok := c.cache[cacheKey{issuer, clientID, clientSecret}]
88+
return client, ok
89+
}
90+
91+
func (c *clientCache) setClient(issuer, clientID, clientSecret string, client *oidc.Client) {
92+
c.mu.Lock()
93+
defer c.mu.Unlock()
94+
c.cache[cacheKey{issuer, clientID, clientSecret}] = client
6095
}
6196

6297
func newOIDCAuthProvider(_ string, cfg map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) {
@@ -75,57 +110,61 @@ func newOIDCAuthProvider(_ string, cfg map[string]string, persister restclient.A
75110
return nil, fmt.Errorf("Must provide %s", cfgClientSecret)
76111
}
77112

78-
var certAuthData []byte
79-
var err error
80-
if cfg[cfgCertificateAuthorityData] != "" {
81-
certAuthData, err = base64.StdEncoding.DecodeString(cfg[cfgCertificateAuthorityData])
82-
if err != nil {
83-
return nil, err
113+
client, ok := cache.getClient(issuer, clientID, clientSecret)
114+
if !ok {
115+
var certAuthData []byte
116+
var err error
117+
if cfg[cfgCertificateAuthorityData] != "" {
118+
certAuthData, err = base64.StdEncoding.DecodeString(cfg[cfgCertificateAuthorityData])
119+
if err != nil {
120+
return nil, err
121+
}
84122
}
85-
}
86-
87-
clientConfig := restclient.Config{
88-
TLSClientConfig: restclient.TLSClientConfig{
89-
CAFile: cfg[cfgCertificateAuthority],
90-
CAData: certAuthData,
91-
},
92-
}
93123

94-
trans, err := restclient.TransportFor(&clientConfig)
95-
if err != nil {
96-
return nil, err
97-
}
98-
hc := &http.Client{Transport: trans}
124+
clientConfig := restclient.Config{
125+
TLSClientConfig: restclient.TLSClientConfig{
126+
CAFile: cfg[cfgCertificateAuthority],
127+
CAData: certAuthData,
128+
},
129+
}
99130

100-
providerCfg, err := oidc.FetchProviderConfig(hc, issuer)
101-
if err != nil {
102-
return nil, fmt.Errorf("error fetching provider config: %v", err)
103-
}
131+
trans, err := restclient.TransportFor(&clientConfig)
132+
if err != nil {
133+
return nil, err
134+
}
135+
hc := &http.Client{Transport: trans}
104136

105-
scopes := strings.Split(cfg[cfgExtraScopes], ",")
106-
oidcCfg := oidc.ClientConfig{
107-
HTTPClient: hc,
108-
Credentials: oidc.ClientCredentials{
109-
ID: clientID,
110-
Secret: clientSecret,
111-
},
112-
ProviderConfig: providerCfg,
113-
Scope: append(scopes, oidc.DefaultScope...),
114-
}
137+
providerCfg, err := oidc.FetchProviderConfig(hc, issuer)
138+
if err != nil {
139+
return nil, fmt.Errorf("error fetching provider config: %v", err)
140+
}
115141

116-
client, err := oidc.NewClient(oidcCfg)
117-
if err != nil {
118-
return nil, fmt.Errorf("error creating OIDC Client: %v", err)
142+
scopes := strings.Split(cfg[cfgExtraScopes], ",")
143+
oidcCfg := oidc.ClientConfig{
144+
HTTPClient: hc,
145+
Credentials: oidc.ClientCredentials{
146+
ID: clientID,
147+
Secret: clientSecret,
148+
},
149+
ProviderConfig: providerCfg,
150+
Scope: append(scopes, oidc.DefaultScope...),
151+
}
152+
client, err = oidc.NewClient(oidcCfg)
153+
if err != nil {
154+
return nil, fmt.Errorf("error creating OIDC Client: %v", err)
155+
}
156+
cache.setClient(issuer, clientID, clientSecret, client)
119157
}
120158

121159
oClient := &oidcClient{client}
122160

123161
var initialIDToken jose.JWT
124162
if cfg[cfgIDToken] != "" {
125-
initialIDToken, err = jose.ParseJWT(cfg[cfgIDToken])
163+
idToken, err := jose.ParseJWT(cfg[cfgIDToken])
126164
if err != nil {
127165
return nil, err
128166
}
167+
initialIDToken = idToken
129168
}
130169

131170
return &oidcAuthProvider{

0 commit comments

Comments
 (0)