diff --git a/pkg/auth/accesstoken.go b/pkg/auth/accesstoken.go new file mode 100644 index 000000000..f528bc9e3 --- /dev/null +++ b/pkg/auth/accesstoken.go @@ -0,0 +1,63 @@ +package auth + +import ( + "time" + + "gopkg.in/square/go-jose.v2" + "gopkg.in/square/go-jose.v2/jwt" +) + +// Signer that produces token signed with API key and secret +type AccessToken struct { + apiKey string + secret string + identity string + grant *VideoGrant + validFor time.Duration +} + +func NewAccessToken(key string, secret string) *AccessToken { + return &AccessToken{ + apiKey: key, + secret: secret, + } +} + +func (t *AccessToken) SetIdentity(identity string) *AccessToken { + t.identity = identity + return t +} + +func (t *AccessToken) SetValidFor(duration time.Duration) *AccessToken { + t.validFor = duration + return t +} + +func (t *AccessToken) AddGrant(grant *VideoGrant) *AccessToken { + t.grant = grant + return t +} + +func (t *AccessToken) ToJWT() (string, error) { + if t.apiKey == "" || t.secret == "" { + return "", ErrKeysMissing + } + + sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: []byte(t.secret)}, + (&jose.SignerOptions{}).WithType("JWT")) + if err != nil { + return "", err + } + + cl := jwt.Claims{ + Issuer: t.apiKey, + NotBefore: jwt.NewNumericDate(time.Now()), + Expiry: jwt.NewNumericDate(time.Now().Add(t.validFor)), + ID: t.identity, + } + grants := &ClaimGrants{} + if t.grant != nil { + grants.Video = t.grant + } + return jwt.Signed(sig).Claims(cl).Claims(grants).CompactSerialize() +} diff --git a/pkg/auth/issuer_test.go b/pkg/auth/accesstoken_test.go similarity index 61% rename from pkg/auth/issuer_test.go rename to pkg/auth/accesstoken_test.go index 1d4186234..e06ac4f20 100644 --- a/pkg/auth/issuer_test.go +++ b/pkg/auth/accesstoken_test.go @@ -14,31 +14,33 @@ import ( func TestAPIIssuer(t *testing.T) { t.Run("keys must be set", func(t *testing.T) { - s := auth.NewAPIKeyTokenIssuer("", "") - _, err := s.CreateToken(&auth.GrantClaims{}, time.Hour) + token := auth.NewAccessToken("", "") + _, err := token.ToJWT() assert.Equal(t, auth.ErrKeysMissing, err) }) t.Run("generates a decodeable key", func(t *testing.T) { apiKey, secret := apiKeypair() - //fmt.Println(apiKey, secret) - s := auth.NewAPIKeyTokenIssuer(apiKey, secret) - claims := auth.GrantClaims{RoomJoin: true, Room: "myroom"} - raw, err := s.CreateToken(&claims, time.Hour) + videoGrant := &auth.VideoGrant{RoomJoin: true, Room: "myroom"} + at := auth.NewAccessToken(apiKey, secret). + AddGrant(videoGrant). + SetValidFor(time.Minute * 5). + SetIdentity("user") + value, err := at.ToJWT() //fmt.Println(raw) assert.NoError(t, err) - assert.Len(t, strings.Split(raw, "."), 3) + assert.Len(t, strings.Split(value, "."), 3) // ensure it's a valid JWT - token, err := jwt.ParseSigned(raw) + token, err := jwt.ParseSigned(value) assert.NoError(t, err) - decodedGrant := auth.GrantClaims{} + decodedGrant := auth.ClaimGrants{} err = token.UnsafeClaimsWithoutVerification(&decodedGrant) assert.NoError(t, err) - assert.EqualValues(t, &claims, &decodedGrant) + assert.EqualValues(t, videoGrant, decodedGrant.Video) }) } diff --git a/pkg/auth/authfakes/fake_key_provider.go b/pkg/auth/authfakes/fake_key_provider.go index ad847ab78..5f68e9e28 100644 --- a/pkg/auth/authfakes/fake_key_provider.go +++ b/pkg/auth/authfakes/fake_key_provider.go @@ -19,14 +19,14 @@ type FakeKeyProvider struct { getSecretReturnsOnCall map[int]struct { result1 string } - KeyCountStub func() int - keyCountMutex sync.RWMutex - keyCountArgsForCall []struct { + NumKeysStub func() int + numKeysMutex sync.RWMutex + numKeysArgsForCall []struct { } - keyCountReturns struct { + numKeysReturns struct { result1 int } - keyCountReturnsOnCall map[int]struct { + numKeysReturnsOnCall map[int]struct { result1 int } invocations map[string][][]interface{} @@ -95,14 +95,14 @@ func (fake *FakeKeyProvider) GetSecretReturnsOnCall(i int, result1 string) { } func (fake *FakeKeyProvider) NumKeys() int { - fake.keyCountMutex.Lock() - ret, specificReturn := fake.keyCountReturnsOnCall[len(fake.keyCountArgsForCall)] - fake.keyCountArgsForCall = append(fake.keyCountArgsForCall, struct { + fake.numKeysMutex.Lock() + ret, specificReturn := fake.numKeysReturnsOnCall[len(fake.numKeysArgsForCall)] + fake.numKeysArgsForCall = append(fake.numKeysArgsForCall, struct { }{}) - stub := fake.KeyCountStub - fakeReturns := fake.keyCountReturns + stub := fake.NumKeysStub + fakeReturns := fake.numKeysReturns fake.recordInvocation("NumKeys", []interface{}{}) - fake.keyCountMutex.Unlock() + fake.numKeysMutex.Unlock() if stub != nil { return stub() } @@ -112,37 +112,37 @@ func (fake *FakeKeyProvider) NumKeys() int { return fakeReturns.result1 } -func (fake *FakeKeyProvider) KeyCountCallCount() int { - fake.keyCountMutex.RLock() - defer fake.keyCountMutex.RUnlock() - return len(fake.keyCountArgsForCall) +func (fake *FakeKeyProvider) NumKeysCallCount() int { + fake.numKeysMutex.RLock() + defer fake.numKeysMutex.RUnlock() + return len(fake.numKeysArgsForCall) } -func (fake *FakeKeyProvider) KeyCountCalls(stub func() int) { - fake.keyCountMutex.Lock() - defer fake.keyCountMutex.Unlock() - fake.KeyCountStub = stub +func (fake *FakeKeyProvider) NumKeysCalls(stub func() int) { + fake.numKeysMutex.Lock() + defer fake.numKeysMutex.Unlock() + fake.NumKeysStub = stub } -func (fake *FakeKeyProvider) KeyCountReturns(result1 int) { - fake.keyCountMutex.Lock() - defer fake.keyCountMutex.Unlock() - fake.KeyCountStub = nil - fake.keyCountReturns = struct { +func (fake *FakeKeyProvider) NumKeysReturns(result1 int) { + fake.numKeysMutex.Lock() + defer fake.numKeysMutex.Unlock() + fake.NumKeysStub = nil + fake.numKeysReturns = struct { result1 int }{result1} } -func (fake *FakeKeyProvider) KeyCountReturnsOnCall(i int, result1 int) { - fake.keyCountMutex.Lock() - defer fake.keyCountMutex.Unlock() - fake.KeyCountStub = nil - if fake.keyCountReturnsOnCall == nil { - fake.keyCountReturnsOnCall = make(map[int]struct { +func (fake *FakeKeyProvider) NumKeysReturnsOnCall(i int, result1 int) { + fake.numKeysMutex.Lock() + defer fake.numKeysMutex.Unlock() + fake.NumKeysStub = nil + if fake.numKeysReturnsOnCall == nil { + fake.numKeysReturnsOnCall = make(map[int]struct { result1 int }) } - fake.keyCountReturnsOnCall[i] = struct { + fake.numKeysReturnsOnCall[i] = struct { result1 int }{result1} } @@ -152,8 +152,8 @@ func (fake *FakeKeyProvider) Invocations() map[string][][]interface{} { defer fake.invocationsMutex.RUnlock() fake.getSecretMutex.RLock() defer fake.getSecretMutex.RUnlock() - fake.keyCountMutex.RLock() - defer fake.keyCountMutex.RUnlock() + fake.numKeysMutex.RLock() + defer fake.numKeysMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/pkg/auth/authfakes/fake_token_issuer.go b/pkg/auth/authfakes/fake_token_issuer.go deleted file mode 100644 index ecc00149c..000000000 --- a/pkg/auth/authfakes/fake_token_issuer.go +++ /dev/null @@ -1,119 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package authfakes - -import ( - "sync" - "time" - - "github.com/livekit/livekit-server/pkg/auth" -) - -type FakeTokenIssuer struct { - CreateTokenStub func(*auth.GrantClaims, time.Duration) (string, error) - createTokenMutex sync.RWMutex - createTokenArgsForCall []struct { - arg1 *auth.GrantClaims - arg2 time.Duration - } - createTokenReturns struct { - result1 string - result2 error - } - createTokenReturnsOnCall map[int]struct { - result1 string - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *FakeTokenIssuer) CreateToken(arg1 *auth.GrantClaims, arg2 time.Duration) (string, error) { - fake.createTokenMutex.Lock() - ret, specificReturn := fake.createTokenReturnsOnCall[len(fake.createTokenArgsForCall)] - fake.createTokenArgsForCall = append(fake.createTokenArgsForCall, struct { - arg1 *auth.GrantClaims - arg2 time.Duration - }{arg1, arg2}) - stub := fake.CreateTokenStub - fakeReturns := fake.createTokenReturns - fake.recordInvocation("CreateToken", []interface{}{arg1, arg2}) - fake.createTokenMutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *FakeTokenIssuer) CreateTokenCallCount() int { - fake.createTokenMutex.RLock() - defer fake.createTokenMutex.RUnlock() - return len(fake.createTokenArgsForCall) -} - -func (fake *FakeTokenIssuer) CreateTokenCalls(stub func(*auth.GrantClaims, time.Duration) (string, error)) { - fake.createTokenMutex.Lock() - defer fake.createTokenMutex.Unlock() - fake.CreateTokenStub = stub -} - -func (fake *FakeTokenIssuer) CreateTokenArgsForCall(i int) (*auth.GrantClaims, time.Duration) { - fake.createTokenMutex.RLock() - defer fake.createTokenMutex.RUnlock() - argsForCall := fake.createTokenArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *FakeTokenIssuer) CreateTokenReturns(result1 string, result2 error) { - fake.createTokenMutex.Lock() - defer fake.createTokenMutex.Unlock() - fake.CreateTokenStub = nil - fake.createTokenReturns = struct { - result1 string - result2 error - }{result1, result2} -} - -func (fake *FakeTokenIssuer) CreateTokenReturnsOnCall(i int, result1 string, result2 error) { - fake.createTokenMutex.Lock() - defer fake.createTokenMutex.Unlock() - fake.CreateTokenStub = nil - if fake.createTokenReturnsOnCall == nil { - fake.createTokenReturnsOnCall = make(map[int]struct { - result1 string - result2 error - }) - } - fake.createTokenReturnsOnCall[i] = struct { - result1 string - result2 error - }{result1, result2} -} - -func (fake *FakeTokenIssuer) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.createTokenMutex.RLock() - defer fake.createTokenMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *FakeTokenIssuer) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ auth.TokenIssuer = new(FakeTokenIssuer) diff --git a/pkg/auth/authfakes/fake_token_verifier.go b/pkg/auth/authfakes/fake_token_verifier.go index 656354191..a3cd92ece 100644 --- a/pkg/auth/authfakes/fake_token_verifier.go +++ b/pkg/auth/authfakes/fake_token_verifier.go @@ -8,33 +8,98 @@ import ( ) type FakeTokenVerifier struct { - VerifyStub func() (*auth.GrantClaims, error) + IdentityStub func() string + identityMutex sync.RWMutex + identityArgsForCall []struct { + } + identityReturns struct { + result1 string + } + identityReturnsOnCall map[int]struct { + result1 string + } + VerifyStub func(interface{}) (*auth.VideoGrant, error) verifyMutex sync.RWMutex verifyArgsForCall []struct { + arg1 interface{} } verifyReturns struct { - result1 *auth.GrantClaims + result1 *auth.VideoGrant result2 error } verifyReturnsOnCall map[int]struct { - result1 *auth.GrantClaims + result1 *auth.VideoGrant result2 error } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } -func (fake *FakeTokenVerifier) Verify() (*auth.GrantClaims, error) { +func (fake *FakeTokenVerifier) Identity() string { + fake.identityMutex.Lock() + ret, specificReturn := fake.identityReturnsOnCall[len(fake.identityArgsForCall)] + fake.identityArgsForCall = append(fake.identityArgsForCall, struct { + }{}) + stub := fake.IdentityStub + fakeReturns := fake.identityReturns + fake.recordInvocation("Identity", []interface{}{}) + fake.identityMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeTokenVerifier) IdentityCallCount() int { + fake.identityMutex.RLock() + defer fake.identityMutex.RUnlock() + return len(fake.identityArgsForCall) +} + +func (fake *FakeTokenVerifier) IdentityCalls(stub func() string) { + fake.identityMutex.Lock() + defer fake.identityMutex.Unlock() + fake.IdentityStub = stub +} + +func (fake *FakeTokenVerifier) IdentityReturns(result1 string) { + fake.identityMutex.Lock() + defer fake.identityMutex.Unlock() + fake.IdentityStub = nil + fake.identityReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeTokenVerifier) IdentityReturnsOnCall(i int, result1 string) { + fake.identityMutex.Lock() + defer fake.identityMutex.Unlock() + fake.IdentityStub = nil + if fake.identityReturnsOnCall == nil { + fake.identityReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.identityReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeTokenVerifier) Verify(arg1 interface{}) (*auth.VideoGrant, error) { fake.verifyMutex.Lock() ret, specificReturn := fake.verifyReturnsOnCall[len(fake.verifyArgsForCall)] fake.verifyArgsForCall = append(fake.verifyArgsForCall, struct { - }{}) + arg1 interface{} + }{arg1}) stub := fake.VerifyStub fakeReturns := fake.verifyReturns - fake.recordInvocation("Verify", []interface{}{}) + fake.recordInvocation("Verify", []interface{}{arg1}) fake.verifyMutex.Unlock() if stub != nil { - return stub() + return stub(arg1) } if specificReturn { return ret.result1, ret.result2 @@ -48,34 +113,41 @@ func (fake *FakeTokenVerifier) VerifyCallCount() int { return len(fake.verifyArgsForCall) } -func (fake *FakeTokenVerifier) VerifyCalls(stub func() (*auth.GrantClaims, error)) { +func (fake *FakeTokenVerifier) VerifyCalls(stub func(interface{}) (*auth.VideoGrant, error)) { fake.verifyMutex.Lock() defer fake.verifyMutex.Unlock() fake.VerifyStub = stub } -func (fake *FakeTokenVerifier) VerifyReturns(result1 *auth.GrantClaims, result2 error) { +func (fake *FakeTokenVerifier) VerifyArgsForCall(i int) interface{} { + fake.verifyMutex.RLock() + defer fake.verifyMutex.RUnlock() + argsForCall := fake.verifyArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeTokenVerifier) VerifyReturns(result1 *auth.VideoGrant, result2 error) { fake.verifyMutex.Lock() defer fake.verifyMutex.Unlock() fake.VerifyStub = nil fake.verifyReturns = struct { - result1 *auth.GrantClaims + result1 *auth.VideoGrant result2 error }{result1, result2} } -func (fake *FakeTokenVerifier) VerifyReturnsOnCall(i int, result1 *auth.GrantClaims, result2 error) { +func (fake *FakeTokenVerifier) VerifyReturnsOnCall(i int, result1 *auth.VideoGrant, result2 error) { fake.verifyMutex.Lock() defer fake.verifyMutex.Unlock() fake.VerifyStub = nil if fake.verifyReturnsOnCall == nil { fake.verifyReturnsOnCall = make(map[int]struct { - result1 *auth.GrantClaims + result1 *auth.VideoGrant result2 error }) } fake.verifyReturnsOnCall[i] = struct { - result1 *auth.GrantClaims + result1 *auth.VideoGrant result2 error }{result1, result2} } @@ -83,6 +155,8 @@ func (fake *FakeTokenVerifier) VerifyReturnsOnCall(i int, result1 *auth.GrantCla func (fake *FakeTokenVerifier) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() + fake.identityMutex.RLock() + defer fake.identityMutex.RUnlock() fake.verifyMutex.RLock() defer fake.verifyMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} diff --git a/pkg/auth/grants.go b/pkg/auth/grants.go index f0adfaffe..5e52e8320 100644 --- a/pkg/auth/grants.go +++ b/pkg/auth/grants.go @@ -1,7 +1,11 @@ package auth -type GrantClaims struct { +type VideoGrant struct { RoomCreate bool `json:"room_create,omitempty"` RoomJoin bool `json:"room_join,omitempty"` - Room string `json:"room"` + Room string `json:"room,omitempty"` +} + +type ClaimGrants struct { + Video *VideoGrant `json:"video,omitempty"` } diff --git a/pkg/auth/interfaces.go b/pkg/auth/interfaces.go index 433789f75..a2821481e 100644 --- a/pkg/auth/interfaces.go +++ b/pkg/auth/interfaces.go @@ -2,7 +2,6 @@ package auth import ( "errors" - "time" ) //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate @@ -11,14 +10,18 @@ var ( ErrKeysMissing = errors.New("missing API key or secret key") ) -//counterfeiter:generate . TokenIssuer -type TokenIssuer interface { - CreateToken(claims *GrantClaims, validFor time.Duration) (string, error) -} +////counterfeiter:generate . AccessToken +//type AccessToken interface { +// SetExpiration(time.Duration) AccessToken +// Identity(string) AccessToken +// AddGrant(*VideoGrant) AccessToken +// ToJWT() (string, error) +//} //counterfeiter:generate . TokenVerifier type TokenVerifier interface { - Verify() (*GrantClaims, error) + Identity() string + Verify(key interface{}) (*VideoGrant, error) } //counterfeiter:generate . KeyProvider diff --git a/pkg/auth/issuer.go b/pkg/auth/issuer.go deleted file mode 100644 index a91a8366f..000000000 --- a/pkg/auth/issuer.go +++ /dev/null @@ -1,41 +0,0 @@ -package auth - -import ( - "time" - - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" -) - -// Signer that produces token signed with API key and secret -type APIKeyTokenIssuer struct { - APIKey string - SecretKey string -} - -func NewAPIKeyTokenIssuer(key string, secret string) *APIKeyTokenIssuer { - return &APIKeyTokenIssuer{ - APIKey: key, - SecretKey: secret, - } -} - -func (s *APIKeyTokenIssuer) CreateToken(claims *GrantClaims, validFor time.Duration) (string, error) { - if s.APIKey == "" || s.SecretKey == "" { - return "", ErrKeysMissing - } - sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: []byte(s.SecretKey)}, - (&jose.SignerOptions{}).WithType("JWT")) - if err != nil { - return "", err - } - - cl := jwt.Claims{ - Issuer: s.APIKey, - Subject: s.APIKey, - NotBefore: jwt.NewNumericDate(time.Now()), - Expiry: jwt.NewNumericDate(time.Now().Add(validFor)), - } - - return jwt.Signed(sig).Claims(cl).Claims(claims).CompactSerialize() -} diff --git a/pkg/auth/verifier.go b/pkg/auth/verifier.go index fd963962d..17337ed6c 100644 --- a/pkg/auth/verifier.go +++ b/pkg/auth/verifier.go @@ -7,9 +7,9 @@ import ( ) type APIKeyTokenVerifier struct { - token *jwt.JSONWebToken - apiKey string - secretKey string + token *jwt.JSONWebToken + identity string + apiKey string } func ParseAPIToken(raw string) (*APIKeyTokenVerifier, error) { @@ -24,8 +24,9 @@ func ParseAPIToken(raw string) (*APIKeyTokenVerifier, error) { } return &APIKeyTokenVerifier{ - token: tok, - apiKey: out.Issuer, + token: tok, + apiKey: out.Issuer, + identity: out.ID, }, nil } @@ -34,21 +35,24 @@ func (v *APIKeyTokenVerifier) APIKey() string { return v.apiKey } -func (v *APIKeyTokenVerifier) SetSecretKey(secret string) { - v.secretKey = secret +func (v *APIKeyTokenVerifier) Identity() string { + return v.identity } -func (v *APIKeyTokenVerifier) Verify() (*GrantClaims, error) { - if v.secretKey == "" { +func (v *APIKeyTokenVerifier) Verify(key interface{}) (*VideoGrant, error) { + if key == nil || key == "" { return nil, ErrKeysMissing } + if s, ok := key.(string); ok { + key = []byte(s) + } out := jwt.Claims{} - claims := GrantClaims{} - if err := v.token.Claims([]byte(v.secretKey), &out, &claims); err != nil { + claims := ClaimGrants{} + if err := v.token.Claims(key, &out, &claims); err != nil { return nil, err } if err := out.Validate(jwt.Expected{Issuer: v.apiKey, Time: time.Now()}); err != nil { return nil, err } - return &claims, nil + return claims.Video, nil } diff --git a/pkg/auth/verifier_test.go b/pkg/auth/verifier_test.go index 0f2d14715..a8afaa3b7 100644 --- a/pkg/auth/verifier_test.go +++ b/pkg/auth/verifier_test.go @@ -18,34 +18,35 @@ func TestAPIVerifier(t *testing.T) { assert.NoError(t, err) assert.Equal(t, apiKey, v.APIKey()) - _, err = v.Verify() + _, err = v.Verify("") assert.Error(t, err) - v.SetSecretKey("anothersecret") - _, err = v.Verify() + _, err = v.Verify("anothersecret") assert.Error(t, err) }) t.Run("key has expired", func(t *testing.T) { v, err := auth.ParseAPIToken(accessToken) - v.SetSecretKey(secret) - _, err = v.Verify() + _, err = v.Verify(secret) assert.Error(t, err) }) t.Run("unexpired token is verified", func(t *testing.T) { - s := auth.NewAPIKeyTokenIssuer(apiKey, secret) - claim := auth.GrantClaims{RoomCreate: true} - authToken, err := s.CreateToken(&claim, time.Minute) + claim := auth.VideoGrant{RoomCreate: true} + at := auth.NewAccessToken(apiKey, secret). + AddGrant(&claim). + SetValidFor(time.Minute). + SetIdentity("me") + authToken, err := at.ToJWT() assert.NoError(t, err) v, err := auth.ParseAPIToken(authToken) assert.NoError(t, err) assert.Equal(t, apiKey, v.APIKey()) + assert.Equal(t, "me", v.Identity()) - v.SetSecretKey(secret) - decoded, err := v.Verify() + decoded, err := v.Verify(secret) assert.NoError(t, err) assert.Equal(t, &claim, decoded) }) diff --git a/pkg/rtc/mediaengine.go b/pkg/rtc/mediaengine.go deleted file mode 100644 index 9efb03c82..000000000 --- a/pkg/rtc/mediaengine.go +++ /dev/null @@ -1,82 +0,0 @@ -package rtc - -import ( - "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" -) - -const ( - mimeTypeH264 = "video/h264" - mimeTypeOpus = "audio/opus" - mimeTypeVP8 = "video/vp8" - mimeTypeVP9 = "video/vp9" -) - -func createMediaEngine() (*webrtc.MediaEngine, error) { - me := &webrtc.MediaEngine{} - if err := me.RegisterCodec(webrtc.RTPCodecParameters{ - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeOpus, ClockRate: 48000, Channels: 2, SDPFmtpLine: "minptime=10;useinbandfec=1", RTCPFeedback: nil}, - PayloadType: 111, - }, webrtc.RTPCodecTypeAudio); err != nil { - return nil, err - } - - videoRTCPFeedback := []webrtc.RTCPFeedback{{"goog-remb", ""}, {"ccm", "fir"}, {"nack", ""}, {"nack", "pli"}} - for _, codec := range []webrtc.RTPCodecParameters{ - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeVP8, ClockRate: 90000, RTCPFeedback: videoRTCPFeedback}, - PayloadType: 96, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeVP9, ClockRate: 90000, SDPFmtpLine: "profile-id=0", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 98, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeVP9, ClockRate: 90000, SDPFmtpLine: "profile-id=1", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 100, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 102, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 127, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 125, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 108, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 127, - }, - { - RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: mimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032", RTCPFeedback: videoRTCPFeedback}, - PayloadType: 123, - }, - } { - if err := me.RegisterCodec(codec, webrtc.RTPCodecTypeVideo); err != nil { - return nil, err - } - } - - for _, extension := range []string{ - sdp.SDESMidURI, - sdp.SDESRTPStreamIDURI, - sdp.TransportCCURI, - } { - if err := me.RegisterHeaderExtension(webrtc.RTPHeaderExtensionCapability{URI: extension}, webrtc.RTPCodecTypeAudio); err != nil { - return nil, err - } - if err := me.RegisterHeaderExtension(webrtc.RTPHeaderExtensionCapability{URI: extension}, webrtc.RTPCodecTypeVideo); err != nil { - return nil, err - } - } - - return me, nil -} diff --git a/pkg/service/auth.go b/pkg/service/auth.go index 541d76803..2e3fe3d98 100644 --- a/pkg/service/auth.go +++ b/pkg/service/auth.go @@ -58,9 +58,7 @@ func (m *APIKeyAuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, return } - v.SetSecretKey(secret) - - grants, err := v.Verify() + grants, err := v.Verify(secret) if err != nil { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("invalid token: " + err.Error())) @@ -75,8 +73,8 @@ func (m *APIKeyAuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next.ServeHTTP(w, r) } -func GetGrants(ctx context.Context) *auth.GrantClaims { - claims, ok := ctx.Value(grantsKey).(*auth.GrantClaims) +func GetGrants(ctx context.Context) *auth.VideoGrant { + claims, ok := ctx.Value(grantsKey).(*auth.VideoGrant) if !ok { return nil } diff --git a/pkg/service/auth_test.go b/pkg/service/auth_test.go index c339b23b5..40f79d3f5 100644 --- a/pkg/service/auth_test.go +++ b/pkg/service/auth_test.go @@ -4,7 +4,6 @@ import ( "net/http" "net/http/httptest" "testing" - "time" "github.com/stretchr/testify/assert" @@ -20,16 +19,17 @@ func TestAuthMiddleware(t *testing.T) { provider.GetSecretReturns(secret) m := service.NewAPIKeyAuthMiddleware(provider) - var grants *auth.GrantClaims + var grants *auth.VideoGrant handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { grants = service.GetGrants(r.Context()) w.WriteHeader(http.StatusOK) }) + orig := &auth.VideoGrant{Room: "abcdefg", RoomJoin: true} // ensure that the original claim could be retrieved - issuer := auth.NewAPIKeyTokenIssuer(api, secret) - orig := &auth.GrantClaims{Room: "abcdefg", RoomJoin: true} - token, err := issuer.CreateToken(orig, time.Minute) + at := auth.NewAccessToken(api, secret). + AddGrant(orig) + token, err := at.ToJWT() assert.NoError(t, err) r := &http.Request{Header: http.Header{}}