Skip to content

Commit

Permalink
google: Add support for OAuth2 token exchange over mTLS
Browse files Browse the repository at this point in the history
  • Loading branch information
andyrzhao committed Feb 22, 2023
1 parent df3362d commit d171fca
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
7 changes: 7 additions & 0 deletions google/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package google

import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -62,6 +63,12 @@ type CredentialsParams struct {

// PKCE is used to support PKCE flow. Optional for 3LO flow.
PKCE *authhandler.PKCEParams

// The OAuth2 TokenURL to use, which depends on whether mTLS is enabled. Optional.
TokenURL string

// The TLSConfig used for constructing an mTLS-enabled HTTP client. Optional.
TLSConfig *tls.Config
}

func (params CredentialsParams) deepCopy() CredentialsParams {
Expand Down
39 changes: 38 additions & 1 deletion google/google.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ package google

import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"net/url"
"strings"
"time"

"cloud.google.com/go/compute/metadata"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google/internal/externalaccount"
"golang.org/x/oauth2/internal"
"golang.org/x/oauth2/jwt"
)

Expand All @@ -26,6 +30,9 @@ var Endpoint = oauth2.Endpoint{
AuthStyle: oauth2.AuthStyleInParams,
}

// MTLSTokenURL is Google's OAuth 2.0 default mTLS endpoint.
const MTLSTokenURL = "https://oauth2.mtls.googleapis.com/token"

// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
const JWTTokenURL = "https://oauth2.googleapis.com/token"

Expand Down Expand Up @@ -172,7 +179,14 @@ func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsPar
cfg.Endpoint.AuthURL = Endpoint.AuthURL
}
if cfg.Endpoint.TokenURL == "" {
cfg.Endpoint.TokenURL = Endpoint.TokenURL
if params.TokenURL != "" {
cfg.Endpoint.TokenURL = params.TokenURL
} else {
cfg.Endpoint.TokenURL = Endpoint.TokenURL
}
}
if params.TLSConfig != nil {
ctx = context.WithValue(ctx, internal.HTTPClient, customHTTPClient(params.TLSConfig))
}
tok := &oauth2.Token{RefreshToken: f.RefreshToken}
return cfg.TokenSource(ctx, tok), nil
Expand Down Expand Up @@ -275,3 +289,26 @@ func (cs computeSource) Token() (*oauth2.Token, error) {
"oauth2.google.serviceAccount": acct,
}), nil
}

// customHTTPClient constructs an HTTPClient using the provided tlsConfig, to support mTLS.
func customHTTPClient(tlsConfig *tls.Config) *http.Client {
trans := baseTransport()
trans.TLSClientConfig = tlsConfig
return &http.Client{Transport: trans}
}

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

0 comments on commit d171fca

Please sign in to comment.