Merge pull request #840 from ericchiang/oidc-bump
*: update go-oidc and use standard library's context package
This commit is contained in:
commit
95d54956e9
22 changed files with 153 additions and 380 deletions
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -15,7 +16,6 @@ import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -19,7 +20,6 @@ import (
|
||||||
|
|
||||||
"github.com/coreos/go-oidc"
|
"github.com/coreos/go-oidc"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ func cmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
a.provider = provider
|
a.provider = provider
|
||||||
a.verifier = provider.Verifier(oidc.VerifyAudience(a.clientID))
|
a.verifier = provider.Verifier(&oidc.Config{ClientID: a.clientID})
|
||||||
|
|
||||||
http.HandleFunc("/", a.handleIndex)
|
http.HandleFunc("/", a.handleIndex)
|
||||||
http.HandleFunc("/login", a.handleLogin)
|
http.HandleFunc("/login", a.handleLogin)
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
package connector
|
package connector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Connector is a mechanism for federating login to a remote identity service.
|
// Connector is a mechanism for federating login to a remote identity service.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package github
|
package github
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -10,7 +11,6 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/github"
|
"golang.org/x/oauth2/github"
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package gitlab
|
package gitlab
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -12,7 +13,6 @@ import (
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/coreos/dex/connector"
|
"github.com/coreos/dex/connector"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -9,7 +10,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"gopkg.in/ldap.v2"
|
"gopkg.in/ldap.v2"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
package mock
|
package mock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/coreos/dex/connector"
|
"github.com/coreos/dex/connector"
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
package oidc
|
package oidc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/coreos/go-oidc"
|
"github.com/coreos/go-oidc"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"github.com/coreos/dex/connector"
|
"github.com/coreos/dex/connector"
|
||||||
|
@ -53,10 +53,10 @@ func (c *Config) Open(logger logrus.FieldLogger) (conn connector.Connector, err
|
||||||
RedirectURL: c.RedirectURI,
|
RedirectURL: c.RedirectURI,
|
||||||
},
|
},
|
||||||
verifier: provider.Verifier(
|
verifier: provider.Verifier(
|
||||||
oidc.VerifyExpiry(),
|
&oidc.Config{ClientID: clientID},
|
||||||
oidc.VerifyAudience(clientID),
|
|
||||||
),
|
),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
cancel: cancel,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
glide.lock
generated
7
glide.lock
generated
|
@ -1,5 +1,5 @@
|
||||||
hash: 1207c251a7dab3b824746d66219beabc40f0b1d3c08ed90ac50f5bbdb8872631
|
hash: fbef1f81a0f86f519714bbe568692a92709c446ef487a3fa9875e58f86e14430
|
||||||
updated: 2017-01-25T20:32:43.599648533+01:00
|
updated: 2017-03-08T10:31:06.364335442-08:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/beevik/etree
|
- name: github.com/beevik/etree
|
||||||
version: 4cd0dd976db869f817248477718071a28e978df0
|
version: 4cd0dd976db869f817248477718071a28e978df0
|
||||||
|
@ -8,7 +8,7 @@ imports:
|
||||||
subpackages:
|
subpackages:
|
||||||
- crdb
|
- crdb
|
||||||
- name: github.com/coreos/go-oidc
|
- name: github.com/coreos/go-oidc
|
||||||
version: 2b5d73091ea4b7ddb15e3ac00077f153120b5b61
|
version: be73733bb8cc830d0205609b95d125215f8e9c70
|
||||||
- name: github.com/ghodss/yaml
|
- name: github.com/ghodss/yaml
|
||||||
version: bea76d6a4713e18b7f5321a2b020738552def3ea
|
version: bea76d6a4713e18b7f5321a2b020738552def3ea
|
||||||
- name: github.com/go-sql-driver/mysql
|
- name: github.com/go-sql-driver/mysql
|
||||||
|
@ -62,7 +62,6 @@ imports:
|
||||||
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
- context/ctxhttp
|
|
||||||
- http2
|
- http2
|
||||||
- http2/hpack
|
- http2/hpack
|
||||||
- internal/timeseries
|
- internal/timeseries
|
||||||
|
|
|
@ -35,7 +35,6 @@ import:
|
||||||
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
- context/ctxhttp
|
|
||||||
- http2
|
- http2
|
||||||
- http2/hpack
|
- http2/hpack
|
||||||
- internal/timeseries
|
- internal/timeseries
|
||||||
|
@ -68,7 +67,7 @@ import:
|
||||||
|
|
||||||
# Used for server integration tests and OpenID Connect connector.
|
# Used for server integration tests and OpenID Connect connector.
|
||||||
- package: github.com/coreos/go-oidc
|
- package: github.com/coreos/go-oidc
|
||||||
version: 2b5d73091ea4b7ddb15e3ac00077f153120b5b61
|
version: be73733bb8cc830d0205609b95d125215f8e9c70
|
||||||
- package: github.com/pquerna/cachecontrol
|
- package: github.com/pquerna/cachecontrol
|
||||||
version: c97913dcbd76de40b051a9b4cd827f7eaeb7a868
|
version: c97913dcbd76de40b051a9b4cd827f7eaeb7a868
|
||||||
- package: golang.org/x/oauth2
|
- package: golang.org/x/oauth2
|
||||||
|
|
|
@ -5,6 +5,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
// go-grpc doesn't use the standard library's context.
|
||||||
|
// https://github.com/grpc/grpc-go/issues/711
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHandleHealth(t *testing.T) {
|
func TestHandleHealth(t *testing.T) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
@ -9,7 +10,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -10,7 +11,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -24,7 +25,6 @@ import (
|
||||||
oidc "github.com/coreos/go-oidc"
|
oidc "github.com/coreos/go-oidc"
|
||||||
"github.com/kylelemons/godebug/pretty"
|
"github.com/kylelemons/godebug/pretty"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
jose "gopkg.in/square/go-jose.v2"
|
||||||
|
|
||||||
|
@ -175,6 +175,8 @@ func TestOAuth2CodeFlow(t *testing.T) {
|
||||||
// Connector used by the tests.
|
// Connector used by the tests.
|
||||||
var conn *mock.Callback
|
var conn *mock.Callback
|
||||||
|
|
||||||
|
oidcConfig := &oidc.Config{SkipClientIDCheck: true}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
// If specified these set of scopes will be used during the test case.
|
// If specified these set of scopes will be used during the test case.
|
||||||
|
@ -189,7 +191,7 @@ func TestOAuth2CodeFlow(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no id token found")
|
return fmt.Errorf("no id token found")
|
||||||
}
|
}
|
||||||
if _, err := p.Verifier().Verify(ctx, idToken); err != nil {
|
if _, err := p.Verifier(oidcConfig).Verify(ctx, idToken); err != nil {
|
||||||
return fmt.Errorf("failed to verify id token: %v", err)
|
return fmt.Errorf("failed to verify id token: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -212,7 +214,7 @@ func TestOAuth2CodeFlow(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no id token found")
|
return fmt.Errorf("no id token found")
|
||||||
}
|
}
|
||||||
idToken, err := p.Verifier().Verify(ctx, rawIDToken)
|
idToken, err := p.Verifier(oidcConfig).Verify(ctx, rawIDToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to verify id token: %v", err)
|
return fmt.Errorf("failed to verify id token: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -229,7 +231,7 @@ func TestOAuth2CodeFlow(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no id token found")
|
return fmt.Errorf("no id token found")
|
||||||
}
|
}
|
||||||
idToken, err := p.Verifier().Verify(ctx, rawIDToken)
|
idToken, err := p.Verifier(oidcConfig).Verify(ctx, rawIDToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to verify id token: %v", err)
|
return fmt.Errorf("failed to verify id token: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -391,7 +393,7 @@ func TestOAuth2CodeFlow(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no id_token in refreshed token")
|
return fmt.Errorf("no id_token in refreshed token")
|
||||||
}
|
}
|
||||||
idToken, err := p.Verifier().Verify(ctx, rawIDToken)
|
idToken, err := p.Verifier(oidcConfig).Verify(ctx, rawIDToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to verify id token: %v", err)
|
return fmt.Errorf("failed to verify id token: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -632,7 +634,10 @@ func TestOAuth2ImplicitFlow(t *testing.T) {
|
||||||
|
|
||||||
src := &nonceSource{nonce: nonce}
|
src := &nonceSource{nonce: nonce}
|
||||||
|
|
||||||
idTokenVerifier := p.Verifier(oidc.VerifyAudience(client.ID), oidc.VerifyNonce(src))
|
idTokenVerifier := p.Verifier(&oidc.Config{
|
||||||
|
ClientID: client.ID,
|
||||||
|
ClaimNonce: src.ClaimNonce,
|
||||||
|
})
|
||||||
|
|
||||||
oauth2Config = &oauth2.Config{
|
oauth2Config = &oauth2.Config{
|
||||||
ClientID: client.ID,
|
ClientID: client.ID,
|
||||||
|
@ -749,7 +754,7 @@ func TestCrossClientScopes(t *testing.T) {
|
||||||
t.Errorf("no id token found: %v", err)
|
t.Errorf("no id token found: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
idToken, err := p.Verifier().Verify(ctx, rawIDToken)
|
idToken, err := p.Verifier(&oidc.Config{ClientID: testClientID}).Verify(ctx, rawIDToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to parse ID Token: %v", err)
|
t.Errorf("failed to parse ID Token: %v", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,6 +2,7 @@ package kubernetes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
|
@ -24,7 +25,6 @@ import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/gtank/cryptopasta"
|
"github.com/gtank/cryptopasta"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
"github.com/coreos/dex/storage"
|
"github.com/coreos/dex/storage"
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package kubernetes
|
package kubernetes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/coreos/dex/storage"
|
"github.com/coreos/dex/storage"
|
||||||
"github.com/coreos/dex/storage/kubernetes/k8sapi"
|
"github.com/coreos/dex/storage/kubernetes/k8sapi"
|
||||||
|
@ -85,6 +84,7 @@ func (c *Config) open(logger logrus.FieldLogger, errOnTPRs bool) (*client, error
|
||||||
|
|
||||||
if !cli.createThirdPartyResources() {
|
if !cli.createThirdPartyResources() {
|
||||||
if errOnTPRs {
|
if errOnTPRs {
|
||||||
|
cancel()
|
||||||
return nil, fmt.Errorf("failed creating third party resources")
|
return nil, fmt.Errorf("failed creating third party resources")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
vendor/github.com/coreos/go-oidc/jwks.go
generated
vendored
5
vendor/github.com/coreos/go-oidc/jwks.go
generated
vendored
|
@ -1,6 +1,7 @@
|
||||||
package oidc
|
package oidc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -9,8 +10,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pquerna/cachecontrol"
|
"github.com/pquerna/cachecontrol"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/net/context/ctxhttp"
|
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
jose "gopkg.in/square/go-jose.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ func (r *remoteKeySet) updateKeys(ctx context.Context) error {
|
||||||
return fmt.Errorf("oidc: can't create request: %v", err)
|
return fmt.Errorf("oidc: can't create request: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := ctxhttp.Do(ctx, clientFromContext(ctx), req)
|
resp, err := doRequest(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("oidc: get keys failed %v", err)
|
return fmt.Errorf("oidc: get keys failed %v", err)
|
||||||
}
|
}
|
||||||
|
|
46
vendor/github.com/coreos/go-oidc/oidc.go
generated
vendored
46
vendor/github.com/coreos/go-oidc/oidc.go
generated
vendored
|
@ -2,6 +2,7 @@
|
||||||
package oidc
|
package oidc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -10,8 +11,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/net/context/ctxhttp"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
jose "gopkg.in/square/go-jose.v2"
|
||||||
)
|
)
|
||||||
|
@ -46,11 +45,12 @@ func ClientContext(ctx context.Context, client *http.Client) context.Context {
|
||||||
return context.WithValue(ctx, oauth2.HTTPClient, client)
|
return context.WithValue(ctx, oauth2.HTTPClient, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func clientFromContext(ctx context.Context) *http.Client {
|
func doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
||||||
if client, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {
|
client := http.DefaultClient
|
||||||
return client
|
if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {
|
||||||
|
client = c
|
||||||
}
|
}
|
||||||
return http.DefaultClient
|
return client.Do(req.WithContext(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider represents an OpenID Connect server's configuration.
|
// Provider represents an OpenID Connect server's configuration.
|
||||||
|
@ -85,7 +85,11 @@ type providerJSON struct {
|
||||||
// or "https://login.salesforce.com".
|
// or "https://login.salesforce.com".
|
||||||
func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
|
func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
|
||||||
wellKnown := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
|
wellKnown := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
|
||||||
resp, err := ctxhttp.Get(ctx, clientFromContext(ctx), wellKnown)
|
req, err := http.NewRequest("GET", wellKnown, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := doRequest(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -174,7 +178,7 @@ func (p *Provider) UserInfo(ctx context.Context, tokenSource oauth2.TokenSource)
|
||||||
}
|
}
|
||||||
token.SetAuthHeader(req)
|
token.SetAuthHeader(req)
|
||||||
|
|
||||||
resp, err := ctxhttp.Do(ctx, clientFromContext(ctx), req)
|
resp, err := doRequest(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -201,19 +205,35 @@ func (p *Provider) UserInfo(ctx context.Context, tokenSource oauth2.TokenSource)
|
||||||
// The ID Token only holds fields OpenID Connect requires. To access additional
|
// The ID Token only holds fields OpenID Connect requires. To access additional
|
||||||
// claims returned by the server, use the Claims method.
|
// claims returned by the server, use the Claims method.
|
||||||
type IDToken struct {
|
type IDToken struct {
|
||||||
// The URL of the server which issued this token. This will always be the same
|
// The URL of the server which issued this token. OpenID Connect
|
||||||
// as the URL used for initial discovery.
|
// requires this value always be identical to the URL used for
|
||||||
|
// initial discovery.
|
||||||
|
//
|
||||||
|
// Note: Because of a known issue with Google Accounts' implementation
|
||||||
|
// this value may differ when using Google.
|
||||||
|
//
|
||||||
|
// See: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
|
||||||
Issuer string
|
Issuer string
|
||||||
|
|
||||||
// The client, or set of clients, that this token is issued for.
|
// The client ID, or set of client IDs, that this token is issued for. For
|
||||||
|
// common uses, this is the client that initialized the auth flow.
|
||||||
|
//
|
||||||
|
// This package ensures the audience contains an expected value.
|
||||||
Audience []string
|
Audience []string
|
||||||
|
|
||||||
// A unique string which identifies the end user.
|
// A unique string which identifies the end user.
|
||||||
Subject string
|
Subject string
|
||||||
|
|
||||||
|
// Expiry of the token. Ths package will not process tokens that have
|
||||||
|
// expired unless that validation is explicitly turned off.
|
||||||
|
Expiry time.Time
|
||||||
|
// When the token was issued by the provider.
|
||||||
IssuedAt time.Time
|
IssuedAt time.Time
|
||||||
Expiry time.Time
|
|
||||||
Nonce string
|
// Initial nonce provided during the authentication redirect.
|
||||||
|
//
|
||||||
|
// If present, this package ensures this is a valid nonce.
|
||||||
|
Nonce string
|
||||||
|
|
||||||
// Raw payload of the id_token.
|
// Raw payload of the id_token.
|
||||||
claims []byte
|
claims []byte
|
||||||
|
|
192
vendor/github.com/coreos/go-oidc/verify.go
generated
vendored
192
vendor/github.com/coreos/go-oidc/verify.go
generated
vendored
|
@ -2,6 +2,7 @@ package oidc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -9,61 +10,71 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
jose "gopkg.in/square/go-jose.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
issuerGoogleAccounts = "https://accounts.google.com"
|
||||||
|
issuerGoogleAccountsNoScheme = "accounts.google.com"
|
||||||
|
)
|
||||||
|
|
||||||
// IDTokenVerifier provides verification for ID Tokens.
|
// IDTokenVerifier provides verification for ID Tokens.
|
||||||
type IDTokenVerifier struct {
|
type IDTokenVerifier struct {
|
||||||
keySet *remoteKeySet
|
keySet *remoteKeySet
|
||||||
config *verificationConfig
|
config *Config
|
||||||
}
|
|
||||||
|
|
||||||
// verificationConfig is the unexported configuration for an IDTokenVerifier.
|
|
||||||
//
|
|
||||||
// Users interact with this struct using a VerificationOption.
|
|
||||||
type verificationConfig struct {
|
|
||||||
issuer string
|
issuer string
|
||||||
// If provided, this value must be in the ID Token audiences.
|
|
||||||
audience string
|
|
||||||
// If not nil, check the expiry of the id token.
|
|
||||||
checkExpiry func() time.Time
|
|
||||||
// If specified, only these sets of algorithms may be used to sign the JWT.
|
|
||||||
requiredAlgs []string
|
|
||||||
// If not nil, don't verify nonce.
|
|
||||||
nonceSource NonceSource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerificationOption provides additional checks on ID Tokens.
|
// Config is the configuration for an IDTokenVerifier.
|
||||||
type VerificationOption interface {
|
type Config struct {
|
||||||
// Unexport this method so other packages can't implement this interface.
|
// Expected audience of the token. For a majority of the cases this is expected to be
|
||||||
updateConfig(c *verificationConfig)
|
// the ID of the client that initialized the login flow. It may occasionally differ if
|
||||||
|
// the provider supports the authorizing party (azp) claim.
|
||||||
|
//
|
||||||
|
// If not provided, users must explicitly set SkipClientIDCheck.
|
||||||
|
ClientID string
|
||||||
|
// Method to verify the ID Token nonce. If a nonce is present and this method
|
||||||
|
// is nil, users must explicitly set SkipNonceCheck.
|
||||||
|
//
|
||||||
|
// If the ID Token nonce is empty, for example if the client didn't provide a nonce in
|
||||||
|
// the initial redirect, this may be nil.
|
||||||
|
ClaimNonce func(nonce string) error
|
||||||
|
// If specified, only this set of algorithms may be used to sign the JWT.
|
||||||
|
//
|
||||||
|
// Since many providers only support RS256, SupportedSigningAlgs defaults to this value.
|
||||||
|
SupportedSigningAlgs []string
|
||||||
|
|
||||||
|
// If true, no ClientID check performed. Must be true if ClientID field is empty.
|
||||||
|
SkipClientIDCheck bool
|
||||||
|
// If true, token expiry is not checked.
|
||||||
|
SkipExpiryCheck bool
|
||||||
|
// If true, nonce claim is not checked. Must be true if ClaimNonce field is empty.
|
||||||
|
SkipNonceCheck bool
|
||||||
|
|
||||||
|
// Time function to check Token expiry. Defaults to time.Now
|
||||||
|
Now func() time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifier returns an IDTokenVerifier that uses the provider's key set to verify JWTs.
|
// Verifier returns an IDTokenVerifier that uses the provider's key set to verify JWTs.
|
||||||
//
|
//
|
||||||
// The returned IDTokenVerifier is tied to the Provider's context and its behavior is
|
// The returned IDTokenVerifier is tied to the Provider's context and its behavior is
|
||||||
// undefined once the Provider's context is canceled.
|
// undefined once the Provider's context is canceled.
|
||||||
func (p *Provider) Verifier(options ...VerificationOption) *IDTokenVerifier {
|
func (p *Provider) Verifier(config *Config) *IDTokenVerifier {
|
||||||
config := &verificationConfig{issuer: p.issuer}
|
|
||||||
for _, option := range options {
|
|
||||||
option.updateConfig(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newVerifier(p.remoteKeySet, config)
|
return newVerifier(p.remoteKeySet, config, p.issuer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVerifier(keySet *remoteKeySet, config *verificationConfig) *IDTokenVerifier {
|
func newVerifier(keySet *remoteKeySet, config *Config, issuer string) *IDTokenVerifier {
|
||||||
// As discussed in the godocs for VerifrySigningAlg, because almost all providers
|
// If SupportedSigningAlgs is empty defaults to only support RS256.
|
||||||
// only support RS256, default to only allowing it.
|
if len(config.SupportedSigningAlgs) == 0 {
|
||||||
if len(config.requiredAlgs) == 0 {
|
config.SupportedSigningAlgs = []string{RS256}
|
||||||
config.requiredAlgs = []string{RS256}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &IDTokenVerifier{
|
return &IDTokenVerifier{
|
||||||
keySet: keySet,
|
keySet: keySet,
|
||||||
config: config,
|
config: config,
|
||||||
|
issuer: issuer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +100,7 @@ func contains(sli []string, ele string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify parses a raw ID Token, verifies it's been signed by the provider, preforms
|
// Verify parses a raw ID Token, verifies it's been signed by the provider, preforms
|
||||||
// any additional checks passed as VerifictionOptions, and returns the payload.
|
// any additional checks depending on the Config, and returns the payload.
|
||||||
//
|
//
|
||||||
// See: https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
|
// See: https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
|
||||||
//
|
//
|
||||||
|
@ -134,20 +145,38 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check issuer.
|
// Check issuer.
|
||||||
if t.Issuer != v.config.issuer {
|
if t.Issuer != v.issuer {
|
||||||
return nil, fmt.Errorf("oidc: id token issued by a different provider, expected %q got %q", v.config.issuer, t.Issuer)
|
// Google sometimes returns "accounts.google.com" as the issuer claim instead of
|
||||||
}
|
// the required "https://accounts.google.com". Detect this case and allow it only
|
||||||
|
// for Google.
|
||||||
// If a client ID has been provided, make sure it's part of the audience.
|
//
|
||||||
if v.config.audience != "" {
|
// We will not add hooks to let other providers go off spec like this.
|
||||||
if !contains(t.Audience, v.config.audience) {
|
if !(v.issuer == issuerGoogleAccounts && t.Issuer == issuerGoogleAccountsNoScheme) {
|
||||||
return nil, fmt.Errorf("oidc: expected audience %q got %q", v.config.audience, t.Audience)
|
return nil, fmt.Errorf("oidc: id token issued by a different provider, expected %q got %q", v.issuer, t.Issuer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a checkExpiry is specified, make sure token is not expired.
|
// If a client ID has been provided, make sure it's part of the audience. SkipClientIDCheck must be true if ClientID is empty.
|
||||||
if v.config.checkExpiry != nil {
|
//
|
||||||
if t.Expiry.Before(v.config.checkExpiry()) {
|
// This check DOES NOT ensure that the ClientID is the party to which the ID Token was issued (i.e. Authorized party).
|
||||||
|
if !v.config.SkipClientIDCheck {
|
||||||
|
if v.config.ClientID != "" {
|
||||||
|
if !contains(t.Audience, v.config.ClientID) {
|
||||||
|
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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a SkipExpiryCheck is false, make sure token is not expired.
|
||||||
|
if !v.config.SkipExpiryCheck {
|
||||||
|
now := time.Now
|
||||||
|
if v.config.Now != nil {
|
||||||
|
now = v.config.Now
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Expiry.Before(now()) {
|
||||||
return nil, fmt.Errorf("oidc: token is expired (Token Expiry: %v)", t.Expiry)
|
return nil, fmt.Errorf("oidc: token is expired (Token Expiry: %v)", t.Expiry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,14 +184,14 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
|
||||||
// If a set of required algorithms has been provided, ensure that the signatures use those.
|
// If a set of required algorithms has been provided, ensure that the signatures use those.
|
||||||
var keyIDs, gotAlgs []string
|
var keyIDs, gotAlgs []string
|
||||||
for _, sig := range jws.Signatures {
|
for _, sig := range jws.Signatures {
|
||||||
if len(v.config.requiredAlgs) == 0 || contains(v.config.requiredAlgs, sig.Header.Algorithm) {
|
if len(v.config.SupportedSigningAlgs) == 0 || contains(v.config.SupportedSigningAlgs, sig.Header.Algorithm) {
|
||||||
keyIDs = append(keyIDs, sig.Header.KeyID)
|
keyIDs = append(keyIDs, sig.Header.KeyID)
|
||||||
} else {
|
} else {
|
||||||
gotAlgs = append(gotAlgs, sig.Header.Algorithm)
|
gotAlgs = append(gotAlgs, sig.Header.Algorithm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(keyIDs) == 0 {
|
if len(keyIDs) == 0 {
|
||||||
return nil, fmt.Errorf("oidc: no signatures use a require algorithm, expected %q got %q", v.config.requiredAlgs, gotAlgs)
|
return nil, fmt.Errorf("oidc: no signatures use a supported algorithm, expected %q got %q", v.config.SupportedSigningAlgs, gotAlgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get keys from the remote key set. This may trigger a re-sync.
|
// Get keys from the remote key set. This may trigger a re-sync.
|
||||||
|
@ -192,79 +221,22 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
|
||||||
|
|
||||||
// Check the nonce after we've verified the token. We don't want to allow unverified
|
// Check the nonce after we've verified the token. We don't want to allow unverified
|
||||||
// payloads to trigger a nonce lookup.
|
// payloads to trigger a nonce lookup.
|
||||||
if v.config.nonceSource != nil {
|
// If SkipNonceCheck is not set ClaimNonce cannot be Nil.
|
||||||
if err := v.config.nonceSource.ClaimNonce(t.Nonce); err != nil {
|
if !v.config.SkipNonceCheck && t.Nonce != "" {
|
||||||
return nil, err
|
if v.config.ClaimNonce != nil {
|
||||||
|
if err := v.config.ClaimNonce(t.Nonce); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("oidc: Invalid configuration. ClaimNonce must be provided or SkipNonceCheck must be set.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyAudience ensures that an ID Token was issued for the specific client.
|
|
||||||
//
|
|
||||||
// Note that a verified token may be valid for other clients, as OpenID Connect allows a token to have
|
|
||||||
// multiple audiences.
|
|
||||||
func VerifyAudience(clientID string) VerificationOption {
|
|
||||||
return clientVerifier{clientID}
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientVerifier struct {
|
|
||||||
clientID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v clientVerifier) updateConfig(c *verificationConfig) {
|
|
||||||
c.audience = v.clientID
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyExpiry ensures that an ID Token has not expired.
|
|
||||||
func VerifyExpiry() VerificationOption {
|
|
||||||
return expiryVerifier{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type expiryVerifier struct{}
|
|
||||||
|
|
||||||
func (v expiryVerifier) updateConfig(c *verificationConfig) {
|
|
||||||
c.checkExpiry = time.Now
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySigningAlg enforces that an ID Token is signed by a specific signing algorithm.
|
|
||||||
//
|
|
||||||
// Because so many providers only support RS256, if this verifiction option isn't used,
|
|
||||||
// the IDTokenVerifier defaults to only allowing RS256.
|
|
||||||
func VerifySigningAlg(allowedAlgs ...string) VerificationOption {
|
|
||||||
return algVerifier{allowedAlgs}
|
|
||||||
}
|
|
||||||
|
|
||||||
type algVerifier struct {
|
|
||||||
algs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v algVerifier) updateConfig(c *verificationConfig) {
|
|
||||||
c.requiredAlgs = v.algs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nonce returns an auth code option which requires the ID Token created by the
|
// Nonce returns an auth code option which requires the ID Token created by the
|
||||||
// OpenID Connect provider to contain the specified nonce.
|
// OpenID Connect provider to contain the specified nonce.
|
||||||
func Nonce(nonce string) oauth2.AuthCodeOption {
|
func Nonce(nonce string) oauth2.AuthCodeOption {
|
||||||
return oauth2.SetAuthURLParam("nonce", nonce)
|
return oauth2.SetAuthURLParam("nonce", nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonceSource represents a source which can verify a nonce is valid and has not
|
|
||||||
// been claimed before.
|
|
||||||
type NonceSource interface {
|
|
||||||
ClaimNonce(nonce string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyNonce ensures that the ID Token contains a nonce which can be claimed by the nonce source.
|
|
||||||
func VerifyNonce(source NonceSource) VerificationOption {
|
|
||||||
return nonceVerifier{source}
|
|
||||||
}
|
|
||||||
|
|
||||||
type nonceVerifier struct {
|
|
||||||
nonceSource NonceSource
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n nonceVerifier) updateConfig(c *verificationConfig) {
|
|
||||||
c.nonceSource = n.nonceSource
|
|
||||||
}
|
|
||||||
|
|
74
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
generated
vendored
74
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
generated
vendored
|
@ -1,74 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.7
|
|
||||||
|
|
||||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
|
||||||
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Do sends an HTTP request with the provided http.Client and returns
|
|
||||||
// an HTTP response.
|
|
||||||
//
|
|
||||||
// If the client is nil, http.DefaultClient is used.
|
|
||||||
//
|
|
||||||
// The provided ctx must be non-nil. If it is canceled or times out,
|
|
||||||
// ctx.Err() will be returned.
|
|
||||||
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
|
||||||
if client == nil {
|
|
||||||
client = http.DefaultClient
|
|
||||||
}
|
|
||||||
resp, err := client.Do(req.WithContext(ctx))
|
|
||||||
// If we got an error, and the context has been canceled,
|
|
||||||
// the context's error is probably more useful.
|
|
||||||
if err != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
err = ctx.Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get issues a GET request via the Do function.
|
|
||||||
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Head issues a HEAD request via the Do function.
|
|
||||||
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("HEAD", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post issues a POST request via the Do function.
|
|
||||||
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("POST", url, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", bodyType)
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PostForm issues a POST request via the Do function.
|
|
||||||
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
|
||||||
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
|
||||||
}
|
|
147
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
generated
vendored
147
vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
generated
vendored
|
@ -1,147 +0,0 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !go1.7
|
|
||||||
|
|
||||||
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
func nop() {}
|
|
||||||
|
|
||||||
var (
|
|
||||||
testHookContextDoneBeforeHeaders = nop
|
|
||||||
testHookDoReturned = nop
|
|
||||||
testHookDidBodyClose = nop
|
|
||||||
)
|
|
||||||
|
|
||||||
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
|
|
||||||
// If the client is nil, http.DefaultClient is used.
|
|
||||||
// If the context is canceled or times out, ctx.Err() will be returned.
|
|
||||||
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
|
||||||
if client == nil {
|
|
||||||
client = http.DefaultClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(djd): Respect any existing value of req.Cancel.
|
|
||||||
cancel := make(chan struct{})
|
|
||||||
req.Cancel = cancel
|
|
||||||
|
|
||||||
type responseAndError struct {
|
|
||||||
resp *http.Response
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
result := make(chan responseAndError, 1)
|
|
||||||
|
|
||||||
// Make local copies of test hooks closed over by goroutines below.
|
|
||||||
// Prevents data races in tests.
|
|
||||||
testHookDoReturned := testHookDoReturned
|
|
||||||
testHookDidBodyClose := testHookDidBodyClose
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
testHookDoReturned()
|
|
||||||
result <- responseAndError{resp, err}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var resp *http.Response
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
testHookContextDoneBeforeHeaders()
|
|
||||||
close(cancel)
|
|
||||||
// Clean up after the goroutine calling client.Do:
|
|
||||||
go func() {
|
|
||||||
if r := <-result; r.resp != nil {
|
|
||||||
testHookDidBodyClose()
|
|
||||||
r.resp.Body.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case r := <-result:
|
|
||||||
var err error
|
|
||||||
resp, err = r.resp, r.err
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
close(cancel)
|
|
||||||
case <-c:
|
|
||||||
// The response's Body is closed.
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
resp.Body = ¬ifyingReader{resp.Body, c}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get issues a GET request via the Do function.
|
|
||||||
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Head issues a HEAD request via the Do function.
|
|
||||||
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("HEAD", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post issues a POST request via the Do function.
|
|
||||||
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("POST", url, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", bodyType)
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PostForm issues a POST request via the Do function.
|
|
||||||
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
|
||||||
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// notifyingReader is an io.ReadCloser that closes the notify channel after
|
|
||||||
// Close is called or a Read fails on the underlying ReadCloser.
|
|
||||||
type notifyingReader struct {
|
|
||||||
io.ReadCloser
|
|
||||||
notify chan<- struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *notifyingReader) Read(p []byte) (int, error) {
|
|
||||||
n, err := r.ReadCloser.Read(p)
|
|
||||||
if err != nil && r.notify != nil {
|
|
||||||
close(r.notify)
|
|
||||||
r.notify = nil
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *notifyingReader) Close() error {
|
|
||||||
err := r.ReadCloser.Close()
|
|
||||||
if r.notify != nil {
|
|
||||||
close(r.notify)
|
|
||||||
r.notify = nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
Reference in a new issue