prysm-pulse/network/auth.go

53 lines
2.0 KiB
Go
Raw Normal View History

package network
import (
"net/http"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors"
)
// DefaultRPCHTTPTimeout for HTTP requests via an RPC connection to an execution node.
const DefaultRPCHTTPTimeout = time.Second * 30
// This creates a custom HTTP transport which we can attach to our HTTP client
// in order to inject JWT auth strings into our HTTP request headers. Authentication
// is required when interacting with an Ethereum engine API server via HTTP, and JWT
// is chosen as the scheme of choice.
// For more details on the requirements of authentication when using the engine API, see
// the specification here: https://github.com/ethereum/execution-apis/blob/main/src/engine/authentication.md
//
// To use this transport, initialize a new &http.Client{} from the standard library
// and set the Transport field to &jwtTransport{} with values
// http.DefaultTransport and a JWT secret.
type jwtTransport struct {
underlyingTransport http.RoundTripper
jwtSecret []byte
jwtId string
}
// RoundTrip ensures our transport implements http.RoundTripper interface from the
// standard library. When used as the transport for an HTTP client, the code below
// will run every time our client makes an HTTP request. This is used to inject
// an JWT bearer token in the Authorization request header of every outgoing request
// our HTTP client makes.
func (t *jwtTransport) RoundTrip(req *http.Request) (*http.Response, error) {
claims := jwt.MapClaims{
// Required claim for engine API auth. "iat" stands for issued at
// and it must be a unix timestamp that is +/- 5 seconds from the current
// timestamp at the moment the server verifies this value.
"iat": time.Now().Unix(),
}
if len(t.jwtId) > 0 {
claims["id"] = t.jwtId
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(t.jwtSecret)
if err != nil {
return nil, errors.Wrap(err, "could not produce signed JWT token")
}
req.Header.Set("Authorization", "Bearer "+tokenString)
return t.underlyingTransport.RoundTrip(req)
}