Skip to content

Commit

Permalink
allow configuring CAs/skip verify for OIDC
Browse files Browse the repository at this point in the history
  • Loading branch information
vito authored and CI Bot committed Mar 22, 2022
1 parent 83ca67f commit f98aae9
Showing 1 changed file with 58 additions and 2 deletions.
60 changes: 58 additions & 2 deletions connector/oidc/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ package oidc

import (
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"strings"
Expand Down Expand Up @@ -38,12 +42,18 @@ type Config struct {
// If this field is nonempty, only users from a listed domain will be allowed to log in
HostedDomains []string `json:"hostedDomains"`

// Override the value of email_verified to true in the returned claims
// Certificates for SSL validation
RootCAs []string `json:"rootCAs"`

// Override the value of email_verifed to true in the returned claims
InsecureSkipEmailVerified bool `json:"insecureSkipEmailVerified"`

// InsecureEnableGroups enables groups claims. This is disabled by default until https://github.com/dexidp/dex/issues/1065 is resolved
InsecureEnableGroups bool `json:"insecureEnableGroups"`

// Disable certificate verification
InsecureSkipVerify bool `json:"insecureSkipVerify"`

// GetUserInfo uses the userinfo endpoint to get additional claims for
// the token. This is especially useful where upstreams return "thin"
// id tokens
Expand Down Expand Up @@ -104,7 +114,13 @@ func knownBrokenAuthHeaderProvider(issuerURL string) bool {
// Open returns a connector which can be used to login users through an upstream
// OpenID Connect provider.
func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, err error) {
httpClient, err := newHTTPClient(c.RootCAs, c.InsecureSkipVerify)
if err != nil {
return nil, err
}

ctx, cancel := context.WithCancel(context.Background())
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)

provider, err := oidc.NewProvider(ctx, c.Issuer)
if err != nil {
Expand Down Expand Up @@ -151,6 +167,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
),
logger: logger,
cancel: cancel,
httpClient: httpClient,
hostedDomains: c.HostedDomains,
insecureSkipEmailVerified: c.InsecureSkipEmailVerified,
insecureEnableGroups: c.InsecureEnableGroups,
Expand All @@ -165,6 +182,40 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
}, nil
}

func newHTTPClient(rootCAs []string, insecureSkipVerify bool) (*http.Client, error) {
pool, err := x509.SystemCertPool()
if err != nil {
return nil, err
}

tlsConfig := tls.Config{RootCAs: pool, InsecureSkipVerify: insecureSkipVerify}
for _, rootCA := range rootCAs {
rootCABytes, err := ioutil.ReadFile(rootCA)
if err != nil {
return nil, fmt.Errorf("failed to read root-ca: %v", err)
}
if !tlsConfig.RootCAs.AppendCertsFromPEM(rootCABytes) {
return nil, fmt.Errorf("no certs found in root CA file %q", rootCA)
}
}

return &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tlsConfig,
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}, nil
}

var (
_ connector.CallbackConnector = (*oidcConnector)(nil)
_ connector.RefreshConnector = (*oidcConnector)(nil)
Expand All @@ -177,6 +228,7 @@ type oidcConnector struct {
verifier *oidc.IDTokenVerifier
cancel context.CancelFunc
logger log.Logger
httpClient *http.Client
hostedDomains []string
insecureSkipEmailVerified bool
insecureEnableGroups bool
Expand Down Expand Up @@ -232,7 +284,10 @@ 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(r.Context(), q.Get("code"))

ctx := context.WithValue(r.Context(), oauth2.HTTPClient, c.httpClient)

token, err := c.oauth2Config.Exchange(ctx, q.Get("code"))
if err != nil {
return identity, fmt.Errorf("oidc: failed to get token: %v", err)
}
Expand Down Expand Up @@ -265,6 +320,7 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
if !ok {
return identity, errors.New("oidc: no id_token in token response")
}

idToken, err := c.verifier.Verify(ctx, rawIDToken)
if err != nil {
return identity, fmt.Errorf("oidc: failed to verify ID Token: %v", err)
Expand Down

0 comments on commit f98aae9

Please sign in to comment.