Use jwt-go (golang-jwt) instead of deprecated jws (x/oauth2/jws)

golang.org/x/oauth2/jws is deprecated: this package is not intended for public use and
might be removed in the future. It exists for internal use only. Please switch to another
JWS package or copy this package into your own source tree.

github.com/golang-jwt/jwt/v4 seems to be a good alternative, and was already
an implicit dependency.
This commit is contained in:
albertony 2022-06-25 15:33:12 +02:00
parent 2e2451f8ec
commit 0374ea2c79
4 changed files with 29 additions and 30 deletions

View file

@ -33,11 +33,6 @@ issues:
- staticcheck
text: 'SA1019: "github.com/rclone/rclone/cmd/serve/httplib" is deprecated'
# TODO: Remove if/when this is fixed by merging PR #6277.
- linters:
- staticcheck
text: 'SA1019: "golang.org/x/oauth2/jws" is deprecated'
run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 10m

View file

@ -27,6 +27,7 @@ import (
"sync/atomic"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/rclone/rclone/backend/box/api"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/config"
@ -45,7 +46,6 @@ import (
"github.com/rclone/rclone/lib/rest"
"github.com/youmark/pkcs8"
"golang.org/x/oauth2"
"golang.org/x/oauth2/jws"
)
const (
@ -76,6 +76,11 @@ var (
}
)
type boxCustomClaims struct {
jwt.RegisteredClaims
BoxSubType string `json:"box_sub_type,omitempty"`
}
// Register with Fs
func init() {
fs.Register(&fs.RegInfo{
@ -178,7 +183,7 @@ func refreshJWTToken(ctx context.Context, jsonFile string, boxSubType string, na
signingHeaders := getSigningHeaders(boxConfig)
queryParams := getQueryParams(boxConfig)
client := fshttp.NewClient(ctx)
err = jwtutil.Config("box", name, claims, signingHeaders, queryParams, privateKey, m, client)
err = jwtutil.Config("box", name, tokenURL, *claims, signingHeaders, queryParams, privateKey, m, client)
return err
}
@ -194,34 +199,29 @@ func getBoxConfig(configFile string) (boxConfig *api.ConfigJSON, err error) {
return boxConfig, nil
}
func getClaims(boxConfig *api.ConfigJSON, boxSubType string) (claims *jws.ClaimSet, err error) {
func getClaims(boxConfig *api.ConfigJSON, boxSubType string) (claims *boxCustomClaims, err error) {
val, err := jwtutil.RandomHex(20)
if err != nil {
return nil, fmt.Errorf("box: failed to generate random string for jti: %w", err)
}
claims = &jws.ClaimSet{
Iss: boxConfig.BoxAppSettings.ClientID,
Sub: boxConfig.EnterpriseID,
Aud: tokenURL,
Exp: time.Now().Add(time.Second * 45).Unix(),
PrivateClaims: map[string]interface{}{
"box_sub_type": boxSubType,
"aud": tokenURL,
"jti": val,
claims = &boxCustomClaims{
RegisteredClaims: jwt.RegisteredClaims{
ID: val,
Issuer: boxConfig.BoxAppSettings.ClientID,
Subject: boxConfig.EnterpriseID,
Audience: jwt.ClaimStrings{tokenURL},
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * 45)),
},
BoxSubType: boxSubType,
}
return claims, nil
}
func getSigningHeaders(boxConfig *api.ConfigJSON) *jws.Header {
signingHeaders := &jws.Header{
Algorithm: "RS256",
Typ: "JWT",
KeyID: boxConfig.BoxAppSettings.AppAuth.PublicKeyID,
func getSigningHeaders(boxConfig *api.ConfigJSON) map[string]interface{} {
signingHeaders := map[string]interface{}{
"kid": boxConfig.BoxAppSettings.AppAuth.PublicKeyID,
}
return signingHeaders
}

2
go.mod
View file

@ -141,7 +141,7 @@ require (
require (
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/pkg/xattr v0.4.9

View file

@ -14,12 +14,12 @@ import (
"strings"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/config/configmap"
"github.com/rclone/rclone/lib/oauthutil"
"golang.org/x/oauth2"
"golang.org/x/oauth2/jws"
)
// RandomHex creates a random string of the given length
@ -32,12 +32,16 @@ func RandomHex(n int) (string, error) {
}
// Config configures rclone using JWT
func Config(id, name string, claims *jws.ClaimSet, header *jws.Header, queryParams map[string]string, privateKey *rsa.PrivateKey, m configmap.Mapper, client *http.Client) (err error) {
payload, err := jws.Encode(header, claims, privateKey)
func Config(id, name, url string, claims jwt.Claims, headerParams map[string]interface{}, queryParams map[string]string, privateKey *rsa.PrivateKey, m configmap.Mapper, client *http.Client) (err error) {
jwtToken := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
for key, value := range headerParams {
jwtToken.Header[key] = value
}
payload, err := jwtToken.SignedString(privateKey)
if err != nil {
return fmt.Errorf("jwtutil: failed to encode payload: %w", err)
}
req, err := http.NewRequest("POST", claims.Aud, nil)
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return fmt.Errorf("jwtutil: failed to create new request: %w", err)
}
@ -49,7 +53,7 @@ func Config(id, name string, claims *jws.ClaimSet, header *jws.Header, queryPara
}
queryString := q.Encode()
req, err = http.NewRequest("POST", claims.Aud, bytes.NewBuffer([]byte(queryString)))
req, err = http.NewRequest("POST", url, bytes.NewBuffer([]byte(queryString)))
if err != nil {
return fmt.Errorf("jwtutil: failed to create new request: %w", err)
}