all: make use of oauth.Token.ExpiresIn

With https://go.dev/issue/61417 implemented, we can use the token type
directly to unmarshal the JSON fields for the wire format.

While here, remove all uses of the deprecated ioutil package
as suggested by gopls while making these changes.

Change-Id: I79d82374643007a21b5b3d9a8117bed81273eca5
Reviewed-on: https://go-review.googlesource.com/c/oauth2/+/614415
Reviewed-by: Sean Liao <sean@liao.dev>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Daniel Martí 2024-09-19 15:49:54 +01:00 committed by Sean Liao
parent 65c15a3514
commit 1c06e8705e
19 changed files with 50 additions and 73 deletions

View File

@ -7,7 +7,6 @@ package clientcredentials
import (
"context"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@ -36,9 +35,9 @@ func TestTokenSourceGrantTypeOverride(t *testing.T) {
wantGrantType := "password"
var gotGrantType string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("ioutil.ReadAll(r.Body) == %v, %v, want _, <nil>", body, err)
t.Errorf("io.ReadAll(r.Body) == %v, %v, want _, <nil>", body, err)
}
if err := r.Body.Close(); err != nil {
t.Errorf("r.Body.Close() == %v, want <nil>", err)
@ -81,7 +80,7 @@ func TestTokenRequest(t *testing.T) {
if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
t.Errorf("Content-Type header = %q; want %q", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
r.Body.Close()
}
@ -123,7 +122,7 @@ func TestTokenRefreshRequest(t *testing.T) {
if got, want := headerContentType, "application/x-www-form-urlencoded"; got != want {
t.Errorf("Content-Type = %q; want %q", got, want)
}
body, _ := ioutil.ReadAll(r.Body)
body, _ := io.ReadAll(r.Body)
const want = "audience=audience1&grant_type=client_credentials&scope=scope1+scope2"
if string(body) != want {
t.Errorf("Unexpected refresh token payload.\n got: %s\nwant: %s\n", body, want)

View File

@ -39,7 +39,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
@ -198,7 +198,7 @@ func (dts downscopingTokenSource) Token() (*oauth2.Token, error) {
return nil, fmt.Errorf("unable to generate POST Request %v", err)
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("downscope: unable to read response body: %v", err)
}

View File

@ -6,7 +6,7 @@ package downscope
import (
"context"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
@ -27,7 +27,7 @@ func Test_DownscopedTokenSource(t *testing.T) {
if r.URL.String() != "/" {
t.Errorf("Unexpected request URL, %v is found", r.URL)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("Failed to read request body: %v", err)
}

View File

@ -7,9 +7,9 @@ package google_test
import (
"context"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
@ -60,7 +60,7 @@ func ExampleJWTConfigFromJSON() {
// To create a service account client, click "Create new Client ID",
// select "Service Account", and click "Create Client ID". A JSON
// key file will then be downloaded to your computer.
data, err := ioutil.ReadFile("/path/to/your-project-key.json")
data, err := os.ReadFile("/path/to/your-project-key.json")
if err != nil {
log.Fatal(err)
}
@ -136,7 +136,7 @@ func ExampleComputeTokenSource() {
func ExampleCredentialsFromJSON() {
ctx := context.Background()
data, err := ioutil.ReadFile("/path/to/key-file.json")
data, err := os.ReadFile("/path/to/key-file.json")
if err != nil {
log.Fatal(err)
}

View File

@ -14,7 +14,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
@ -170,7 +169,7 @@ func requestDataHash(req *http.Request) (string, error) {
}
defer requestBody.Close()
requestData, err = ioutil.ReadAll(io.LimitReader(requestBody, 1<<20))
requestData, err = io.ReadAll(io.LimitReader(requestBody, 1<<20))
if err != nil {
return "", err
}
@ -419,7 +418,7 @@ func (cs *awsCredentialSource) getAWSSessionToken() (string, error) {
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return "", err
}
@ -462,7 +461,7 @@ func (cs *awsCredentialSource) getRegion(headers map[string]string) (string, err
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return "", err
}
@ -531,7 +530,7 @@ func (cs *awsCredentialSource) getMetadataSecurityCredentials(roleName string, h
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return result, err
}
@ -564,7 +563,7 @@ func (cs *awsCredentialSource) getMetadataRoleName(headers map[string]string) (s
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return "", err
}

View File

@ -8,7 +8,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
@ -77,7 +77,7 @@ func run(t *testing.T, config *Config, tets *testExchangeTokenServer) (*oauth2.T
if got, want := headerMetrics, tets.metricsHeader; got != want {
t.Errorf("got %v but want %v", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("Failed reading request body: %s.", err)
}
@ -131,7 +131,7 @@ func createImpersonationServer(urlWanted, authWanted, bodyWanted, response strin
if got, want := headerContentType, "application/json"; got != want {
t.Errorf("got %v but want %v", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("Failed reading request body: %v.", err)
}
@ -160,7 +160,7 @@ func createTargetServer(metricsHeaderWanted string, t *testing.T) *httptest.Serv
if got, want := headerMetrics, metricsHeaderWanted; got != want {
t.Errorf("got %v but want %v", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("Failed reading request body: %v.", err)
}

View File

@ -11,7 +11,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"regexp"
@ -258,7 +257,7 @@ func (cs executableCredentialSource) getTokenFromOutputFile() (token string, err
}
defer file.Close()
data, err := ioutil.ReadAll(io.LimitReader(file, 1<<20))
data, err := io.ReadAll(io.LimitReader(file, 1<<20))
if err != nil || len(data) == 0 {
// Cachefile exists, but no data found. Get new credential.
return "", nil

View File

@ -8,7 +8,6 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sort"
"testing"
@ -614,7 +613,7 @@ func TestRetrieveExecutableSubjectTokenSuccesses(t *testing.T) {
}
func TestRetrieveOutputFileSubjectTokenNotJSON(t *testing.T) {
outputFile, err := ioutil.TempFile("testdata", "result.*.json")
outputFile, err := os.CreateTemp("testdata", "result.*.json")
if err != nil {
t.Fatalf("Tempfile failed: %v", err)
}
@ -763,7 +762,7 @@ var cacheFailureTests = []struct {
func TestRetrieveOutputFileSubjectTokenFailureTests(t *testing.T) {
for _, tt := range cacheFailureTests {
t.Run(tt.name, func(t *testing.T) {
outputFile, err := ioutil.TempFile("testdata", "result.*.json")
outputFile, err := os.CreateTemp("testdata", "result.*.json")
if err != nil {
t.Fatalf("Tempfile failed: %v", err)
}
@ -866,7 +865,7 @@ var invalidCacheTests = []struct {
func TestRetrieveOutputFileSubjectTokenInvalidCache(t *testing.T) {
for _, tt := range invalidCacheTests {
t.Run(tt.name, func(t *testing.T) {
outputFile, err := ioutil.TempFile("testdata", "result.*.json")
outputFile, err := os.CreateTemp("testdata", "result.*.json")
if err != nil {
t.Fatalf("Tempfile failed: %v", err)
}
@ -970,8 +969,7 @@ var cacheSuccessTests = []struct {
func TestRetrieveOutputFileSubjectTokenJwt(t *testing.T) {
for _, tt := range cacheSuccessTests {
t.Run(tt.name, func(t *testing.T) {
outputFile, err := ioutil.TempFile("testdata", "result.*.json")
outputFile, err := os.CreateTemp("testdata", "result.*.json")
if err != nil {
t.Fatalf("Tempfile failed: %v", err)
}

View File

@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
)
@ -29,7 +28,7 @@ func (cs fileCredentialSource) subjectToken() (string, error) {
return "", fmt.Errorf("oauth2/google/externalaccount: failed to open credential file %q", cs.File)
}
defer tokenFile.Close()
tokenBytes, err := ioutil.ReadAll(io.LimitReader(tokenFile, 1<<20))
tokenBytes, err := io.ReadAll(io.LimitReader(tokenFile, 1<<20))
if err != nil {
return "", fmt.Errorf("oauth2/google/externalaccount: failed to read credential file: %v", err)
}

View File

@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"golang.org/x/oauth2"
@ -44,7 +43,7 @@ func (cs urlCredentialSource) subjectToken() (string, error) {
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return "", fmt.Errorf("oauth2/google/externalaccount: invalid body in subject token URL query: %v", err)
}

View File

@ -285,22 +285,18 @@ func (cs computeSource) Token() (*oauth2.Token, error) {
if err != nil {
return nil, err
}
var res struct {
AccessToken string `json:"access_token"`
ExpiresInSec int `json:"expires_in"`
TokenType string `json:"token_type"`
}
var res oauth2.Token
err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
if err != nil {
return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
}
if res.ExpiresInSec == 0 || res.AccessToken == "" {
if res.ExpiresIn == 0 || res.AccessToken == "" {
return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
}
tok := &oauth2.Token{
AccessToken: res.AccessToken,
TokenType: res.TokenType,
Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
Expiry: time.Now().Add(time.Duration(res.ExpiresIn) * time.Second),
}
// NOTE(cbro): add hidden metadata about where the token is from.
// This is needed for detection by client libraries to know that credentials come from the metadata server.

View File

@ -8,7 +8,7 @@ import (
"context"
"encoding/json"
"errors"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
@ -227,7 +227,7 @@ func (trts *testRefreshTokenServer) run(t *testing.T) (string, error) {
if got, want := headerContentType, trts.ContentType; got != want {
t.Errorf("got %v but want %v", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("Failed reading request body: %s.", err)
}

View File

@ -10,7 +10,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"time"
@ -81,7 +80,7 @@ func (its ImpersonateTokenSource) Token() (*oauth2.Token, error) {
return nil, fmt.Errorf("oauth2/google: unable to generate access token: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, fmt.Errorf("oauth2/google: unable to read body: %v", err)
}

View File

@ -9,7 +9,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
@ -82,7 +81,7 @@ func makeRequest(ctx context.Context, endpoint string, data url.Values, authenti
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, err
}

View File

@ -7,7 +7,7 @@ package stsexchange
import (
"context"
"encoding/json"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"net/url"
@ -73,7 +73,7 @@ func TestExchangeToken(t *testing.T) {
if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
t.Errorf("Unexpected Content-Type header, got %v, want %v", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("Failed reading request body: %v.", err)
}
@ -132,7 +132,7 @@ var optsValues = [][]string{{"foo", "bar"}, {"cat", "pan"}}
func TestExchangeToken_Opts(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("Failed reading request body: %v.", err)
}
@ -220,7 +220,7 @@ func TestRefreshToken(t *testing.T) {
if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
t.Errorf("Unexpected Content-Type header, got %v, want %v", got, want)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("Failed reading request body: %v.", err)
}

View File

@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"math"
"mime"
"net/http"
@ -257,7 +256,7 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20))
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20))
r.Body.Close()
if err != nil {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)

View File

@ -13,7 +13,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
@ -114,7 +113,7 @@ func (js jwtSource) Token() (*oauth2.Token, error) {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
}
@ -123,11 +122,7 @@ func (js jwtSource) Token() (*oauth2.Token, error) {
}
// tokenRes is the JSON response body.
var tokenRes struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int64 `json:"expires_in"` // relative seconds from now
}
var tokenRes oauth2.Token
if err := json.Unmarshal(body, &tokenRes); err != nil {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
}

View File

@ -13,7 +13,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
@ -136,7 +135,7 @@ func (js jwtSource) Token() (*oauth2.Token, error) {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
}
@ -148,10 +147,8 @@ func (js jwtSource) Token() (*oauth2.Token, error) {
}
// tokenRes is the JSON response body.
var tokenRes struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
oauth2.Token
IDToken string `json:"id_token"`
ExpiresIn int64 `json:"expires_in"` // relative seconds from now
}
if err := json.Unmarshal(body, &tokenRes); err != nil {
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)

View File

@ -9,7 +9,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@ -104,7 +103,7 @@ func TestExchangeRequest(t *testing.T) {
if headerContentType != "application/x-www-form-urlencoded" {
t.Errorf("Unexpected Content-Type header %q", headerContentType)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("Failed reading request body: %s.", err)
}
@ -148,7 +147,7 @@ func TestExchangeRequest_CustomParam(t *testing.T) {
if headerContentType != "application/x-www-form-urlencoded" {
t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("Failed reading request body: %s.", err)
}
@ -194,7 +193,7 @@ func TestExchangeRequest_JSONResponse(t *testing.T) {
if headerContentType != "application/x-www-form-urlencoded" {
t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("Failed reading request body: %s.", err)
}
@ -393,7 +392,7 @@ func TestPasswordCredentialsTokenRequest(t *testing.T) {
if headerContentType != expected {
t.Errorf("Content-Type header = %q; want %q", headerContentType, expected)
}
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("Failed reading request body: %s.", err)
}
@ -435,7 +434,7 @@ func TestTokenRefreshRequest(t *testing.T) {
if headerContentType != "application/x-www-form-urlencoded" {
t.Errorf("Unexpected Content-Type header %q", headerContentType)
}
body, _ := ioutil.ReadAll(r.Body)
body, _ := io.ReadAll(r.Body)
if string(body) != "grant_type=refresh_token&refresh_token=REFRESH_TOKEN" {
t.Errorf("Unexpected refresh token payload %q", body)
}
@ -460,7 +459,7 @@ func TestFetchWithNoRefreshToken(t *testing.T) {
if headerContentType != "application/x-www-form-urlencoded" {
t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
}
body, _ := ioutil.ReadAll(r.Body)
body, _ := io.ReadAll(r.Body)
if string(body) != "client_id=CLIENT_ID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN" {
t.Errorf("Unexpected refresh token payload, %v is found.", string(body))
}