diff --git a/cmd/example-app/main.go b/cmd/example-app/main.go index d2ada840..32728841 100644 --- a/cmd/example-app/main.go +++ b/cmd/example-app/main.go @@ -17,7 +17,7 @@ import ( "strings" "time" - "github.com/ericchiang/oidc" + "github.com/coreos/go-oidc" "github.com/spf13/cobra" "golang.org/x/net/context" "golang.org/x/oauth2" @@ -173,7 +173,7 @@ func cmd() *cobra.Command { } a.provider = provider - a.verifier = provider.NewVerifier(a.ctx, oidc.VerifyAudience(a.clientID)) + a.verifier = provider.Verifier(oidc.VerifyAudience(a.clientID)) http.HandleFunc("/", a.handleIndex) http.HandleFunc("/login", a.handleLogin) @@ -269,7 +269,7 @@ func (a *app) handleCallback(w http.ResponseWriter, r *http.Request) { RefreshToken: refresh, Expiry: time.Now().Add(-time.Hour), } - token, err = oauth2Config.TokenSource(a.ctx, t).Token() + token, err = oauth2Config.TokenSource(r.Context(), t).Token() default: http.Error(w, fmt.Sprintf("no code in request: %q", r.Form), http.StatusBadRequest) return @@ -286,7 +286,7 @@ func (a *app) handleCallback(w http.ResponseWriter, r *http.Request) { return } - idToken, err := a.verifier.Verify(rawIDToken) + idToken, err := a.verifier.Verify(r.Context(), rawIDToken) if err != nil { http.Error(w, fmt.Sprintf("Failed to verify ID token: %v", err), http.StatusInternalServerError) return diff --git a/connector/oidc/oidc.go b/connector/oidc/oidc.go index c9d88191..6a71d017 100644 --- a/connector/oidc/oidc.go +++ b/connector/oidc/oidc.go @@ -6,7 +6,7 @@ import ( "fmt" "net/http" - "github.com/ericchiang/oidc" + "github.com/coreos/go-oidc" "golang.org/x/net/context" "golang.org/x/oauth2" @@ -51,7 +51,7 @@ func (c *Config) Open() (conn connector.Connector, err error) { Scopes: scopes, RedirectURL: c.RedirectURI, }, - verifier: provider.NewVerifier(ctx, + verifier: provider.Verifier( oidc.VerifyExpiry(), oidc.VerifyAudience(clientID), ), @@ -99,7 +99,7 @@ func (c *oidcConnector) HandleCallback(s connector.Scopes, r *http.Request) (ide if errType := q.Get("error"); errType != "" { return identity, &oauth2Error{errType, q.Get("error_description")} } - token, err := c.oauth2Config.Exchange(c.ctx, q.Get("code")) + token, err := c.oauth2Config.Exchange(r.Context(), q.Get("code")) if err != nil { return identity, fmt.Errorf("oidc: failed to get token: %v", err) } @@ -108,7 +108,7 @@ func (c *oidcConnector) HandleCallback(s connector.Scopes, r *http.Request) (ide if !ok { return identity, errors.New("oidc: no id_token in token response") } - idToken, err := c.verifier.Verify(rawIDToken) + idToken, err := c.verifier.Verify(r.Context(), rawIDToken) if err != nil { return identity, fmt.Errorf("oidc: failed to verify ID Token: %v", err) } diff --git a/glide.lock b/glide.lock index 41f250fa..0c79505e 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ -hash: bc7fa6bbfddcb39710064a9d6dab090d49bd88486571cae12c68c4b70093e716 -updated: 2016-11-03T14:31:37.323302694-07:00 +hash: c3530f2a60a64c2efc4c3ac499fcd15f79de2a532715ba2b9841c1d404942b2e +updated: 2016-11-17T15:18:56.701287533-08:00 imports: - name: github.com/cockroachdb/cockroach-go version: 31611c0501c812f437d4861d87d117053967c955 subpackages: - crdb -- name: github.com/ericchiang/oidc - version: 1907f0e61549f9081f26bdf269f11603496c9dee +- name: github.com/coreos/go-oidc + version: 5a7f09ab5787e846efa7f56f4a08b6d6926d08c4 - name: github.com/ghodss/yaml version: bea76d6a4713e18b7f5321a2b020738552def3ea - name: github.com/go-sql-driver/mysql @@ -52,6 +52,7 @@ imports: version: 6a513affb38dc9788b449d59ffed099b8de18fa0 subpackages: - context + - context/ctxhttp - http2 - http2/hpack - internal/timeseries @@ -87,13 +88,8 @@ imports: version: 4e86f4367175e39f69d9358a5f17b4dda270378d - name: gopkg.in/ldap.v2 version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73 -- name: gopkg.in/square/go-jose.v1 - version: e3f973b66b91445ec816dd7411ad1b6495a5a2fc - subpackages: - - cipher - - json - name: gopkg.in/square/go-jose.v2 - version: f209f41628247c56938cb20ef51d589ddad6c30b + version: 8c5257b2f658f86d174ae68c6a592eaf6a9608d9 subpackages: - cipher - json diff --git a/glide.yaml b/glide.yaml index 73be313a..bd16dab6 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,7 +17,7 @@ import: version: 4e86f4367175e39f69d9358a5f17b4dda270378d - package: gopkg.in/square/go-jose.v2 - version: f209f41628247c56938cb20ef51d589ddad6c30b + version: v2.0.0 subpackages: - cipher - json @@ -26,6 +26,7 @@ import: version: 6a513affb38dc9788b449d59ffed099b8de18fa0 subpackages: - context + - context/ctxhttp - http2 - http2/hpack - internal/timeseries @@ -49,16 +50,17 @@ import: subpackages: - bcrypt -- package: github.com/ericchiang/oidc - version: 1907f0e61549f9081f26bdf269f11603496c9dee +- package: github.com/coreos/go-oidc + version: 5a7f09ab5787e846efa7f56f4a08b6d6926d08c4 - package: github.com/pquerna/cachecontrol version: c97913dcbd76de40b051a9b4cd827f7eaeb7a868 -- package: gopkg.in/square/go-jose.v1 - version: v1.0.2 - package: golang.org/x/oauth2 version: 08c8d727d2392d18286f9f88ad775ad98f09ab33 -# Not actually imported but glide detects it. Consider adding subpackages to -# the oauth2 package to eliminate. + subpackages: [] +# The oauth2 package only imports the appengine code when it's given a +# specific build tags, but glide detects it anyway. +# +# https://github.com/golang/oauth2/blob/d5040cdd/client_appengine.go - package: google.golang.org/appengine version: 267c27e7492265b84fc6719503b14a1e17975d79 subpackages: diff --git a/server/server_test.go b/server/server_test.go index 6db67d5c..a5865dfa 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -3,6 +3,7 @@ package server import ( "crypto/rsa" "crypto/x509" + "encoding/json" "encoding/pem" "errors" "fmt" @@ -17,7 +18,7 @@ import ( "testing" "time" - "github.com/ericchiang/oidc" + oidc "github.com/coreos/go-oidc" "github.com/kylelemons/godebug/pretty" "golang.org/x/crypto/bcrypt" "golang.org/x/net/context" @@ -117,17 +118,21 @@ func TestDiscovery(t *testing.T) { if err != nil { t.Fatalf("failed to get provider: %v", err) } - required := []struct { - name, val string - }{ - {"issuer", p.Issuer}, - {"authorization_endpoint", p.AuthURL}, - {"token_endpoint", p.TokenURL}, - {"jwks_uri", p.JWKSURL}, + + var got map[string]*json.RawMessage + if err := p.Claims(&got); err != nil { + t.Fatalf("failed to decode claims: %v", err) + } + + required := []string{ + "issuer", + "authorization_endpoint", + "token_endpoint", + "jwks_uri", } for _, field := range required { - if field.val == "" { - t.Errorf("server discovery is missing required field %q", field.name) + if _, ok := got[field]; !ok { + t.Errorf("server discovery is missing required field %q", field) } } } @@ -169,7 +174,7 @@ func TestOAuth2CodeFlow(t *testing.T) { if !ok { return fmt.Errorf("no id token found") } - if _, err := p.NewVerifier(ctx).Verify(idToken); err != nil { + if _, err := p.Verifier().Verify(ctx, idToken); err != nil { return fmt.Errorf("failed to verify id token: %v", err) } return nil @@ -192,7 +197,7 @@ func TestOAuth2CodeFlow(t *testing.T) { if !ok { return fmt.Errorf("no id token found") } - idToken, err := p.NewVerifier(ctx).Verify(rawIDToken) + idToken, err := p.Verifier().Verify(ctx, rawIDToken) if err != nil { return fmt.Errorf("failed to verify id token: %v", err) } @@ -230,7 +235,7 @@ func TestOAuth2CodeFlow(t *testing.T) { v.Add("grant_type", "refresh_token") v.Add("refresh_token", token.RefreshToken) v.Add("scope", strings.Join(requestedScopes, " ")) - resp, err := http.PostForm(p.TokenURL, v) + resp, err := http.PostForm(p.Endpoint().TokenURL, v) if err != nil { return err } @@ -258,7 +263,7 @@ func TestOAuth2CodeFlow(t *testing.T) { // Since we support that client we choose to be more relaxed about // scope parsing, disregarding extra whitespace. v.Add("scope", " "+strings.Join(requestedScopes, " ")) - resp, err := http.PostForm(p.TokenURL, v) + resp, err := http.PostForm(p.Endpoint().TokenURL, v) if err != nil { return err } @@ -284,7 +289,7 @@ func TestOAuth2CodeFlow(t *testing.T) { v.Add("refresh_token", token.RefreshToken) // Request a scope that wasn't requestd initially. v.Add("scope", "oidc email profile") - resp, err := http.PostForm(p.TokenURL, v) + resp, err := http.PostForm(p.Endpoint().TokenURL, v) if err != nil { return err } @@ -335,7 +340,7 @@ func TestOAuth2CodeFlow(t *testing.T) { if !ok { return fmt.Errorf("no id_token in refreshed token") } - idToken, err := p.NewVerifier(ctx).Verify(rawIDToken) + idToken, err := p.Verifier().Verify(ctx, rawIDToken) if err != nil { return fmt.Errorf("failed to verify id token: %v", err) } @@ -547,7 +552,7 @@ func TestOAuth2ImplicitFlow(t *testing.T) { src := &nonceSource{nonce: nonce} - idTokenVerifier := p.NewVerifier(ctx, oidc.VerifyAudience(client.ID), oidc.VerifyNonce(src)) + idTokenVerifier := p.Verifier(oidc.VerifyAudience(client.ID), oidc.VerifyNonce(src)) oauth2Config = &oauth2.Config{ ClientID: client.ID, @@ -569,7 +574,7 @@ func TestOAuth2ImplicitFlow(t *testing.T) { if idToken == "" { return errors.New("no id_token in fragment") } - if _, err := idTokenVerifier.Verify(idToken); err != nil { + if _, err := idTokenVerifier.Verify(ctx, idToken); err != nil { return fmt.Errorf("failed to verify id_token: %v", err) } return nil @@ -664,7 +669,7 @@ func TestCrossClientScopes(t *testing.T) { t.Errorf("no id token found: %v", err) return } - idToken, err := p.NewVerifier(ctx).Verify(rawIDToken) + idToken, err := p.Verifier().Verify(ctx, rawIDToken) if err != nil { t.Errorf("failed to parse ID Token: %v", err) return diff --git a/vendor/github.com/coreos/go-oidc/.gitignore b/vendor/github.com/coreos/go-oidc/.gitignore new file mode 100644 index 00000000..c96f2f47 --- /dev/null +++ b/vendor/github.com/coreos/go-oidc/.gitignore @@ -0,0 +1,2 @@ +/bin +/gopath diff --git a/vendor/github.com/coreos/go-oidc/.travis.yml b/vendor/github.com/coreos/go-oidc/.travis.yml new file mode 100644 index 00000000..fb89294c --- /dev/null +++ b/vendor/github.com/coreos/go-oidc/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.7.3 + - 1.6.3 + +install: + - go get -v -t github.com/coreos/go-oidc + - go get golang.org/x/tools/cmd/cover + - go get github.com/golang/lint/golint + +script: + - ./test + +notifications: + email: false diff --git a/vendor/github.com/coreos/go-oidc/CONTRIBUTING.md b/vendor/github.com/coreos/go-oidc/CONTRIBUTING.md new file mode 100644 index 00000000..6662073a --- /dev/null +++ b/vendor/github.com/coreos/go-oidc/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# How to Contribute + +CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via +GitHub pull requests. This document outlines some of the conventions on +development workflow, commit message formatting, contact points and other +resources to make it easier to get your contribution accepted. + +# Certificate of Origin + +By contributing to this project you agree to the Developer Certificate of +Origin (DCO). This document was created by the Linux Kernel community and is a +simple statement that you, as a contributor, have the legal right to make the +contribution. See the [DCO](DCO) file for details. + +# Email and Chat + +The project currently uses the general CoreOS email list and IRC channel: +- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev) +- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org + +Please avoid emailing maintainers found in the MAINTAINERS file directly. They +are very busy and read the mailing lists. + +## Getting Started + +- Fork the repository on GitHub +- Read the [README](README.md) for build and test instructions +- Play with the project, submit bugs, submit patches! + +## Contribution Flow + +This is a rough outline of what a contributor's workflow looks like: + +- Create a topic branch from where you want to base your work (usually master). +- Make commits of logical units. +- Make sure your commit messages are in the proper format (see below). +- Push your changes to a topic branch in your fork of the repository. +- Make sure the tests pass, and add any new tests as appropriate. +- Submit a pull request to the original repository. + +Thanks for your contributions! + +### Format of the Commit Message + +We follow a rough convention for commit messages that is designed to answer two +questions: what changed and why. The subject line should feature the what and +the body of the commit should describe the why. + +``` +scripts: add the test-cluster command + +this uses tmux to setup a test cluster that you can easily kill and +start for debugging. + +Fixes #38 +``` + +The format can be described more formally as follows: + +``` +: + + + +