diff --git a/key/doc.go b/key/doc.go index 936eec74..c5ecc491 100644 --- a/key/doc.go +++ b/key/doc.go @@ -1,2 +1,2 @@ -// Package key is DEPRECATED. Use github.com/coreos/go-oidc instead. +// Package key is DEPRECATED. Use github.com/gambol99/go-oidc instead. package key diff --git a/key/key.go b/key/key.go index 208c1fc1..034d6363 100644 --- a/key/key.go +++ b/key/key.go @@ -8,7 +8,7 @@ import ( "io" "time" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) func NewPublicKey(jwk jose.JWK) *PublicKey { diff --git a/key/key_test.go b/key/key_test.go index 04d58214..2e75982f 100644 --- a/key/key_test.go +++ b/key/key_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) func TestPrivateRSAKeyJWK(t *testing.T) { diff --git a/key/manager.go b/key/manager.go index 476ab6a8..d5f1b203 100644 --- a/key/manager.go +++ b/key/manager.go @@ -6,8 +6,8 @@ import ( "github.com/jonboulle/clockwork" - "github.com/coreos/go-oidc/jose" "github.com/coreos/pkg/health" + "github.com/gambol99/go-oidc/jose" ) type PrivateKeyManager interface { diff --git a/key/manager_test.go b/key/manager_test.go index f3c753e7..c0ed0867 100644 --- a/key/manager_test.go +++ b/key/manager_test.go @@ -10,7 +10,7 @@ import ( "github.com/jonboulle/clockwork" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) var ( diff --git a/oauth2/oauth2.go b/oauth2/oauth2.go index 72d1d671..fdb69abb 100644 --- a/oauth2/oauth2.go +++ b/oauth2/oauth2.go @@ -12,7 +12,7 @@ import ( "strconv" "strings" - phttp "github.com/coreos/go-oidc/http" + phttp "github.com/gambol99/go-oidc/http" ) // ResponseTypesEqual compares two response_type values. If either diff --git a/oauth2/oauth2_test.go b/oauth2/oauth2_test.go index 0267a84f..ab8c43b9 100644 --- a/oauth2/oauth2_test.go +++ b/oauth2/oauth2_test.go @@ -10,7 +10,7 @@ import ( "strings" "testing" - phttp "github.com/coreos/go-oidc/http" + phttp "github.com/gambol99/go-oidc/http" ) func TestResponseTypesEqual(t *testing.T) { diff --git a/oidc/client.go b/oidc/client.go index 7a3cb40f..063461fa 100644 --- a/oidc/client.go +++ b/oidc/client.go @@ -10,10 +10,10 @@ import ( "sync" "time" - phttp "github.com/coreos/go-oidc/http" - "github.com/coreos/go-oidc/jose" - "github.com/coreos/go-oidc/key" - "github.com/coreos/go-oidc/oauth2" + phttp "github.com/gambol99/go-oidc/http" + "github.com/gambol99/go-oidc/jose" + "github.com/gambol99/go-oidc/key" + "github.com/gambol99/go-oidc/oauth2" ) const ( @@ -408,7 +408,7 @@ func emailsToStrings(addrs []mail.Address) []string { // // NOTE(ericchiang): For development purposes Valid does not mandate 'https' for // URLs fields where the OIDC spec requires it. This may change in future releases -// of this package. See: https://github.com/coreos/go-oidc/issues/34 +// of this package. See: https://github.com/gambol99/go-oidc/issues/34 func (m *ClientMetadata) Valid() error { if len(m.RedirectURIs) == 0 { return errors.New("zero redirect URLs") @@ -556,12 +556,13 @@ func (c *ClientRegistrationResponse) UnmarshalJSON(data []byte) error { } type ClientConfig struct { - HTTPClient phttp.Client - Credentials ClientCredentials - Scope []string - RedirectURL string - ProviderConfig ProviderConfig - KeySet key.PublicKeySet + Credentials ClientCredentials + HTTPClient phttp.Client + KeySet key.PublicKeySet + ProviderConfig ProviderConfig + RedirectURL string + Scope []string + SkipClientIDCheck bool } func NewClient(cfg ClientConfig) (*Client, error) { @@ -579,6 +580,7 @@ func NewClient(cfg ClientConfig) (*Client, error) { redirectURL: ru.String(), providerConfig: newProviderConfigRepo(cfg.ProviderConfig), keySet: cfg.KeySet, + skipClientID: cfg.SkipClientIDCheck, } if c.httpClient == nil { @@ -593,19 +595,21 @@ func NewClient(cfg ClientConfig) (*Client, error) { return &c, nil } +// Client is the oidc client type Client struct { - httpClient phttp.Client - providerConfig *providerConfigRepo - credentials ClientCredentials - redirectURL string - scope []string - keySet key.PublicKeySet - providerSyncer *ProviderConfigSyncer - + credentials ClientCredentials + httpClient phttp.Client + keySet key.PublicKeySet keySetSyncMutex sync.RWMutex lastKeySetSync time.Time + providerConfig *providerConfigRepo + providerSyncer *ProviderConfigSyncer + redirectURL string + scope []string + skipClientID bool } +// Healthy checks the provider is healthy func (c *Client) Healthy() error { now := time.Now().UTC() @@ -622,6 +626,7 @@ func (c *Client) Healthy() error { return nil } +// OAuthClient returns a oauth2 client func (c *Client) OAuthClient() (*oauth2.Client, error) { cfg := c.providerConfig.Get() authMethod, err := chooseAuthMethod(cfg) @@ -771,10 +776,11 @@ func (c *Client) RefreshToken(refreshToken string) (jose.JWT, error) { return jwt, c.VerifyJWT(jwt) } +// VerifyJWT verifies the JWT tokens func (c *Client) VerifyJWT(jwt jose.JWT) error { var keysFunc func() []key.PublicKey - if kID, ok := jwt.KeyID(); ok { - keysFunc = c.keysFuncWithID(kID) + if kid, ok := jwt.KeyID(); ok { + keysFunc = c.keysFuncWithID(kid) } else { keysFunc = c.keysFuncAll() } @@ -782,7 +788,9 @@ func (c *Client) VerifyJWT(jwt jose.JWT) error { v := NewJWTVerifier( c.providerConfig.Get().Issuer.String(), c.credentials.ID, - c.maybeSyncKeys, keysFunc) + c.maybeSyncKeys, + keysFunc, + c.skipClientID) return v.Verify(jwt) } diff --git a/oidc/client_race_test.go b/oidc/client_race_test.go index 315eaf24..303b0031 100644 --- a/oidc/client_race_test.go +++ b/oidc/client_race_test.go @@ -59,7 +59,7 @@ func TestProviderSyncRace(t *testing.T) { } if !cli.providerConfig.Get().Empty() { - t.Errorf("want c.ProviderConfig == nil, got c.ProviderConfig=%#v") + t.Errorf("want c.ProviderConfig == nil, got c.ProviderConfig=%#v", cli.providerConfig) } // SyncProviderConfig beings a goroutine which writes to the client's provider config. diff --git a/oidc/client_test.go b/oidc/client_test.go index a0701b5d..b00176a0 100644 --- a/oidc/client_test.go +++ b/oidc/client_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" - "github.com/coreos/go-oidc/jose" - "github.com/coreos/go-oidc/key" - "github.com/coreos/go-oidc/oauth2" + "github.com/gambol99/go-oidc/jose" + "github.com/gambol99/go-oidc/key" + "github.com/gambol99/go-oidc/oauth2" "github.com/kylelemons/godebug/pretty" ) diff --git a/oidc/doc.go b/oidc/doc.go index 196611ec..5f99aaed 100644 --- a/oidc/doc.go +++ b/oidc/doc.go @@ -1,2 +1,2 @@ -// Package oidc is DEPRECATED. Use github.com/coreos/go-oidc instead. +// Package oidc is DEPRECATED. Use github.com/gambol99/go-oidc instead. package oidc diff --git a/oidc/identity.go b/oidc/identity.go index 9bfa8e34..34793277 100644 --- a/oidc/identity.go +++ b/oidc/identity.go @@ -4,7 +4,7 @@ import ( "errors" "time" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) type Identity struct { diff --git a/oidc/identity_test.go b/oidc/identity_test.go index d286c669..32fffc5b 100644 --- a/oidc/identity_test.go +++ b/oidc/identity_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) func TestIdentityFromClaims(t *testing.T) { diff --git a/oidc/key.go b/oidc/key.go index 82a0f567..33e5d911 100755 --- a/oidc/key.go +++ b/oidc/key.go @@ -6,9 +6,9 @@ import ( "net/http" "time" - phttp "github.com/coreos/go-oidc/http" - "github.com/coreos/go-oidc/jose" - "github.com/coreos/go-oidc/key" + phttp "github.com/gambol99/go-oidc/http" + "github.com/gambol99/go-oidc/jose" + "github.com/gambol99/go-oidc/key" ) // DefaultPublicKeySetTTL is the default TTL set on the PublicKeySet if no diff --git a/oidc/provider.go b/oidc/provider.go index 2afc0da3..57d907d7 100644 --- a/oidc/provider.go +++ b/oidc/provider.go @@ -14,8 +14,8 @@ import ( "github.com/coreos/pkg/timeutil" "github.com/jonboulle/clockwork" - phttp "github.com/coreos/go-oidc/http" - "github.com/coreos/go-oidc/oauth2" + phttp "github.com/gambol99/go-oidc/http" + "github.com/gambol99/go-oidc/oauth2" ) const ( @@ -325,7 +325,7 @@ func contains(sli []string, ele string) bool { // // NOTE(ericchiang): For development purposes Valid does not mandate 'https' for // URLs fields where the OIDC spec requires it. This may change in future releases -// of this package. See: https://github.com/coreos/go-oidc/issues/34 +// of this package. See: https://github.com/gambol99/go-oidc/issues/34 func (p ProviderConfig) Valid() error { grantTypes := p.GrantTypesSupported if len(grantTypes) == 0 { diff --git a/oidc/provider_test.go b/oidc/provider_test.go index 9b39f92c..a615b7f7 100644 --- a/oidc/provider_test.go +++ b/oidc/provider_test.go @@ -17,8 +17,8 @@ import ( "github.com/kylelemons/godebug/diff" "github.com/kylelemons/godebug/pretty" - "github.com/coreos/go-oidc/jose" - "github.com/coreos/go-oidc/oauth2" + "github.com/gambol99/go-oidc/jose" + "github.com/gambol99/go-oidc/oauth2" ) func TestProviderConfigDefaults(t *testing.T) { diff --git a/oidc/transport.go b/oidc/transport.go index 61c926d7..963bfbbe 100644 --- a/oidc/transport.go +++ b/oidc/transport.go @@ -5,8 +5,8 @@ import ( "net/http" "sync" - phttp "github.com/coreos/go-oidc/http" - "github.com/coreos/go-oidc/jose" + phttp "github.com/gambol99/go-oidc/http" + "github.com/gambol99/go-oidc/jose" ) type TokenRefresher interface { diff --git a/oidc/transport_test.go b/oidc/transport_test.go index 9ef909aa..9ed21ff7 100644 --- a/oidc/transport_test.go +++ b/oidc/transport_test.go @@ -6,7 +6,7 @@ import ( "reflect" "testing" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) type staticTokenRefresher struct { diff --git a/oidc/util.go b/oidc/util.go index f2a5a195..a5a50846 100644 --- a/oidc/util.go +++ b/oidc/util.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) // RequestTokenExtractor funcs extract a raw encoded token from a request. diff --git a/oidc/util_test.go b/oidc/util_test.go index c4b8f16b..99d32ffe 100644 --- a/oidc/util_test.go +++ b/oidc/util_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/coreos/go-oidc/jose" + "github.com/gambol99/go-oidc/jose" ) func TestCookieTokenExtractorInvalid(t *testing.T) { diff --git a/oidc/verification.go b/oidc/verification.go index d9c6afa6..33d62946 100644 --- a/oidc/verification.go +++ b/oidc/verification.go @@ -7,8 +7,8 @@ import ( "github.com/jonboulle/clockwork" - "github.com/coreos/go-oidc/jose" - "github.com/coreos/go-oidc/key" + "github.com/gambol99/go-oidc/jose" + "github.com/gambol99/go-oidc/key" ) func VerifySignature(jwt jose.JWT, keys []key.PublicKey) (bool, error) { @@ -36,9 +36,9 @@ func containsString(needle string, haystack []string) bool { return false } -// Verify claims in accordance with OIDC spec +// VerifyClaims claims in accordance with OIDC spec // http://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation -func VerifyClaims(jwt jose.JWT, issuer, clientID string) error { +func VerifyClaims(jwt jose.JWT, issuer, clientID string, skipClientID bool) error { now := time.Now().UTC() claims, err := jwt.Claims() @@ -60,7 +60,7 @@ func VerifyClaims(jwt jose.JWT, issuer, clientID string) error { // host, and optionally, port number and path components and no query or fragment components. if iss, exists := claims["iss"].(string); exists { if !urlEqual(iss, issuer) { - return fmt.Errorf("invalid claim value: 'iss'. expected=%s, found=%s.", issuer, iss) + return fmt.Errorf("Invalid claim value: 'iss'. expected=%s, found=%s", issuer, iss) } } else { return errors.New("missing claim: 'iss'") @@ -78,16 +78,18 @@ func VerifyClaims(jwt jose.JWT, issuer, clientID string) error { // It MAY also contain identifiers for other audiences. In the general case, the aud // value is an array of case sensitive strings. In the common special case when there // is one audience, the aud value MAY be a single case sensitive string. - if aud, ok, err := claims.StringClaim("aud"); err == nil && ok { - if aud != clientID { - return fmt.Errorf("invalid claims, 'aud' claim and 'client_id' do not match, aud=%s, client_id=%s", aud, clientID) - } - } else if aud, ok, err := claims.StringsClaim("aud"); err == nil && ok { - if !containsString(clientID, aud) { - return fmt.Errorf("invalid claims, cannot find 'client_id' in 'aud' claim, aud=%v, client_id=%s", aud, clientID) + if !skipClientID { + if aud, ok, err := claims.StringClaim("aud"); err == nil && ok { + if aud != clientID { + return fmt.Errorf("invalid claims, 'aud' claim and 'client_id' do not match, aud=%s, client_id=%s", aud, clientID) + } + } else if aud, ok, err := claims.StringsClaim("aud"); err == nil && ok { + if !containsString(clientID, aud) { + return fmt.Errorf("invalid claims, cannot find 'client_id' in 'aud' claim, aud=%v, client_id=%s", aud, clientID) + } + } else { + return errors.New("invalid claim value: 'aud' is required, and should be either string or string array") } - } else { - return errors.New("invalid claim value: 'aud' is required, and should be either string or string array") } return nil @@ -142,29 +144,34 @@ func VerifyClientClaims(jwt jose.JWT, issuer string) (string, error) { return sub, nil } +// JWTVerifier is a verifications checker type JWTVerifier struct { - issuer string - clientID string - syncFunc func() error - keysFunc func() []key.PublicKey - clock clockwork.Clock + issuer string + clientID string + skipClientIDCheck bool + syncFunc func() error + keysFunc func() []key.PublicKey + clock clockwork.Clock } -func NewJWTVerifier(issuer, clientID string, syncFunc func() error, keysFunc func() []key.PublicKey) JWTVerifier { +// NewJWTVerifier returns a JWT verifier +func NewJWTVerifier(issuer, clientID string, syncFunc func() error, keysFunc func() []key.PublicKey, skipClientID bool) JWTVerifier { return JWTVerifier{ - issuer: issuer, - clientID: clientID, - syncFunc: syncFunc, - keysFunc: keysFunc, - clock: clockwork.NewRealClock(), + issuer: issuer, + clientID: clientID, + syncFunc: syncFunc, + keysFunc: keysFunc, + skipClientIDCheck: skipClientID, + clock: clockwork.NewRealClock(), } } +// Verify is responsible for verifying the token func (v *JWTVerifier) Verify(jwt jose.JWT) error { // Verify claims before verifying the signature. This is an optimization to throw out // tokens we know are invalid without undergoing an expensive signature check and // possibly a re-sync event. - if err := VerifyClaims(jwt, v.issuer, v.clientID); err != nil { + if err := VerifyClaims(jwt, v.issuer, v.clientID, v.skipClientIDCheck); err != nil { return fmt.Errorf("oidc: JWT claims invalid: %v", err) } diff --git a/oidc/verification_test.go b/oidc/verification_test.go index 3b8c5e9f..494fc979 100644 --- a/oidc/verification_test.go +++ b/oidc/verification_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/coreos/go-oidc/jose" - "github.com/coreos/go-oidc/key" + "github.com/gambol99/go-oidc/jose" + "github.com/gambol99/go-oidc/key" ) func TestVerifyClientClaims(t *testing.T) { @@ -232,7 +232,6 @@ func TestJWTVerifier(t *testing.T) { jwt: newJWT(iss, "XXX", "YYY", past12, future12, priv1.Signer()), wantErr: true, }, - { name: "JWT signed with available key", verifier: JWTVerifier{ diff --git a/verify.go b/verify.go index b46afdb6..51464d99 100644 --- a/verify.go +++ b/verify.go @@ -165,7 +165,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok return nil, fmt.Errorf("oidc: expected audience %q got %q", v.config.ClientID, t.Audience) } } else { - return nil, fmt.Errorf("oidc: Invalid configuration. ClientID must be provided or SkipClientIDCheck must be set.") + return nil, fmt.Errorf("oidc: Invalid configuration. ClientID must be provided or SkipClientIDCheck must be set") } }