idtoken: support using ID Tokens

This commit adds two new features to our apis that support the use
of ID tokens.

1. Users now have functions that fetch ID tokens for them:
  - NewClient
  - NewTokenSource
Both of these are configured to auto-refresh tokens based off of
Application Default Credentials or provided options.

2. Users can now validate ID tokens with the following:
  - Validator.Validate
  - Validate
These methods decode the provided token to figure out what kind of
encrption was used to sign the token. This is then validated
against the user's JWKs that are found at known Google endpoint.
Because of this, these methods can only be used to validate Google
ID tokens at this time. A common use case where a user would want
to validate these tokens is if they are using App Eninge with IAP.

Change-Id: I0877eff081b030eac55759444870c950cd028a14
Reviewed-on: https://code-review.googlesource.com/c/google-api-go-client/+/53510
Reviewed-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Broadfoot <cbro@google.com>
Reviewed-by: Tyler Bui-Palsulich <tbp@google.com>
diff --git a/.gitignore b/.gitignore
index c643732..f5470ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,4 +13,7 @@
 *~
 *.out
 *.test
-*.exe
\ No newline at end of file
+*.exe
+
+.idea/*
+.vscode/*
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 46efc62..4e31d86 100644
--- a/go.mod
+++ b/go.mod
@@ -3,20 +3,17 @@
 go 1.11
 
 require (
-	cloud.google.com/go v0.38.0 // indirect
-	github.com/google/go-cmp v0.3.0
+	cloud.google.com/go v0.56.0
+	github.com/google/go-cmp v0.4.0
 	github.com/googleapis/gax-go/v2 v2.0.5
-	github.com/hashicorp/golang-lru v0.5.1 // indirect
-	go.opencensus.io v0.21.0
-	golang.org/x/lint v0.0.0-20190409202823-959b441ac422
-	golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c // indirect
-	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
-	golang.org/x/sync v0.0.0-20190423024810-112230192c58
-	golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b
-	golang.org/x/text v0.3.2 // indirect
-	golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135
-	google.golang.org/appengine v1.5.0
-	google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55
-	google.golang.org/grpc v1.27.0
-	honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc
+	go.opencensus.io v0.22.3
+	golang.org/x/lint v0.0.0-20200302205851-738671d3881b
+	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
+	golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
+	golang.org/x/sys v0.0.0-20200331124033-c3d80250170d
+	golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4
+	google.golang.org/appengine v1.6.5
+	google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940
+	google.golang.org/grpc v1.28.0
+	honnef.co/go/tools v0.0.1-2020.1.3
 )
diff --git a/go.sum b/go.sum
index 75ae672..38d943d 100644
--- a/go.sum
+++ b/go.sum
@@ -2,91 +2,299 @@
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI=
 golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/idtoken/cache.go b/idtoken/cache.go
new file mode 100644
index 0000000..4af90f9
--- /dev/null
+++ b/idtoken/cache.go
@@ -0,0 +1,107 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idtoken
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+type cachingClient struct {
+	client *http.Client
+	mu     sync.Mutex
+	certs  map[string]*cachedResponse
+}
+
+func newCachingClient(client *http.Client) *cachingClient {
+	return &cachingClient{
+		client: client,
+		certs:  make(map[string]*cachedResponse, 2),
+	}
+}
+
+type cachedResponse struct {
+	resp *certResponse
+	exp  time.Time
+}
+
+func (c *cachingClient) getCert(ctx context.Context, url string) (*certResponse, error) {
+	if response, ok := c.get(url); ok {
+		return response, nil
+	}
+	req, err := http.NewRequest(http.MethodGet, url, nil)
+	if err != nil {
+		return nil, err
+	}
+	req = req.WithContext(ctx)
+	resp, err := c.client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("idtoken: unable to retrieve cert, got status code %d", resp.StatusCode)
+	}
+
+	certResp := &certResponse{}
+	if err := json.NewDecoder(resp.Body).Decode(certResp); err != nil {
+		return nil, err
+
+	}
+	c.set(url, certResp, resp.Header)
+	return certResp, nil
+}
+
+func (c *cachingClient) get(url string) (*certResponse, bool) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	cachedResp, ok := c.certs[url]
+	if !ok {
+		return nil, false
+	}
+	if time.Now().After(cachedResp.exp) {
+		return nil, false
+	}
+	return cachedResp.resp, true
+}
+
+func (c *cachingClient) set(url string, resp *certResponse, headers http.Header) {
+	exp := calculateExpireTime(headers)
+	c.mu.Lock()
+	c.certs[url] = &cachedResponse{resp: resp, exp: exp}
+	c.mu.Unlock()
+}
+
+// calculateExpireTime will determine the expire time for the cache based on
+// HTTP headers. If there is any difficulty reading the headers the fallback is
+// to set the cache to expire now.
+func calculateExpireTime(headers http.Header) time.Time {
+	var maxAge int
+	cc := strings.Split(headers.Get("cache-control"), ",")
+	for _, v := range cc {
+		if strings.Contains(v, "max-age") {
+			ss := strings.Split(v, "=")
+			if len(ss) < 2 {
+				return time.Now()
+			}
+			ma, err := strconv.Atoi(ss[1])
+			if err != nil {
+				return time.Now()
+			}
+			maxAge = ma
+		}
+	}
+	age, err := strconv.Atoi(headers.Get("age"))
+	if err != nil {
+		return time.Now()
+	}
+	return time.Now().Add(time.Duration(maxAge-age) * time.Second)
+}
diff --git a/idtoken/cache_test.go b/idtoken/cache_test.go
new file mode 100644
index 0000000..1e4b172
--- /dev/null
+++ b/idtoken/cache_test.go
@@ -0,0 +1,50 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idtoken
+
+import (
+	"net/http"
+	"testing"
+	"time"
+)
+
+func TestCacheHit(t *testing.T) {
+	dummyResp := &certResponse{
+		Keys: []jwk{
+			{
+				Kid: "123",
+			},
+		},
+	}
+	cache := newCachingClient(nil)
+	// Cache should be empty
+	cert, ok := cache.get(googleSACertsURL)
+	if ok || cert != nil {
+		t.Fatal("cache for SA certs should be empty")
+	}
+
+	// Add an item, but make it expire now
+	cache.set(googleSACertsURL, dummyResp, make(http.Header))
+	cert, ok = cache.get(googleSACertsURL)
+	if ok || cert != nil {
+		t.Fatal("cache for SA certs should be expired")
+	}
+
+	// Add an item that expires in 1 seconds
+	h := make(http.Header)
+	h.Set("age", "0")
+	h.Set("cache-control", "public, max-age=1, must-revalidate, no-transform")
+	cache.set(googleSACertsURL, dummyResp, h)
+	cert, ok = cache.get(googleSACertsURL)
+	if !ok || cert == nil || cert.Keys[0].Kid != "123" {
+		t.Fatal("cache for SA certs have a resp")
+	}
+	// Wait
+	time.Sleep(2 * time.Second)
+	cert, ok = cache.get(googleSACertsURL)
+	if ok || cert != nil {
+		t.Fatal("cache for SA certs should be expired")
+	}
+}
diff --git a/idtoken/compute.go b/idtoken/compute.go
new file mode 100644
index 0000000..1b5e045
--- /dev/null
+++ b/idtoken/compute.go
@@ -0,0 +1,56 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idtoken
+
+import (
+	"fmt"
+	"net/url"
+	"time"
+
+	"cloud.google.com/go/compute/metadata"
+	"golang.org/x/oauth2"
+
+	"google.golang.org/api/internal"
+)
+
+// computeTokenSource checks if this code is being run on GCE. If it is, it will
+// use the metadata service to build a TokenSource that fetches ID tokens.
+func computeTokenSource(audience string, ds *internal.DialSettings) (oauth2.TokenSource, error) {
+	if ds.CustomClaims != nil {
+		return nil, fmt.Errorf("idtoken: WithCustomClaims can't be used with the metadata serive, please provide a service account if you would like to use this feature")
+	}
+	ts := computeIDTokenSource{
+		audience: audience,
+	}
+	tok, err := ts.Token()
+	if err != nil {
+		return nil, err
+	}
+	return oauth2.ReuseTokenSource(tok, ts), nil
+}
+
+type computeIDTokenSource struct {
+	audience string
+}
+
+func (c computeIDTokenSource) Token() (*oauth2.Token, error) {
+	v := url.Values{}
+	v.Set("audience", c.audience)
+	v.Set("format", "full")
+	urlSuffix := "instance/service-accounts/default/identity?" + v.Encode()
+	res, err := metadata.Get(urlSuffix)
+	if err != nil {
+		return nil, err
+	}
+	if res == "" {
+		return nil, fmt.Errorf("idtoken: invalid response from metadata service")
+	}
+	return &oauth2.Token{
+		AccessToken: res,
+		TokenType:   "bearer",
+		// Compute tokens are valid for one hour, leave a little buffer
+		Expiry: time.Now().Add(55 * time.Minute),
+	}, nil
+}
diff --git a/idtoken/doc.go b/idtoken/doc.go
new file mode 100644
index 0000000..6181aaf
--- /dev/null
+++ b/idtoken/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package idtoken provides utilities for creating authenticated transorts with
+// ID Tokens for Google HTTP APIs. It also provides methods to validate Google
+// issued ID tokens.
+package idtoken
diff --git a/idtoken/idtoken.go b/idtoken/idtoken.go
new file mode 100644
index 0000000..a5ee882
--- /dev/null
+++ b/idtoken/idtoken.go
@@ -0,0 +1,170 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idtoken
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"cloud.google.com/go/compute/metadata"
+	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/google"
+
+	"google.golang.org/api/internal"
+	"google.golang.org/api/option"
+	htransport "google.golang.org/api/transport/http"
+)
+
+// ClientOption is aliased so relevant options are easily found in the docs.
+
+// ClientOption is for configuring a Google API client or transport.
+type ClientOption = option.ClientOption
+
+// NewClient creates a HTTP Client that automatically adds an ID token to each
+// request via an Authorization header. The token will have have the audience
+// provided and be configured with the supplied options. The parameter audience
+// may not be empty.
+func NewClient(ctx context.Context, audience string, opts ...ClientOption) (*http.Client, error) {
+	var ds internal.DialSettings
+	for _, opt := range opts {
+		opt.Apply(&ds)
+	}
+	if err := ds.Validate(); err != nil {
+		return nil, err
+	}
+	if ds.NoAuth {
+		return nil, fmt.Errorf("idtoken: option.WithoutAuthentication not supported")
+	}
+	if ds.APIKey != "" {
+		return nil, fmt.Errorf("idtoken: option.WithAPIKey not supported")
+	}
+	if ds.TokenSource != nil {
+		return nil, fmt.Errorf("idtoken: option.WithTokenSource not supported")
+	}
+
+	ts, err := NewTokenSource(ctx, audience, opts...)
+	if err != nil {
+		return nil, err
+	}
+	opts = append(opts, option.WithTokenSource(ts))
+	t, err := htransport.NewTransport(ctx, http.DefaultTransport, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return &http.Client{Transport: t}, nil
+}
+
+// NewTokenSource creates a TokenSource that returns ID tokens with the audience
+// provided and configured with the supplied options. The parameter audience may
+// not be empty.
+func NewTokenSource(ctx context.Context, audience string, opts ...ClientOption) (oauth2.TokenSource, error) {
+	if audience == "" {
+		return nil, fmt.Errorf("idtoken: must supply a non-empty audience")
+	}
+	var ds internal.DialSettings
+	for _, opt := range opts {
+		opt.Apply(&ds)
+	}
+	if err := ds.Validate(); err != nil {
+		return nil, err
+	}
+	if ds.TokenSource != nil {
+		return nil, fmt.Errorf("idtoken: option.WithTokenSource not supported")
+	}
+	return newTokenSource(ctx, audience, &ds)
+}
+
+func newTokenSource(ctx context.Context, audience string, ds *internal.DialSettings) (oauth2.TokenSource, error) {
+	creds, err := internal.Creds(ctx, ds)
+	if err != nil {
+		return nil, err
+	}
+	if len(creds.JSON) > 0 {
+		return tokenSourceFromBytes(ctx, creds.JSON, audience, ds)
+	}
+	// If internal.Creds did not return a response with JSON fallback to the
+	// metadata service as the creds.TokenSource is not an ID token.
+	if metadata.OnGCE() {
+		return computeTokenSource(audience, ds)
+	}
+	return nil, fmt.Errorf("idtoken: couldn't find any credentials")
+}
+
+func tokenSourceFromBytes(ctx context.Context, data []byte, audience string, ds *internal.DialSettings) (oauth2.TokenSource, error) {
+	if err := isServiceAccount(data); err != nil {
+		return nil, err
+	}
+	cfg, err := google.JWTConfigFromJSON(data, ds.Scopes...)
+	if err != nil {
+		return nil, err
+	}
+
+	customClaims := ds.CustomClaims
+	if customClaims == nil {
+		customClaims = make(map[string]interface{})
+	}
+	customClaims["target_audience"] = audience
+
+	cfg.PrivateClaims = customClaims
+	cfg.UseIDToken = true
+
+	ts := cfg.TokenSource(ctx)
+	tok, err := ts.Token()
+	if err != nil {
+		return nil, err
+	}
+	return oauth2.ReuseTokenSource(tok, ts), nil
+}
+
+func isServiceAccount(data []byte) error {
+	if len(data) == 0 {
+		return fmt.Errorf("idtoken: credential provided is 0 bytes")
+	}
+	var f struct {
+		Type string `json:"type"`
+	}
+	if err := json.Unmarshal(data, &f); err != nil {
+		return err
+	}
+	if f.Type != "service_account" {
+		return fmt.Errorf("idtoken: credential must be service_account, found %q", f.Type)
+	}
+	return nil
+}
+
+// WithCustomClaims optionally specifies custom private claims for an ID token.
+func WithCustomClaims(customClaims map[string]interface{}) ClientOption {
+	return withCustomClaims(customClaims)
+}
+
+type withCustomClaims map[string]interface{}
+
+func (w withCustomClaims) Apply(o *internal.DialSettings) {
+	o.CustomClaims = w
+}
+
+// WithCredentialsFile returns a ClientOption that authenticates
+// API calls with the given service account or refresh token JSON
+// credentials file.
+func WithCredentialsFile(filename string) ClientOption {
+	return option.WithCredentialsFile(filename)
+}
+
+// WithCredentialsJSON returns a ClientOption that authenticates
+// API calls with the given service account or refresh token JSON
+// credentials.
+func WithCredentialsJSON(p []byte) ClientOption {
+	return option.WithCredentialsJSON(p)
+}
+
+// WithHTTPClient returns a ClientOption that specifies the HTTP client to use
+// as the basis of communications. This option may only be used with services
+// that support HTTP as their communication transport. When used, the
+// WithHTTPClient option takes precedent over all other supplied options.
+func WithHTTPClient(client *http.Client) ClientOption {
+	return option.WithHTTPClient(client)
+}
diff --git a/idtoken/validate.go b/idtoken/validate.go
new file mode 100644
index 0000000..518528b
--- /dev/null
+++ b/idtoken/validate.go
@@ -0,0 +1,296 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idtoken
+
+import (
+	"context"
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/sha256"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"math/big"
+	"net/http"
+	"strings"
+
+	htransport "google.golang.org/api/transport/http"
+)
+
+const (
+	es256KeySize      int    = 32
+	googleIAPCertsURL string = "https://www.gstatic.com/iap/verify/public_key-jwk"
+	googleSACertsURL  string = "https://www.googleapis.com/oauth2/v3/certs"
+)
+
+var defaultValidator = &Validator{client: newCachingClient(http.DefaultClient)}
+
+// Payload represents a decoded payload of an ID Token.
+type Payload struct {
+	Issuer   string                 `json:"iss"`
+	Audience string                 `json:"aud"`
+	Expires  int64                  `json:"exp"`
+	IssuedAt int64                  `json:"iat"`
+	Subject  string                 `json:"sub,omitempty"`
+	Claims   map[string]interface{} `json:"-"`
+}
+
+// jwt represents the segments of a jwt and exposes convenience methods for
+// working with the different segments.
+type jwt struct {
+	header    string
+	payload   string
+	signature string
+}
+
+// jwtHeader represents a parted jwt's header segment.
+type jwtHeader struct {
+	Algorithm string `json:"alg"`
+	Type      string `json:"typ"`
+	KeyID     string `json:"kid"`
+}
+
+// certResponse represents a list jwks. It is the format returned from known
+// Google cert endpoints.
+type certResponse struct {
+	Keys []jwk `json:"keys"`
+}
+
+// jwk is a simplified representation of a standard jwk. It only includes the
+// fields used by Google's cert endpoints.
+type jwk struct {
+	Alg string `json:"alg"`
+	Crv string `json:"crv"`
+	Kid string `json:"kid"`
+	Kty string `json:"kty"`
+	Use string `json:"use"`
+	E   string `json:"e"`
+	N   string `json:"n"`
+	X   string `json:"x"`
+	Y   string `json:"y"`
+}
+
+// Validator provides a way to validate Google ID Tokens with a user provided
+// http.Client.
+type Validator struct {
+	client *cachingClient
+}
+
+// NewValidator creates a Validator that uses the options provided to configure
+// a the internal http.Client that will be used to make requests to fetch JWKs.
+func NewValidator(ctx context.Context, opts ...ClientOption) (*Validator, error) {
+	client, _, err := htransport.NewClient(ctx, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return &Validator{client: newCachingClient(client)}, nil
+}
+
+// Validate is used to validate the provided idToken with a known Google cert
+// URL. If audience is not empty the audience claim of the Token is validated.
+// Upon successful validation a parsed token Payload is returned allowing the
+// caller to validate any additional claims.
+func (v *Validator) Validate(ctx context.Context, idToken string, audience string) (*Payload, error) {
+	return v.validate(ctx, idToken, audience)
+}
+
+// Validate is used to validate the provided idToken with a known Google cert
+// URL. If audience is not empty the audience claim of the Token is validated.
+// Upon successful validation a parsed token Payload is returned allowing the
+// caller to validate any additional claims.
+func Validate(ctx context.Context, idToken string, audience string) (*Payload, error) {
+	// TODO(codyoss): consider adding a check revoked version of the api. See: https://pkg.go.dev/firebase.google.com/go/auth?tab=doc#Client.VerifyIDTokenAndCheckRevoked
+	return defaultValidator.validate(ctx, idToken, audience)
+}
+
+func (v *Validator) validate(ctx context.Context, idToken string, audience string) (*Payload, error) {
+	jwt, err := parseJWT(idToken)
+	if err != nil {
+		return nil, err
+	}
+	header, err := jwt.parsedHeader()
+	if err != nil {
+		return nil, err
+	}
+	payload, err := jwt.parsedPayload()
+	if err != nil {
+		return nil, err
+	}
+	sig, err := jwt.decodedSignature()
+	if err != nil {
+		return nil, err
+	}
+
+	if audience != "" && payload.Audience != audience {
+		return nil, fmt.Errorf("idtoken: audience provided does not match aud claim in the JWT")
+	}
+
+	switch header.Algorithm {
+	case "RS256":
+		if err := v.validateRS256(ctx, header.KeyID, jwt.hashedContent(), sig); err != nil {
+			return nil, err
+		}
+	case "ES256":
+		if err := v.validateES256(ctx, header.KeyID, jwt.hashedContent(), sig); err != nil {
+			return nil, err
+		}
+	default:
+		return nil, fmt.Errorf("idtoken: expected JWT signed with RS256 or ES256 but found %q", header.Algorithm)
+	}
+
+	return payload, nil
+}
+
+func (v *Validator) validateRS256(ctx context.Context, keyID string, hashedContent []byte, sig []byte) error {
+	certResp, err := v.client.getCert(ctx, googleSACertsURL)
+	if err != nil {
+		return err
+	}
+	j, err := findMatchingKey(certResp, keyID)
+	if err != nil {
+		return err
+	}
+	dn, err := decode(j.N)
+	if err != nil {
+		return err
+	}
+	de, err := decode(j.E)
+	if err != nil {
+		return err
+	}
+
+	pk := &rsa.PublicKey{
+		N: new(big.Int).SetBytes(dn),
+		E: int(new(big.Int).SetBytes(de).Int64()),
+	}
+	return rsa.VerifyPKCS1v15(pk, crypto.SHA256, hashedContent, sig)
+}
+
+func (v *Validator) validateES256(ctx context.Context, keyID string, hashedContent []byte, sig []byte) error {
+	certResp, err := v.client.getCert(ctx, googleIAPCertsURL)
+	if err != nil {
+		return err
+	}
+	j, err := findMatchingKey(certResp, keyID)
+	if err != nil {
+		return err
+	}
+	dx, err := decode(j.X)
+	if err != nil {
+		return err
+	}
+	dy, err := decode(j.Y)
+	if err != nil {
+		return err
+	}
+
+	pk := &ecdsa.PublicKey{
+		Curve: elliptic.P256(),
+		X:     new(big.Int).SetBytes(dx),
+		Y:     new(big.Int).SetBytes(dy),
+	}
+	r := big.NewInt(0).SetBytes(sig[:es256KeySize])
+	s := big.NewInt(0).SetBytes(sig[es256KeySize:])
+	if valid := ecdsa.Verify(pk, hashedContent, r, s); !valid {
+		return fmt.Errorf("idtoken: ES256 signature not valid")
+	}
+	return nil
+}
+
+func findMatchingKey(response *certResponse, keyID string) (*jwk, error) {
+	if response == nil {
+		return nil, fmt.Errorf("idtoken: cert response is nil")
+	}
+	for _, v := range response.Keys {
+		if v.Kid == keyID {
+			return &v, nil
+		}
+	}
+	return nil, fmt.Errorf("idtoken: could not find matching cert keyId for the token provided")
+}
+
+func parseJWT(idToken string) (*jwt, error) {
+	segments := strings.Split(idToken, ".")
+	if len(segments) != 3 {
+		return nil, fmt.Errorf("idtoken: invalid token, token must have three segments; found %d", len(segments))
+	}
+	return &jwt{
+		header:    segments[0],
+		payload:   segments[1],
+		signature: segments[2],
+	}, nil
+}
+
+// decodedHeader base64 decodes the header segment.
+func (j *jwt) decodedHeader() ([]byte, error) {
+	dh, err := decode(j.header)
+	if err != nil {
+		return nil, fmt.Errorf("idtoken: unable to decode JWT header: %v", err)
+	}
+	return dh, nil
+}
+
+// decodedPayload base64 payload the header segment.
+func (j *jwt) decodedPayload() ([]byte, error) {
+	p, err := decode(j.payload)
+	if err != nil {
+		return nil, fmt.Errorf("idtoken: unable to decode JWT payload: %v", err)
+	}
+	return p, nil
+}
+
+// decodedPayload base64 payload the header segment.
+func (j *jwt) decodedSignature() ([]byte, error) {
+	p, err := decode(j.signature)
+	if err != nil {
+		return nil, fmt.Errorf("idtoken: unable to decode JWT signature: %v", err)
+	}
+	return p, nil
+}
+
+// parsedHeader returns a struct representing a JWT header.
+func (j *jwt) parsedHeader() (jwtHeader, error) {
+	var h jwtHeader
+	dh, err := j.decodedHeader()
+	if err != nil {
+		return h, err
+	}
+	err = json.Unmarshal(dh, &h)
+	if err != nil {
+		return h, fmt.Errorf("idtoken: unable to unmarshal JWT header: %v", err)
+	}
+	return h, nil
+}
+
+// parsedPayload returns a struct representing a JWT payload.
+func (j *jwt) parsedPayload() (*Payload, error) {
+	var p Payload
+	dp, err := j.decodedPayload()
+	if err != nil {
+		return nil, err
+	}
+	err = json.Unmarshal(dp, &p)
+	if err != nil {
+		return nil, fmt.Errorf("idtoken: unable to unmarshal JWT payload: %v", err)
+	}
+	return &p, nil
+}
+
+// hashedContent gets the SHA256 checksum for verification of the JWT.
+func (j *jwt) hashedContent() []byte {
+	signedContent := j.header + "." + j.payload
+	hashed := sha256.Sum256([]byte(signedContent))
+	return hashed[:]
+}
+
+func (j *jwt) String() string {
+	return fmt.Sprintf("%s.%s.%s", j.header, j.payload, j.signature)
+}
+
+func decode(s string) ([]byte, error) {
+	return base64.RawURLEncoding.DecodeString(s)
+}
diff --git a/idtoken/validate_test.go b/idtoken/validate_test.go
new file mode 100644
index 0000000..54ff07c
--- /dev/null
+++ b/idtoken/validate_test.go
@@ -0,0 +1,199 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idtoken
+
+import (
+	"bytes"
+	"context"
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/rsa"
+	"encoding/base64"
+	"encoding/json"
+	"io/ioutil"
+	"math/big"
+	"net/http"
+	"testing"
+
+	"google.golang.org/api/option"
+)
+
+const (
+	keyID        = "1234"
+	testAudience = "test-audience"
+)
+
+func TestValidateRS256(t *testing.T) {
+	idToken, pk := createRS256JWT(t)
+	tests := []struct {
+		name    string
+		keyID   string
+		n       *big.Int
+		e       int
+		wantErr bool
+	}{
+		{name: "works", keyID: keyID, n: pk.N, e: pk.E, wantErr: false},
+		{name: "no matching key", keyID: "5678", n: pk.N, e: pk.E, wantErr: true},
+		{name: "sig does not match", keyID: keyID, n: new(big.Int).SetBytes([]byte("42")), e: 42, wantErr: true},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client := &http.Client{
+				Transport: RoundTripFn(func(req *http.Request) *http.Response {
+					cr := certResponse{
+						Keys: []jwk{
+							{
+								Kid: tt.keyID,
+								N:   base64.RawURLEncoding.EncodeToString(tt.n.Bytes()),
+								E:   base64.RawURLEncoding.EncodeToString(new(big.Int).SetInt64(int64(tt.e)).Bytes()),
+							},
+						},
+					}
+					b, err := json.Marshal(&cr)
+					if err != nil {
+						t.Fatalf("unable to marshal response: %v", err)
+					}
+					return &http.Response{
+						StatusCode: 200,
+						Body:       ioutil.NopCloser(bytes.NewReader(b)),
+						Header:     make(http.Header),
+					}
+				}),
+			}
+
+			v, err := NewValidator(context.Background(), option.WithHTTPClient(client))
+			if err != nil {
+				t.Fatalf("NewValidator(...) = %q, want nil", err)
+			}
+			payload, err := v.Validate(context.Background(), idToken, testAudience)
+			if !tt.wantErr && err != nil {
+				t.Fatalf("Validate(ctx, %s, %s) = %q, want nil", idToken, testAudience, err)
+			}
+			if !tt.wantErr && payload.Audience != testAudience {
+				t.Fatalf("got %v, want %v", payload.Audience, testAudience)
+			}
+		})
+	}
+}
+
+func TestValidateES256(t *testing.T) {
+	idToken, pk := createES256JWT(t)
+	tests := []struct {
+		name    string
+		keyID   string
+		x       *big.Int
+		y       *big.Int
+		wantErr bool
+	}{
+		{name: "works", keyID: keyID, x: pk.X, y: pk.Y, wantErr: false},
+		{name: "no matching key", keyID: "5678", x: pk.X, y: pk.Y, wantErr: true},
+		{name: "sig does not match", keyID: keyID, x: new(big.Int), y: new(big.Int), wantErr: true},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client := &http.Client{
+				Transport: RoundTripFn(func(req *http.Request) *http.Response {
+					cr := certResponse{
+						Keys: []jwk{
+							{
+								Kid: tt.keyID,
+								X:   base64.RawURLEncoding.EncodeToString(tt.x.Bytes()),
+								Y:   base64.RawURLEncoding.EncodeToString(tt.y.Bytes()),
+							},
+						},
+					}
+					b, err := json.Marshal(&cr)
+					if err != nil {
+						t.Fatalf("unable to marshal response: %v", err)
+					}
+					return &http.Response{
+						StatusCode: 200,
+						Body:       ioutil.NopCloser(bytes.NewReader(b)),
+						Header:     make(http.Header),
+					}
+				}),
+			}
+
+			v, err := NewValidator(context.Background(), option.WithHTTPClient(client))
+			if err != nil {
+				t.Fatalf("NewValidator(...) = %q, want nil", err)
+			}
+			payload, err := v.Validate(context.Background(), idToken, testAudience)
+			if !tt.wantErr && err != nil {
+				t.Fatalf("Validate(ctx, %s, %s) = %q, want nil", idToken, testAudience, err)
+			}
+			if !tt.wantErr && payload.Audience != testAudience {
+				t.Fatalf("got %v, want %v", payload.Audience, testAudience)
+			}
+		})
+	}
+}
+
+func createES256JWT(t *testing.T) (string, ecdsa.PublicKey) {
+	t.Helper()
+	token := commonToken(t, "ES256")
+	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("unable to generate key: %v", err)
+	}
+	r, s, err := ecdsa.Sign(rand.Reader, privateKey, token.hashedContent())
+	if err != nil {
+		t.Fatalf("unable to sign content: %v", err)
+	}
+	var sig []byte
+	sig = append(sig, r.Bytes()...)
+	sig = append(sig, s.Bytes()...)
+	token.signature = base64.RawURLEncoding.EncodeToString(sig)
+	return token.String(), privateKey.PublicKey
+}
+
+func createRS256JWT(t *testing.T) (string, rsa.PublicKey) {
+	t.Helper()
+	token := commonToken(t, "RS256")
+	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		t.Fatalf("unable to generate key: %v", err)
+	}
+	sig, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, token.hashedContent())
+	if err != nil {
+		t.Fatalf("unable to sign content: %v", err)
+	}
+	token.signature = base64.RawURLEncoding.EncodeToString(sig)
+	return token.String(), privateKey.PublicKey
+}
+
+func commonToken(t *testing.T, alg string) *jwt {
+	t.Helper()
+	header := jwtHeader{
+		KeyID:     keyID,
+		Algorithm: alg,
+		Type:      "JWT",
+	}
+	payload := Payload{
+		Issuer:   "example.com",
+		Audience: testAudience,
+	}
+
+	hb, err := json.Marshal(&header)
+	if err != nil {
+		t.Fatalf("unable to marshall header: %v", err)
+	}
+	pb, err := json.Marshal(&payload)
+	if err != nil {
+		t.Fatalf("unable to marshall payload: %v", err)
+	}
+	eb := base64.RawURLEncoding.EncodeToString(hb)
+	ep := base64.RawURLEncoding.EncodeToString(pb)
+	return &jwt{
+		header:  eb,
+		payload: ep,
+	}
+}
+
+type RoundTripFn func(req *http.Request) *http.Response
+
+func (f RoundTripFn) RoundTrip(req *http.Request) (*http.Response, error) { return f(req), nil }
diff --git a/integration-tests/idtoken/idtoken_test.go b/integration-tests/idtoken/idtoken_test.go
new file mode 100644
index 0000000..2ff8876
--- /dev/null
+++ b/integration-tests/idtoken/idtoken_test.go
@@ -0,0 +1,47 @@
+// Copyright 2020 Google LLC.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build integration
+
+package idtoken
+
+import (
+	"context"
+	"net/http"
+	"os"
+	"strings"
+	"testing"
+
+	"google.golang.org/api/idtoken"
+	"google.golang.org/api/option"
+)
+
+const (
+	envCredentialFile = "API_GO_CLIENT_SA"
+	envTokenAudience  = "API_GO_CLIENT_TOKEN_AUDIENCE"
+)
+
+func TestNewTokenSource(t *testing.T) {
+	aud := os.Getenv(envTokenAudience)
+	ts, err := idtoken.NewTokenSource(context.Background(), aud, option.WithCredentialsFile(os.Getenv(envCredentialFile)))
+	if err != nil {
+		t.Fatalf("unable to create TokenSource: %v", err)
+	}
+	tok, err := ts.Token()
+	if err != nil {
+		t.Fatalf("unable to retrieve Token: %v", err)
+	}
+	req := &http.Request{Header: make(http.Header)}
+	tok.SetAuthHeader(req)
+	if !strings.HasPrefix(req.Header.Get("Authorization"), "Bearer ") {
+		t.Fatalf("token should sign requests with Bearer Authorization header")
+	}
+	validTok, err := idtoken.Validate(context.Background(), tok.AccessToken, aud)
+	if err != nil {
+		t.Fatalf("token validation failed: %v", err)
+	}
+	if validTok.Audience != aud {
+		t.Fatalf("got %q, want %q", validTok.Audience, aud)
+	}
+}
diff --git a/internal/settings.go b/internal/settings.go
index 33ba7ac..0d8210b 100644
--- a/internal/settings.go
+++ b/internal/settings.go
@@ -36,6 +36,7 @@
 	NoAuth            bool
 	TelemetryDisabled bool
 	ClientCertSource  func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
+	CustomClaims      map[string]interface{}
 
 	// Google API system parameters. For more information please read:
 	// https://cloud.google.com/apis/docs/system-parameters