live-sfu-demo/internal/server/token.go

66 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package server
import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"strings"
"time"
)
// SRS 推流 JWT(HS256)。服务端签发、并在 WHIP 反代层校验 role=publish,
// 形成「分发入口」的访问控制。Cloudflare 走自身 AppSecret,无需此 token。
func b64url(b []byte) string { return base64.RawURLEncoding.EncodeToString(b) }
type streamClaims struct {
Room string `json:"room"`
Identity string `json:"identity"`
Role string `json:"role"`
Exp int64 `json:"exp"`
Iat int64 `json:"iat"`
}
func signStreamToken(secret, room, identity, role string, ttl time.Duration) (string, error) {
now := time.Now()
c := streamClaims{Room: room, Identity: identity, Role: role, Iat: now.Unix(), Exp: now.Add(ttl).Unix()}
payload, _ := json.Marshal(c)
header, _ := json.Marshal(map[string]string{"alg": "HS256", "typ": "JWT"})
signing := b64url(header) + "." + b64url(payload)
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(signing))
return signing + "." + b64url(mac.Sum(nil)), nil
}
func verifyStreamToken(secret, token string) (*streamClaims, error) {
parts := strings.Split(token, ".")
if len(parts) != 3 {
return nil, errors.New("bad token")
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(parts[0] + "." + parts[1]))
if !hmac.Equal([]byte(b64url(mac.Sum(nil))), []byte(parts[2])) {
return nil, errors.New("bad signature")
}
p, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return nil, err
}
var c streamClaims
if err := json.Unmarshal(p, &c); err != nil {
return nil, err
}
if c.Exp < time.Now().Unix() {
return nil, errors.New("token expired")
}
return &c, nil
}
func randomID() string {
b := make([]byte, 9)
rand.Read(b)
return base64.RawURLEncoding.EncodeToString(b)
}