You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-zello-client/client/tokenmanager.go

90 lines
1.9 KiB
Go

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)
}
}