76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
package office
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
func signJWT(payload any, secret string) (string, error) {
|
|
if secret == "" {
|
|
return "", nil
|
|
}
|
|
header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`))
|
|
bodyBytes, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
body := base64.RawURLEncoding.EncodeToString(bodyBytes)
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
_, _ = mac.Write([]byte(header + "." + body))
|
|
sig := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
|
|
return header + "." + body + "." + sig, nil
|
|
}
|
|
|
|
func wrapConfig(config map[string]any, secret string) (map[string]any, error) {
|
|
if secret == "" {
|
|
return config, nil
|
|
}
|
|
token, err := signJWT(config, secret)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
config["token"] = token
|
|
return config, nil
|
|
}
|
|
|
|
func verifyJWT(token, secret string) (map[string]any, error) {
|
|
if secret == "" || token == "" {
|
|
return nil, fmt.Errorf("missing token or secret")
|
|
}
|
|
parts := splitJWT(token)
|
|
if len(parts) != 3 {
|
|
return nil, fmt.Errorf("invalid token")
|
|
}
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
_, _ = mac.Write([]byte(parts[0] + "." + parts[1]))
|
|
expected := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
|
|
if !hmac.Equal([]byte(expected), []byte(parts[2])) {
|
|
return nil, fmt.Errorf("invalid signature")
|
|
}
|
|
raw, err := base64.RawURLEncoding.DecodeString(parts[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var payload map[string]any
|
|
if err := json.Unmarshal(raw, &payload); err != nil {
|
|
return nil, err
|
|
}
|
|
return payload, nil
|
|
}
|
|
|
|
func splitJWT(token string) []string {
|
|
var parts []string
|
|
start := 0
|
|
for i := 0; i < len(token); i++ {
|
|
if token[i] == '.' {
|
|
parts = append(parts, token[start:i])
|
|
start = i + 1
|
|
}
|
|
}
|
|
parts = append(parts, token[start:])
|
|
return parts
|
|
}
|