Skip to content

Commit accb058

Browse files
authored
chore: bump cristalhq/jwt to v5 (#3476)
1 parent e2b2994 commit accb058

File tree

12 files changed

+87
-57
lines changed

12 files changed

+87
-57
lines changed

api/rpc/perms/permissions.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package perms
33
import (
44
"encoding/json"
55

6-
"github.com/cristalhq/jwt"
6+
"github.com/cristalhq/jwt/v5"
77
"github.com/filecoin-project/go-jsonrpc/auth"
88
)
99

@@ -28,9 +28,13 @@ func (j *JWTPayload) MarshalBinary() (data []byte, err error) {
2828

2929
// NewTokenWithPerms generates and signs a new JWT token with the given secret
3030
// and given permissions.
31-
func NewTokenWithPerms(secret jwt.Signer, perms []auth.Permission) ([]byte, error) {
31+
func NewTokenWithPerms(signer jwt.Signer, perms []auth.Permission) ([]byte, error) {
3232
p := &JWTPayload{
3333
Allow: perms,
3434
}
35-
return jwt.NewTokenBuilder(secret).BuildBytes(p)
35+
token, err := jwt.NewBuilder(signer).Build(p)
36+
if err != nil {
37+
return nil, err
38+
}
39+
return token.Bytes(), nil
3640
}

api/rpc/server.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"sync/atomic"
99
"time"
1010

11-
"github.com/cristalhq/jwt"
11+
"github.com/cristalhq/jwt/v5"
1212
"github.com/filecoin-project/go-jsonrpc"
1313
"github.com/filecoin-project/go-jsonrpc/auth"
1414
logging "github.com/ipfs/go-log/v2"
@@ -27,10 +27,11 @@ type Server struct {
2727

2828
started atomic.Bool
2929

30-
auth jwt.Signer
30+
signer jwt.Signer
31+
verifier jwt.Verifier
3132
}
3233

33-
func NewServer(address, port string, authDisabled bool, secret jwt.Signer) *Server {
34+
func NewServer(address, port string, authDisabled bool, signer jwt.Signer, verifier jwt.Verifier) *Server {
3435
rpc := jsonrpc.NewServer()
3536
srv := &Server{
3637
rpc: rpc,
@@ -39,7 +40,8 @@ func NewServer(address, port string, authDisabled bool, secret jwt.Signer) *Serv
3940
// the amount of time allowed to read request headers. set to the default 2 seconds
4041
ReadHeaderTimeout: 2 * time.Second,
4142
},
42-
auth: secret,
43+
signer: signer,
44+
verifier: verifier,
4345
authDisabled: authDisabled,
4446
}
4547
srv.srv.Handler = &auth.Handler{
@@ -56,7 +58,7 @@ func (s *Server) verifyAuth(_ context.Context, token string) ([]auth.Permission,
5658
if s.authDisabled {
5759
return perms.AllPerms, nil
5860
}
59-
return authtoken.ExtractSignedPermissions(s.auth, token)
61+
return authtoken.ExtractSignedPermissions(s.verifier, token)
6062
}
6163

6264
// RegisterService registers a service onto the RPC server. All methods on the service will then be

api/rpc_test.go

+20-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"time"
1010

1111
sdk "github.com/cosmos/cosmos-sdk/types"
12-
"github.com/cristalhq/jwt"
12+
"github.com/cristalhq/jwt/v5"
1313
"github.com/golang/mock/gomock"
1414
"github.com/libp2p/go-libp2p/core/network"
1515
"github.com/stretchr/testify/require"
@@ -46,10 +46,15 @@ func TestRPCCallsUnderlyingNode(t *testing.T) {
4646
t.Cleanup(cancel)
4747

4848
// generate dummy signer and sign admin perms token with it
49-
signer, err := jwt.NewHS256(make([]byte, 32))
49+
key := make([]byte, 32)
50+
51+
signer, err := jwt.NewSignerHS(jwt.HS256, key)
52+
require.NoError(t, err)
53+
54+
verifier, err := jwt.NewVerifierHS(jwt.HS256, key)
5055
require.NoError(t, err)
5156

52-
nd, server := setupNodeWithAuthedRPC(t, signer)
57+
nd, server := setupNodeWithAuthedRPC(t, signer, verifier)
5358
url := nd.RPCServer.ListenAddr()
5459

5560
adminToken, err := perms.NewTokenWithPerms(signer, perms.AllPerms)
@@ -123,10 +128,15 @@ func TestAuthedRPC(t *testing.T) {
123128
t.Cleanup(cancel)
124129

125130
// generate dummy signer and sign admin perms token with it
126-
signer, err := jwt.NewHS256(make([]byte, 32))
131+
key := make([]byte, 32)
132+
133+
signer, err := jwt.NewSignerHS(jwt.HS256, key)
134+
require.NoError(t, err)
135+
136+
verifier, err := jwt.NewVerifierHS(jwt.HS256, key)
127137
require.NoError(t, err)
128138

129-
nd, server := setupNodeWithAuthedRPC(t, signer)
139+
nd, server := setupNodeWithAuthedRPC(t, signer, verifier)
130140
url := nd.RPCServer.ListenAddr()
131141

132142
// create permissioned tokens
@@ -284,7 +294,9 @@ func implementsMarshaler(t *testing.T, typ reflect.Type) {
284294

285295
// setupNodeWithAuthedRPC sets up a node and overrides its JWT
286296
// signer with the given signer.
287-
func setupNodeWithAuthedRPC(t *testing.T, auth jwt.Signer) (*nodebuilder.Node, *mockAPI) {
297+
func setupNodeWithAuthedRPC(t *testing.T,
298+
jwtSigner jwt.Signer, jwtVerifier jwt.Verifier,
299+
) (*nodebuilder.Node, *mockAPI) {
288300
ctx, cancel := context.WithCancel(context.Background())
289301
t.Cleanup(cancel)
290302

@@ -316,8 +328,8 @@ func setupNodeWithAuthedRPC(t *testing.T, auth jwt.Signer) (*nodebuilder.Node, *
316328
srv.RegisterService("da", mockAPI.DA, &da.API{})
317329
})
318330
// fx.Replace does not work here, but fx.Decorate does
319-
nd := nodebuilder.TestNode(t, node.Full, invokeRPC, fx.Decorate(func() (jwt.Signer, error) {
320-
return auth, nil
331+
nd := nodebuilder.TestNode(t, node.Full, invokeRPC, fx.Decorate(func() (jwt.Signer, jwt.Verifier, error) {
332+
return jwtSigner, jwtVerifier, nil
321333
}))
322334
// start node
323335
err := nd.Start(ctx)

cmd/auth.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"io"
88
"path/filepath"
99

10-
"github.com/cristalhq/jwt"
10+
"github.com/cristalhq/jwt/v5"
1111
"github.com/filecoin-project/go-jsonrpc/auth"
1212
"github.com/mitchellh/go-homedir"
1313
"github.com/spf13/cobra"
@@ -74,7 +74,7 @@ func newKeystore(path string) (keystore.Keystore, error) {
7474
}
7575

7676
func buildJWTToken(body []byte, permissions []auth.Permission) (string, error) {
77-
signer, err := jwt.NewHS256(body)
77+
signer, err := jwt.NewSignerHS(jwt.HS256, body)
7878
if err != nil {
7979
return "", err
8080
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/celestiaorg/nmt v0.21.0
1616
github.com/celestiaorg/rsmt2d v0.13.1
1717
github.com/cosmos/cosmos-sdk v0.46.16
18-
github.com/cristalhq/jwt v1.2.0
18+
github.com/cristalhq/jwt/v5 v5.4.0
1919
github.com/dgraph-io/badger/v4 v4.2.1-0.20240106094458-1c417aa3799c
2020
github.com/etclabscore/go-openrpc-reflect v0.0.37
2121
github.com/filecoin-project/dagstore v0.5.6

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -503,8 +503,8 @@ github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6V
503503
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
504504
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
505505
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
506-
github.com/cristalhq/jwt v1.2.0 h1:fHmMkFJvEbS4o04aQP8BmtJg7fqkYvd7r8er3sUdS4Q=
507-
github.com/cristalhq/jwt v1.2.0/go.mod h1:QQFazsDzoqeucUEEV0h16uPTZXBAi2SVA8cQ9JEDuFw=
506+
github.com/cristalhq/jwt/v5 v5.4.0 h1:Wxi1TocFHaijyV608j7v7B9mPc4ZNjvWT3LKBO0d4QI=
507+
github.com/cristalhq/jwt/v5 v5.4.0/go.mod h1:+b/BzaCWEpFDmXxspJ5h4SdJ1N/45KMjKOetWzmHvDA=
508508
github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0=
509509
github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis=
510510
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=

libs/authtoken/authtoken.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ package authtoken
33
import (
44
"encoding/json"
55

6-
"github.com/cristalhq/jwt"
6+
"github.com/cristalhq/jwt/v5"
77
"github.com/filecoin-project/go-jsonrpc/auth"
88

99
"github.com/celestiaorg/celestia-node/api/rpc/perms"
1010
)
1111

1212
// ExtractSignedPermissions returns the permissions granted to the token by the passed signer.
1313
// If the token isn't signed by the signer, it will not pass verification.
14-
func ExtractSignedPermissions(signer jwt.Signer, token string) ([]auth.Permission, error) {
15-
tk, err := jwt.ParseAndVerifyString(token, signer)
14+
func ExtractSignedPermissions(verifier jwt.Verifier, token string) ([]auth.Permission, error) {
15+
tk, err := jwt.Parse([]byte(token), verifier)
1616
if err != nil {
1717
return nil, err
1818
}
1919
p := new(perms.JWTPayload)
20-
err = json.Unmarshal(tk.RawClaims(), p)
20+
err = json.Unmarshal(tk.Claims(), p)
2121
if err != nil {
2222
return nil, err
2323
}
@@ -26,11 +26,11 @@ func ExtractSignedPermissions(signer jwt.Signer, token string) ([]auth.Permissio
2626

2727
// NewSignedJWT returns a signed JWT token with the passed permissions and signer.
2828
func NewSignedJWT(signer jwt.Signer, permissions []auth.Permission) (string, error) {
29-
token, err := jwt.NewTokenBuilder(signer).Build(&perms.JWTPayload{
29+
token, err := jwt.NewBuilder(signer).Build(&perms.JWTPayload{
3030
Allow: permissions,
3131
})
3232
if err != nil {
3333
return "", err
3434
}
35-
return token.InsecureString(), nil
35+
return token.String(), nil
3636
}

nodebuilder/node.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"fmt"
77
"strings"
88

9-
"github.com/cristalhq/jwt"
9+
"github.com/cristalhq/jwt/v5"
1010
"github.com/ipfs/boxo/blockservice"
1111
"github.com/ipfs/boxo/exchange"
1212
logging "github.com/ipfs/go-log/v2"

nodebuilder/node/admin.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package node
33
import (
44
"context"
55

6-
"github.com/cristalhq/jwt"
6+
"github.com/cristalhq/jwt/v5"
77
"github.com/filecoin-project/go-jsonrpc/auth"
88
logging "github.com/ipfs/go-log/v2"
99

@@ -13,14 +13,16 @@ import (
1313
var APIVersion = GetBuildInfo().SemanticVersion
1414

1515
type module struct {
16-
tp Type
17-
signer jwt.Signer
16+
tp Type
17+
signer jwt.Signer
18+
verifier jwt.Verifier
1819
}
1920

20-
func newModule(tp Type, signer jwt.Signer) Module {
21+
func newModule(tp Type, signer jwt.Signer, verifier jwt.Verifier) Module {
2122
return &module{
22-
tp: tp,
23-
signer: signer,
23+
tp: tp,
24+
signer: signer,
25+
verifier: verifier,
2426
}
2527
}
2628

@@ -51,7 +53,7 @@ func (m *module) LogLevelSet(_ context.Context, name, level string) error {
5153
}
5254

5355
func (m *module) AuthVerify(_ context.Context, token string) ([]auth.Permission, error) {
54-
return authtoken.ExtractSignedPermissions(m.signer, token)
56+
return authtoken.ExtractSignedPermissions(m.verifier, token)
5557
}
5658

5759
func (m *module) AuthNew(_ context.Context, permissions []auth.Permission) (string, error) {

nodebuilder/node/auth.go

+25-15
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,42 @@ import (
44
"crypto/rand"
55
"io"
66

7-
"github.com/cristalhq/jwt"
7+
"github.com/cristalhq/jwt/v5"
88

99
"github.com/celestiaorg/celestia-node/libs/keystore"
1010
)
1111

1212
var SecretName = keystore.KeyName("jwt-secret.jwt")
1313

14-
// secret returns the node's JWT secret if it exists, or generates
15-
// and saves a new one if it does not.
16-
func secret(ks keystore.Keystore) (jwt.Signer, error) {
17-
// if key already exists, use it
18-
if pk, ok := existing(ks); ok {
19-
return jwt.NewHS256(pk)
14+
// jwtSignerAndVerifier returns the node's JWT signer and verifier for a saved key,
15+
// or generates and saves a new one if it does not.
16+
func jwtSignerAndVerifier(ks keystore.Keystore) (jwt.Signer, jwt.Verifier, error) {
17+
key, ok := existing(ks)
18+
if !ok {
19+
// otherwise, generate and save new priv key
20+
sk, err := io.ReadAll(io.LimitReader(rand.Reader, 32))
21+
if err != nil {
22+
return nil, nil, err
23+
}
24+
25+
// save key
26+
err = ks.Put(SecretName, keystore.PrivKey{Body: sk})
27+
if err != nil {
28+
return nil, nil, err
29+
}
30+
key = sk
2031
}
21-
// otherwise, generate and save new priv key
22-
sk, err := io.ReadAll(io.LimitReader(rand.Reader, 32))
32+
33+
signer, err := jwt.NewSignerHS(jwt.HS256, key)
2334
if err != nil {
24-
return nil, err
35+
return nil, nil, err
2536
}
26-
// save key
27-
err = ks.Put(SecretName, keystore.PrivKey{Body: sk})
37+
38+
verifier, err := jwt.NewVerifierHS(jwt.HS256, key)
2839
if err != nil {
29-
return nil, err
40+
return nil, nil, err
3041
}
31-
32-
return jwt.NewHS256(sk)
42+
return signer, verifier, nil
3343
}
3444

3545
func existing(ks keystore.Keystore) ([]byte, bool) {

nodebuilder/node/module.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package node
22

33
import (
4-
"github.com/cristalhq/jwt"
4+
"github.com/cristalhq/jwt/v5"
55
"go.uber.org/fx"
66
)
77

88
func ConstructModule(tp Type) fx.Option {
99
return fx.Module(
1010
"node",
11-
fx.Provide(func(secret jwt.Signer) Module {
12-
return newModule(tp, secret)
11+
fx.Provide(func(signer jwt.Signer, verifier jwt.Verifier) Module {
12+
return newModule(tp, signer, verifier)
1313
}),
14-
fx.Provide(secret),
14+
fx.Provide(jwtSignerAndVerifier),
1515
)
1616
}

nodebuilder/rpc/constructors.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package rpc
22

33
import (
4-
"github.com/cristalhq/jwt"
4+
"github.com/cristalhq/jwt/v5"
55

66
"github.com/celestiaorg/celestia-node/api/rpc"
77
"github.com/celestiaorg/celestia-node/nodebuilder/blob"
@@ -39,6 +39,6 @@ func registerEndpoints(
3939
serv.RegisterService("da", daMod, &da.API{})
4040
}
4141

42-
func server(cfg *Config, auth jwt.Signer) *rpc.Server {
43-
return rpc.NewServer(cfg.Address, cfg.Port, cfg.SkipAuth, auth)
42+
func server(cfg *Config, signer jwt.Signer, verifier jwt.Verifier) *rpc.Server {
43+
return rpc.NewServer(cfg.Address, cfg.Port, cfg.SkipAuth, signer, verifier)
4444
}

0 commit comments

Comments
 (0)