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