Skip to content

Commit

Permalink
re-enabling jwt on keymanager API (#13492)
Browse files Browse the repository at this point in the history
* re-enabling jwt on keymanager API

* adding tests

* Update validator/rpc/intercepter.go

Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com>

* handling error in test

* remove debugging logs

---------

Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com>
  • Loading branch information
james-prysm and saolyn committed Jan 22, 2024
1 parent 4afb379 commit 8dd5e96
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
1 change: 0 additions & 1 deletion validator/rpc/auth_token.go
Expand Up @@ -191,7 +191,6 @@ func createTokenString(jwtKey []byte) (string, error) {
return tokenString, nil
}

// DEPRECATED: associated to Initialize Web UI API
func createRandomJWTSecret() ([]byte, error) {
r := rand.NewGenerator()
jwtKey := make([]byte, 32)
Expand Down
5 changes: 2 additions & 3 deletions validator/rpc/intercepter.go
Expand Up @@ -40,8 +40,7 @@ func (s *Server) JwtHttpInterceptor(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// if it's not initialize or has a web prefix
if !strings.Contains(r.URL.Path, api.WebUrlPrefix+"initialize") && // ignore some routes
!strings.Contains(r.URL.Path, api.WebUrlPrefix+"health/logs") &&
strings.Contains(r.URL.Path, api.WebUrlPrefix) {
!strings.Contains(r.URL.Path, api.WebUrlPrefix+"health/logs") {
reqToken := r.Header.Get("Authorization")
if reqToken == "" {
http.Error(w, "unauthorized: no Authorization header passed. Please use an Authorization header with the jwt created in the prysm wallet", http.StatusUnauthorized)
Expand All @@ -50,7 +49,7 @@ func (s *Server) JwtHttpInterceptor(next http.Handler) http.Handler {
token := strings.Split(reqToken, "Bearer ")[1]
_, err := jwt.Parse(token, s.validateJWT)
if err != nil {
http.Error(w, fmt.Errorf("unauthorized:could not parse JWT token: %v", err).Error(), http.StatusUnauthorized)
http.Error(w, fmt.Errorf("forbidden: could not parse JWT token: %v", err).Error(), http.StatusForbidden)
return
}
}
Expand Down
55 changes: 55 additions & 0 deletions validator/rpc/intercepter_test.go
Expand Up @@ -2,9 +2,12 @@ package rpc

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"github.com/golang-jwt/jwt/v4"
"github.com/prysmaticlabs/prysm/v4/api"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
Expand Down Expand Up @@ -67,3 +70,55 @@ func TestServer_JWTInterceptor_InvalidSigningType(t *testing.T) {
_, err := ss.validateJWT(token)
require.ErrorContains(t, "unexpected JWT signing method", err)
}

func TestServer_JwtHttpInterceptor(t *testing.T) {
jwtKey, err := createRandomJWTSecret()
require.NoError(t, err)

s := &Server{jwtSecret: jwtKey}
testHandler := s.JwtHttpInterceptor(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Your test handler logic here
w.WriteHeader(http.StatusOK)
_, err := w.Write([]byte("Test Response"))
require.NoError(t, err)
}))
t.Run("no jwt was sent", func(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
require.NoError(t, err)
testHandler.ServeHTTP(rr, req)
require.Equal(t, http.StatusUnauthorized, rr.Code)
})
t.Run("wrong jwt was sent", func(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
require.NoError(t, err)
req.Header.Set("Authorization", "Bearer YOUR_JWT_TOKEN") // Replace with a valid JWT token
testHandler.ServeHTTP(rr, req)
require.Equal(t, http.StatusForbidden, rr.Code)
})
t.Run("jwt was sent", func(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest(http.MethodGet, "/eth/v1/keystores", nil)
require.NoError(t, err)
token, err := createTokenString(jwtKey)
require.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+token) // Replace with a valid JWT token
testHandler.ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code)
})
t.Run("initialize does not need jwt", func(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest(http.MethodGet, api.WebUrlPrefix+"initialize", nil)
require.NoError(t, err)
testHandler.ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code)
})
t.Run("health does not need jwt", func(t *testing.T) {
rr := httptest.NewRecorder()
req, err := http.NewRequest(http.MethodGet, api.WebUrlPrefix+"health/logs", nil)
require.NoError(t, err)
testHandler.ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code)
})
}

0 comments on commit 8dd5e96

Please sign in to comment.