parent
4b4c7eefe6
commit
972e41e92d
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue