From 972e41e92d756a337846132d053d5bb3fa4cf25e Mon Sep 17 00:00:00 2001 From: "cheetah.cat" Date: Wed, 21 Aug 2024 18:40:55 +0200 Subject: [PATCH] added tokenmanager --- client/tokenmanager.go | 89 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 client/tokenmanager.go diff --git a/client/tokenmanager.go b/client/tokenmanager.go new file mode 100644 index 0000000..d724836 --- /dev/null +++ b/client/tokenmanager.go @@ -0,0 +1,89 @@ +package client + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + "time" +) + +const tokenExpirationSeconds = 60 + +type TokenManager struct { + issuer string + privateKey string +} + +func (t *TokenManager) CreateJwt() (string, error) { + if t.issuer == "" || t.privateKey == "" { + return "", errors.New("missing required field issuer or private key") + } + + key, err := t.getRsaPrivateKey() + if err != nil { + return "", err + } + + var header = struct { + Algorithm string `json:"alg"` + Type string `json:"typ"` + }{ + "RS256", + "JWT", + } + var payload = struct { + Issuer string `json:"iss"` + Expiration int64 `json:"exp"` + }{ + t.issuer, + time.Now().Unix() + tokenExpirationSeconds, + } + + headerJson, _ := json.Marshal(&header) + payloadJson, _ := json.Marshal(&payload) + pkg := base64.RawURLEncoding.EncodeToString(headerJson) + "." + base64.RawURLEncoding.EncodeToString(payloadJson) + + if signature, err := t.sign([]byte(pkg), key); err != nil { + return "", err + } else { + return pkg + "." + base64.RawURLEncoding.EncodeToString(signature), nil + } +} + +func (t *TokenManager) sign(data []byte, privateKey *rsa.PrivateKey) ([]byte, error) { + h := sha256.New() + h.Write(data) + d := h.Sum(nil) + return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, d) +} + +func (t *TokenManager) getRsaPrivateKey() (*rsa.PrivateKey, error) { + block, _ := pem.Decode([]byte(t.privateKey)) + if block == nil { + return nil, errors.New("invalid private key format") + } + + switch block.Type { + case "PRIVATE KEY": + key, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + return nil, err + } + return key.(*rsa.PrivateKey), nil + case "RSA PRIVATE KEY": + key, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + return nil, err + } + return key, nil + default: + return nil, fmt.Errorf("unsupported key type %q", block.Type) + } +}