Skip to content

Commit 72446ad

Browse files
committed
ensure access token do not contain sensitive credentials
1 parent 7b3cb6d commit 72446ad

File tree

3 files changed

+411
-0
lines changed

3 files changed

+411
-0
lines changed

auth/accesstoken.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ func (t *AccessToken) ToJWT() (string, error) {
142142
return "", ErrKeysMissing
143143
}
144144

145+
if t.grant.RoomConfig != nil {
146+
if err := t.grant.RoomConfig.CheckCredentials(); err != nil {
147+
return "", err
148+
}
149+
}
150+
145151
sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: []byte(t.secret)},
146152
(&jose.SignerOptions{}).WithType("JWT"))
147153
if err != nil {

auth/grants.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package auth
1616

1717
import (
18+
"errors"
1819
"maps"
1920
"strings"
2021

@@ -33,6 +34,8 @@ var tokenMarshaler = protojson.MarshalOptions{
3334
EmitDefaultValues: false,
3435
}
3536

37+
var ErrSensitiveCredentials = errors.New("room configuration should not contain sensitive credentials")
38+
3639
func (c *RoomConfiguration) Clone() *RoomConfiguration {
3740
if c == nil {
3841
return nil
@@ -48,6 +51,116 @@ func (c *RoomConfiguration) UnmarshalJSON(data []byte) error {
4851
return protojson.Unmarshal(data, (*livekit.RoomConfiguration)(c))
4952
}
5053

54+
// CheckCredentials checks if the room configuration contains sensitive credentials
55+
// and returns an error if it does.
56+
//
57+
// This is used to prevent sensitive credentials from being leaked to the client.
58+
// It is not used to validate the credentials themselves, as that is done by the
59+
// egress service.
60+
func (c *RoomConfiguration) CheckCredentials() error {
61+
if c.Egress == nil {
62+
return nil
63+
}
64+
65+
if c.Egress.Participant != nil {
66+
for _, output := range c.Egress.Participant.FileOutputs {
67+
if err := checkOutputForCredentials(output.Output); err != nil {
68+
return err
69+
}
70+
}
71+
for _, output := range c.Egress.Participant.SegmentOutputs {
72+
if err := checkOutputForCredentials(output.Output); err != nil {
73+
return err
74+
}
75+
}
76+
}
77+
if c.Egress.Room != nil {
78+
for _, output := range c.Egress.Room.FileOutputs {
79+
if err := checkOutputForCredentials(output.Output); err != nil {
80+
return err
81+
}
82+
}
83+
for _, output := range c.Egress.Room.SegmentOutputs {
84+
if err := checkOutputForCredentials(output.Output); err != nil {
85+
return err
86+
}
87+
}
88+
for _, output := range c.Egress.Room.ImageOutputs {
89+
if err := checkOutputForCredentials(output.Output); err != nil {
90+
return err
91+
}
92+
}
93+
if len(c.Egress.Room.StreamOutputs) > 0 {
94+
// do not leak stream key
95+
return ErrSensitiveCredentials
96+
}
97+
}
98+
if c.Egress.Tracks != nil {
99+
if err := checkOutputForCredentials(c.Egress.Tracks.Output); err != nil {
100+
return err
101+
}
102+
}
103+
return nil
104+
}
105+
106+
func checkOutputForCredentials(output any) error {
107+
if output == nil {
108+
return nil
109+
}
110+
111+
switch msg := output.(type) {
112+
case *livekit.EncodedFileOutput_S3:
113+
if msg.S3.Secret != "" {
114+
return ErrSensitiveCredentials
115+
}
116+
case *livekit.SegmentedFileOutput_S3:
117+
if msg.S3.Secret != "" {
118+
return ErrSensitiveCredentials
119+
}
120+
case *livekit.AutoTrackEgress_S3:
121+
if msg.S3.Secret != "" {
122+
return ErrSensitiveCredentials
123+
}
124+
case *livekit.EncodedFileOutput_Gcp:
125+
if msg.Gcp.Credentials != "" {
126+
return ErrSensitiveCredentials
127+
}
128+
case *livekit.SegmentedFileOutput_Gcp:
129+
if msg.Gcp.Credentials != "" {
130+
return ErrSensitiveCredentials
131+
}
132+
case *livekit.AutoTrackEgress_Gcp:
133+
if msg.Gcp.Credentials != "" {
134+
return ErrSensitiveCredentials
135+
}
136+
case *livekit.EncodedFileOutput_Azure:
137+
if msg.Azure.AccountKey != "" {
138+
return ErrSensitiveCredentials
139+
}
140+
case *livekit.SegmentedFileOutput_Azure:
141+
if msg.Azure.AccountKey != "" {
142+
return ErrSensitiveCredentials
143+
}
144+
case *livekit.AutoTrackEgress_Azure:
145+
if msg.Azure.AccountKey != "" {
146+
return ErrSensitiveCredentials
147+
}
148+
case *livekit.EncodedFileOutput_AliOSS:
149+
if msg.AliOSS.Secret != "" {
150+
return ErrSensitiveCredentials
151+
}
152+
case *livekit.SegmentedFileOutput_AliOSS:
153+
if msg.AliOSS.Secret != "" {
154+
return ErrSensitiveCredentials
155+
}
156+
case *livekit.AutoTrackEgress_AliOSS:
157+
if msg.AliOSS.Secret != "" {
158+
return ErrSensitiveCredentials
159+
}
160+
}
161+
return nil
162+
}
163+
51164
type ClaimGrants struct {
52165
Identity string `json:"-"`
53166
Name string `json:"name,omitempty"`

0 commit comments

Comments
 (0)