package jitsi import ( "crypto/rand" "encoding/hex" "fmt" "time" "github.com/golang-jwt/jwt/v5" ) type Config struct { Secret string AppID string AppName string Domain string SiteDomain string } type JitsiClaims struct { jwt.RegisteredClaims Room string `json:"room,omitempty"` Context *JitsiContext `json:"context,omitempty"` } type JitsiContext struct { User *JitsiUser `json:"user,omitempty"` } type JitsiUser struct { ID string `json:"id"` Name string `json:"name"` Email string `json:"email,omitempty"` Avatar string `json:"avatar,omitempty"` Moderator bool `json:"moderator"` } func GenerateSecret() string { b := make([]byte, 32) rand.Read(b) return hex.EncodeToString(b) } func (c *Config) MeetURL(room, jwtToken string) string { domain := c.Domain if domain == "" { domain = "meet.jit.si" } return fmt.Sprintf("https://%s/%s?jwt=%s", domain, room, jwtToken) } func (c *Config) GenerateToken(userID, userName, room string, moderator bool, avatar string) (string, error) { if c.Secret == "" { return "", fmt.Errorf("jitsi secret is not configured") } if c.AppID == "" { return "", fmt.Errorf("jitsi app id is not configured") } now := time.Now().UTC() claims := JitsiClaims{ RegisteredClaims: jwt.RegisteredClaims{ Issuer: c.AppID, Subject: userID, Audience: jwt.ClaimStrings{c.AppID}, IssuedAt: jwt.NewNumericDate(now), NotBefore: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(now.Add(1 * time.Hour)), ID: fmt.Sprintf("%s-%d", userID, now.Unix()), }, Room: room, Context: &JitsiContext{ User: &JitsiUser{ ID: userID, Name: userName, Avatar: avatar, Moderator: moderator, }, }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(c.Secret)) }