add bare bones jwt stuff to support authsock

This commit is contained in:
sawka
2024-07-25 16:41:34 -07:00
parent 96420ea3ef
commit 67ee0df322
4 changed files with 82 additions and 1 deletions
+78
View File
@@ -10,7 +10,9 @@ import (
"net"
"os"
"reflect"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
@@ -177,6 +179,82 @@ func RunWshRpcOverListener(listener net.Listener) {
}()
}
func MakeClientJWTToken(rpcCtx wshutil.RpcContext, sockName string) (string, error) {
claims := jwt.MapClaims{}
claims["iat"] = time.Now().Unix()
claims["iss"] = "waveterm"
claims["sock"] = sockName
claims["exp"] = time.Now().Add(time.Hour * 24 * 365).Unix()
if rpcCtx.BlockId != "" {
claims["blockid"] = rpcCtx.BlockId
}
if rpcCtx.TabId != "" {
claims["tabid"] = rpcCtx.TabId
}
if rpcCtx.WindowId != "" {
claims["windowid"] = rpcCtx.WindowId
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenStr, err := token.SignedString([]byte(wavebase.JwtSecret))
if err != nil {
return "", fmt.Errorf("error signing token: %w", err)
}
return tokenStr, nil
}
func ValidateAndExtractRpcContextFromToken(tokenStr string) (wshutil.RpcContext, error) {
parser := jwt.NewParser(jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Name}))
token, err := parser.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return []byte(wavebase.JwtSecret), nil
})
if err != nil {
return wshutil.RpcContext{}, fmt.Errorf("error parsing token: %w", err)
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return wshutil.RpcContext{}, fmt.Errorf("error getting claims from token")
}
// validate "exp" claim
if exp, ok := claims["exp"].(float64); ok {
if int64(exp) < time.Now().Unix() {
return wshutil.RpcContext{}, fmt.Errorf("token has expired")
}
} else {
return wshutil.RpcContext{}, fmt.Errorf("exp claim is missing or invalid")
}
// validate "iss" claim
if iss, ok := claims["iss"].(string); ok {
if iss != "waveterm" {
return wshutil.RpcContext{}, fmt.Errorf("unexpected issuer: %s", iss)
}
} else {
return wshutil.RpcContext{}, fmt.Errorf("iss claim is missing or invalid")
}
rpcCtx := wshutil.RpcContext{}
rpcCtx.BlockId = claims["blockid"].(string)
rpcCtx.TabId = claims["tabid"].(string)
rpcCtx.WindowId = claims["windowid"].(string)
return rpcCtx, nil
}
func ExtractUnverifiedSocketName(tokenStr string) (string, error) {
// this happens on the client who does not have access to the secret key
// we want to read the claims without validating the signature
token, _, err := new(jwt.Parser).ParseUnverified(tokenStr, jwt.MapClaims{})
if err != nil {
return "", fmt.Errorf("error parsing token: %w", err)
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return "", fmt.Errorf("error getting claims from token")
}
sockName, ok := claims["sock"].(string)
if !ok {
return "", fmt.Errorf("sock claim is missing or invalid")
}
return sockName, nil
}
func RunDomainSocketWshServer() error {
sockName := wavebase.GetDomainSocketName()
listener, err := MakeUnixListener(sockName)