Merge pull request #210 from ericchiang/update_go_oidc

Godeps: update coreos/go-oidc to include OIDC race condition fixes
This commit is contained in:
Eric Chiang 2015-12-15 09:46:26 -08:00
commit bf13c3bc37
3 changed files with 53 additions and 31 deletions

10
Godeps/Godeps.json generated
View file

@ -21,23 +21,23 @@
}, },
{ {
"ImportPath": "github.com/coreos/go-oidc/http", "ImportPath": "github.com/coreos/go-oidc/http",
"Rev": "faf70c34f9c411f234eb96d23c518c087cd96d79" "Rev": "024cdeee09d02fb439eb55bc422e582ac115615b"
}, },
{ {
"ImportPath": "github.com/coreos/go-oidc/jose", "ImportPath": "github.com/coreos/go-oidc/jose",
"Rev": "faf70c34f9c411f234eb96d23c518c087cd96d79" "Rev": "024cdeee09d02fb439eb55bc422e582ac115615b"
}, },
{ {
"ImportPath": "github.com/coreos/go-oidc/key", "ImportPath": "github.com/coreos/go-oidc/key",
"Rev": "faf70c34f9c411f234eb96d23c518c087cd96d79" "Rev": "024cdeee09d02fb439eb55bc422e582ac115615b"
}, },
{ {
"ImportPath": "github.com/coreos/go-oidc/oauth2", "ImportPath": "github.com/coreos/go-oidc/oauth2",
"Rev": "faf70c34f9c411f234eb96d23c518c087cd96d79" "Rev": "024cdeee09d02fb439eb55bc422e582ac115615b"
}, },
{ {
"ImportPath": "github.com/coreos/go-oidc/oidc", "ImportPath": "github.com/coreos/go-oidc/oidc",
"Rev": "faf70c34f9c411f234eb96d23c518c087cd96d79" "Rev": "024cdeee09d02fb439eb55bc422e582ac115615b"
}, },
{ {
"ImportPath": "github.com/coreos/pkg/capnslog", "ImportPath": "github.com/coreos/pkg/capnslog",

View file

@ -78,7 +78,7 @@ func NewClient(cfg ClientConfig) (*Client, error) {
httpClient: cfg.HTTPClient, httpClient: cfg.HTTPClient,
scope: cfg.Scope, scope: cfg.Scope,
redirectURL: ru.String(), redirectURL: ru.String(),
providerConfig: cfg.ProviderConfig, providerConfig: newProviderConfigRepo(cfg.ProviderConfig),
keySet: cfg.KeySet, keySet: cfg.KeySet,
} }
@ -96,7 +96,7 @@ func NewClient(cfg ClientConfig) (*Client, error) {
type Client struct { type Client struct {
httpClient phttp.Client httpClient phttp.Client
providerConfig ProviderConfig providerConfig *providerConfigRepo
credentials ClientCredentials credentials ClientCredentials
redirectURL string redirectURL string
scope []string scope []string
@ -106,14 +106,39 @@ type Client struct {
lastKeySetSync time.Time lastKeySetSync time.Time
} }
type providerConfigRepo struct {
mu sync.RWMutex
config ProviderConfig // do not access directly, use Get()
}
func newProviderConfigRepo(pc ProviderConfig) *providerConfigRepo {
return &providerConfigRepo{sync.RWMutex{}, pc}
}
// returns an error to implement ProviderConfigSetter
func (r *providerConfigRepo) Set(cfg ProviderConfig) error {
r.mu.Lock()
defer r.mu.Unlock()
r.config = cfg
return nil
}
func (r *providerConfigRepo) Get() ProviderConfig {
r.mu.RLock()
defer r.mu.RUnlock()
return r.config
}
func (c *Client) Healthy() error { func (c *Client) Healthy() error {
now := time.Now().UTC() now := time.Now().UTC()
if c.providerConfig.Empty() { cfg := c.providerConfig.Get()
if cfg.Empty() {
return errors.New("oidc client provider config empty") return errors.New("oidc client provider config empty")
} }
if !c.providerConfig.ExpiresAt.IsZero() && c.providerConfig.ExpiresAt.Before(now) { if !cfg.ExpiresAt.IsZero() && cfg.ExpiresAt.Before(now) {
return errors.New("oidc client provider config expired") return errors.New("oidc client provider config expired")
} }
@ -121,7 +146,8 @@ func (c *Client) Healthy() error {
} }
func (c *Client) OAuthClient() (*oauth2.Client, error) { func (c *Client) OAuthClient() (*oauth2.Client, error) {
authMethod, err := c.chooseAuthMethod() cfg := c.providerConfig.Get()
authMethod, err := chooseAuthMethod(cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -129,8 +155,8 @@ func (c *Client) OAuthClient() (*oauth2.Client, error) {
ocfg := oauth2.Config{ ocfg := oauth2.Config{
Credentials: oauth2.ClientCredentials(c.credentials), Credentials: oauth2.ClientCredentials(c.credentials),
RedirectURL: c.redirectURL, RedirectURL: c.redirectURL,
AuthURL: c.providerConfig.AuthEndpoint, AuthURL: cfg.AuthEndpoint,
TokenURL: c.providerConfig.TokenEndpoint, TokenURL: cfg.TokenEndpoint,
Scope: c.scope, Scope: c.scope,
AuthMethod: authMethod, AuthMethod: authMethod,
} }
@ -138,12 +164,12 @@ func (c *Client) OAuthClient() (*oauth2.Client, error) {
return oauth2.NewClient(c.httpClient, ocfg) return oauth2.NewClient(c.httpClient, ocfg)
} }
func (c *Client) chooseAuthMethod() (string, error) { func chooseAuthMethod(cfg ProviderConfig) (string, error) {
if len(c.providerConfig.TokenEndpointAuthMethodsSupported) == 0 { if len(cfg.TokenEndpointAuthMethodsSupported) == 0 {
return oauth2.AuthMethodClientSecretBasic, nil return oauth2.AuthMethodClientSecretBasic, nil
} }
for _, authMethod := range c.providerConfig.TokenEndpointAuthMethodsSupported { for _, authMethod := range cfg.TokenEndpointAuthMethodsSupported {
if _, ok := supportedAuthMethods[authMethod]; ok { if _, ok := supportedAuthMethods[authMethod]; ok {
return authMethod, nil return authMethod, nil
} }
@ -153,9 +179,8 @@ func (c *Client) chooseAuthMethod() (string, error) {
} }
func (c *Client) SyncProviderConfig(discoveryURL string) chan struct{} { func (c *Client) SyncProviderConfig(discoveryURL string) chan struct{} {
rp := &providerConfigRepo{c}
r := NewHTTPProviderConfigGetter(c.httpClient, discoveryURL) r := NewHTTPProviderConfigGetter(c.httpClient, discoveryURL)
return NewProviderConfigSyncer(r, rp).Run() return NewProviderConfigSyncer(r, c.providerConfig).Run()
} }
func (c *Client) maybeSyncKeys() error { func (c *Client) maybeSyncKeys() error {
@ -178,7 +203,8 @@ func (c *Client) maybeSyncKeys() error {
return nil return nil
} }
r := NewRemotePublicKeyRepo(c.httpClient, c.providerConfig.KeysEndpoint) cfg := c.providerConfig.Get()
r := NewRemotePublicKeyRepo(c.httpClient, cfg.KeysEndpoint)
w := &clientKeyRepo{client: c} w := &clientKeyRepo{client: c}
_, err := key.Sync(r, w) _, err := key.Sync(r, w)
c.lastKeySetSync = time.Now().UTC() c.lastKeySetSync = time.Now().UTC()
@ -186,15 +212,6 @@ func (c *Client) maybeSyncKeys() error {
return err return err
} }
type providerConfigRepo struct {
client *Client
}
func (r *providerConfigRepo) Set(cfg ProviderConfig) error {
r.client.providerConfig = cfg
return nil
}
type clientKeyRepo struct { type clientKeyRepo struct {
client *Client client *Client
} }
@ -209,7 +226,9 @@ func (r *clientKeyRepo) Set(ks key.KeySet) error {
} }
func (c *Client) ClientCredsToken(scope []string) (jose.JWT, error) { func (c *Client) ClientCredsToken(scope []string) (jose.JWT, error) {
if !c.providerConfig.SupportsGrantType(oauth2.GrantTypeClientCreds) { cfg := c.providerConfig.Get()
if !cfg.SupportsGrantType(oauth2.GrantTypeClientCreds) {
return jose.JWT{}, fmt.Errorf("%v grant type is not supported", oauth2.GrantTypeClientCreds) return jose.JWT{}, fmt.Errorf("%v grant type is not supported", oauth2.GrantTypeClientCreds)
} }
@ -280,7 +299,7 @@ func (c *Client) VerifyJWT(jwt jose.JWT) error {
} }
v := NewJWTVerifier( v := NewJWTVerifier(
c.providerConfig.Issuer, c.providerConfig.Get().Issuer,
c.credentials.ID, c.credentials.ID,
c.maybeSyncKeys, keysFunc) c.maybeSyncKeys, keysFunc)

View file

@ -25,6 +25,9 @@ const (
discoveryConfigPath = "/.well-known/openid-configuration" discoveryConfigPath = "/.well-known/openid-configuration"
) )
// internally configurable for tests
var minimumProviderConfigSyncInterval = MinimumProviderConfigSyncInterval
type ProviderConfig struct { type ProviderConfig struct {
Issuer string `json:"issuer"` Issuer string `json:"issuer"`
AuthEndpoint string `json:"authorization_endpoint"` AuthEndpoint string `json:"authorization_endpoint"`
@ -172,8 +175,8 @@ func nextSyncAfter(exp time.Time, clock clockwork.Clock) time.Duration {
t := exp.Sub(clock.Now()) / 2 t := exp.Sub(clock.Now()) / 2
if t > MaximumProviderConfigSyncInterval { if t > MaximumProviderConfigSyncInterval {
t = MaximumProviderConfigSyncInterval t = MaximumProviderConfigSyncInterval
} else if t < MinimumProviderConfigSyncInterval { } else if t < minimumProviderConfigSyncInterval {
t = MinimumProviderConfigSyncInterval t = minimumProviderConfigSyncInterval
} }
return t return t