mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2026-03-14 14:35:44 +01:00
Migrate to github.com/golang-jwt/jwt/v5
This commit is contained in:
parent
7608d9f81e
commit
e152b8dcda
14 changed files with 78 additions and 51 deletions
|
|
@ -26,7 +26,7 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type ProxyClientMessage struct {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/pion/sdp/v3"
|
||||
)
|
||||
|
||||
|
|
@ -394,11 +394,9 @@ func (p *HelloV2AuthParams) CheckValid() error {
|
|||
}
|
||||
|
||||
type AuthTokenClaims interface {
|
||||
TokenSubject() string
|
||||
TokenUserData() json.RawMessage
|
||||
jwt.Claims
|
||||
|
||||
VerifyIssuedAt(cmp time.Time, req bool) bool
|
||||
VerifyExpiresAt(cmp time.Time, req bool) bool
|
||||
GetUserData() json.RawMessage
|
||||
}
|
||||
|
||||
type HelloV2TokenClaims struct {
|
||||
|
|
@ -407,11 +405,7 @@ type HelloV2TokenClaims struct {
|
|||
UserData json.RawMessage `json:"userdata,omitempty"`
|
||||
}
|
||||
|
||||
func (c *HelloV2TokenClaims) TokenSubject() string {
|
||||
return c.Subject
|
||||
}
|
||||
|
||||
func (c *HelloV2TokenClaims) TokenUserData() json.RawMessage {
|
||||
func (c *HelloV2TokenClaims) GetUserData() json.RawMessage {
|
||||
return c.UserData
|
||||
}
|
||||
|
||||
|
|
@ -432,11 +426,7 @@ type FederationTokenClaims struct {
|
|||
UserData json.RawMessage `json:"userdata,omitempty"`
|
||||
}
|
||||
|
||||
func (c *FederationTokenClaims) TokenSubject() string {
|
||||
return c.Subject
|
||||
}
|
||||
|
||||
func (c *FederationTokenClaims) TokenUserData() json.RawMessage {
|
||||
func (c *FederationTokenClaims) GetUserData() json.RawMessage {
|
||||
return c.UserData
|
||||
}
|
||||
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -5,7 +5,7 @@ go 1.21.0
|
|||
require (
|
||||
github.com/dlintw/goconf v0.0.0-20120228082610-dcc070983490
|
||||
github.com/fsnotify/fsnotify v1.8.0
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/mux v1.8.1
|
||||
|
|
@ -41,6 +41,7 @@ require (
|
|||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -53,6 +53,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
|
||||
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
|
|
|
|||
53
hub.go
53
hub.go
|
|
@ -47,7 +47,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
|
@ -111,6 +111,9 @@ var (
|
|||
// Delay after which a "cleared" / "rejected" dialout status should be removed.
|
||||
removeCallStatusTTL = 5 * time.Second
|
||||
|
||||
// Allow time differences of up to one minute between server and proxy.
|
||||
tokenLeeway = time.Minute
|
||||
|
||||
DefaultTrustedProxies = DefaultPrivateIps()
|
||||
)
|
||||
|
||||
|
|
@ -1338,15 +1341,20 @@ func (h *Hub) processHelloV2(ctx context.Context, client HandlerClient, message
|
|||
}
|
||||
|
||||
return key, nil
|
||||
})
|
||||
}, jwt.WithValidMethods([]string{
|
||||
jwt.SigningMethodRS256.Alg(),
|
||||
jwt.SigningMethodRS384.Alg(),
|
||||
jwt.SigningMethodRS512.Alg(),
|
||||
jwt.SigningMethodES256.Alg(),
|
||||
jwt.SigningMethodES384.Alg(),
|
||||
jwt.SigningMethodES512.Alg(),
|
||||
jwt.SigningMethodEdDSA.Alg(),
|
||||
}), jwt.WithIssuedAt(), jwt.WithLeeway(tokenLeeway))
|
||||
if err != nil {
|
||||
if err, ok := err.(*jwt.ValidationError); ok {
|
||||
if err.Errors&jwt.ValidationErrorIssuedAt == jwt.ValidationErrorIssuedAt {
|
||||
return nil, nil, TokenNotValidYet
|
||||
}
|
||||
if err.Errors&jwt.ValidationErrorExpired == jwt.ValidationErrorExpired {
|
||||
return nil, nil, TokenExpired
|
||||
}
|
||||
if errors.Is(err, jwt.ErrTokenNotValidYet) || errors.Is(err, jwt.ErrTokenUsedBeforeIssued) {
|
||||
return nil, nil, TokenNotValidYet
|
||||
} else if errors.Is(err, jwt.ErrTokenExpired) {
|
||||
return nil, nil, TokenExpired
|
||||
}
|
||||
|
||||
return nil, nil, InvalidToken
|
||||
|
|
@ -1367,20 +1375,35 @@ func (h *Hub) processHelloV2(ctx context.Context, client HandlerClient, message
|
|||
}
|
||||
authTokenClaims = claims
|
||||
}
|
||||
now := time.Now()
|
||||
if !authTokenClaims.VerifyIssuedAt(now, true) {
|
||||
return nil, nil, TokenNotValidYet
|
||||
|
||||
issuedAt, err := authTokenClaims.GetIssuedAt()
|
||||
if err != nil {
|
||||
return nil, nil, InvalidToken
|
||||
}
|
||||
if !authTokenClaims.VerifyExpiresAt(now, true) {
|
||||
expiresAt, err := authTokenClaims.GetExpirationTime()
|
||||
if err != nil {
|
||||
return nil, nil, InvalidToken
|
||||
}
|
||||
now := time.Now()
|
||||
if issuedAt != nil && expiresAt != nil && expiresAt.Before(issuedAt.Time) {
|
||||
return nil, nil, TokenExpired
|
||||
} else if issuedAt == nil {
|
||||
return nil, nil, TokenNotValidYet
|
||||
} else if minExpiresAt := now.Add(-tokenLeeway); expiresAt == nil || expiresAt.Before(minExpiresAt) {
|
||||
return nil, nil, TokenExpired
|
||||
}
|
||||
|
||||
subject, err := authTokenClaims.GetSubject()
|
||||
if err != nil {
|
||||
return nil, nil, InvalidToken
|
||||
}
|
||||
|
||||
auth := &BackendClientResponse{
|
||||
Type: "auth",
|
||||
Auth: &BackendClientAuthResponse{
|
||||
Version: message.Hello.Version,
|
||||
UserId: authTokenClaims.TokenSubject(),
|
||||
User: authTokenClaims.TokenUserData(),
|
||||
UserId: subject,
|
||||
User: authTokenClaims.GetUserData(),
|
||||
},
|
||||
}
|
||||
return backend, auth, nil
|
||||
|
|
|
|||
11
hub_test.go
11
hub_test.go
|
|
@ -44,7 +44,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -934,7 +934,7 @@ func TestClientHelloV2_IssuedInFuture(t *testing.T) {
|
|||
client := NewTestClient(t, server, hub)
|
||||
defer client.CloseWithBye()
|
||||
|
||||
issuedAt := time.Now().Add(time.Minute)
|
||||
issuedAt := time.Now().Add(tokenLeeway * 2)
|
||||
expiresAt := issuedAt.Add(time.Second)
|
||||
require.NoError(client.SendHelloV2WithTimes(testDefaultUserId, issuedAt, expiresAt))
|
||||
|
||||
|
|
@ -962,8 +962,9 @@ func TestClientHelloV2_Expired(t *testing.T) {
|
|||
client := NewTestClient(t, server, hub)
|
||||
defer client.CloseWithBye()
|
||||
|
||||
issuedAt := time.Now().Add(-time.Minute)
|
||||
require.NoError(client.SendHelloV2WithTimes(testDefaultUserId, issuedAt, issuedAt.Add(time.Second)))
|
||||
issuedAt := time.Now().Add(-tokenLeeway * 3)
|
||||
expiresAt := time.Now().Add(-tokenLeeway * 2)
|
||||
require.NoError(client.SendHelloV2WithTimes(testDefaultUserId, issuedAt, expiresAt))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||
defer cancel()
|
||||
|
|
@ -1017,7 +1018,7 @@ func TestClientHelloV2_ExpiresAtMissing(t *testing.T) {
|
|||
client := NewTestClient(t, server, hub)
|
||||
defer client.CloseWithBye()
|
||||
|
||||
issuedAt := time.Now().Add(-time.Minute)
|
||||
issuedAt := time.Now()
|
||||
var expiresAt time.Time
|
||||
require.NoError(client.SendHelloV2WithTimes(testDefaultUserId, issuedAt, expiresAt))
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
signaling "github.com/strukturag/nextcloud-spreed-signaling"
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
|
|
@ -71,6 +71,9 @@ const (
|
|||
// Maximum age a token may have to prevent reuse of old tokens.
|
||||
maxTokenAge = 5 * time.Minute
|
||||
|
||||
// Allow time differences of up to one minute between server and proxy.
|
||||
tokenLeeway = time.Minute
|
||||
|
||||
remotePublisherTimeout = 5 * time.Second
|
||||
|
||||
ProxyFeatureRemoteStreams = "remote-streams"
|
||||
|
|
@ -1296,13 +1299,18 @@ func (s *ProxyServer) parseToken(tokenValue string) (*signaling.TokenClaims, str
|
|||
}
|
||||
|
||||
return tokenKey.key, nil
|
||||
})
|
||||
if err, ok := err.(*jwt.ValidationError); ok {
|
||||
if err.Errors&jwt.ValidationErrorIssuedAt == jwt.ValidationErrorIssuedAt {
|
||||
return nil, "not-valid-yet", TokenNotValidYet
|
||||
}
|
||||
}
|
||||
}, jwt.WithValidMethods([]string{
|
||||
jwt.SigningMethodRS256.Alg(),
|
||||
jwt.SigningMethodRS384.Alg(),
|
||||
jwt.SigningMethodRS512.Alg(),
|
||||
}), jwt.WithIssuedAt(), jwt.WithLeeway(tokenLeeway))
|
||||
if err != nil {
|
||||
if errors.Is(err, jwt.ErrTokenNotValidYet) || errors.Is(err, jwt.ErrTokenUsedBeforeIssued) {
|
||||
return nil, "not-valid-yet", TokenNotValidYet
|
||||
} else if errors.Is(err, jwt.ErrTokenExpired) {
|
||||
return nil, "expired", TokenExpired
|
||||
}
|
||||
|
||||
return nil, reason, TokenAuthFailed
|
||||
}
|
||||
|
||||
|
|
@ -1311,8 +1319,9 @@ func (s *ProxyServer) parseToken(tokenValue string) (*signaling.TokenClaims, str
|
|||
return nil, "auth-failed", TokenAuthFailed
|
||||
}
|
||||
|
||||
minIssuedAt := time.Now().Add(-maxTokenAge)
|
||||
if issuedAt := claims.IssuedAt; issuedAt != nil && issuedAt.Before(minIssuedAt) {
|
||||
now := time.Now()
|
||||
minIssuedAt := now.Add(-(maxTokenAge + tokenLeeway))
|
||||
if issuedAt := claims.IssuedAt; issuedAt == nil || issuedAt.Before(minIssuedAt) {
|
||||
return nil, "expired", TokenExpired
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
signaling "github.com/strukturag/nextcloud-spreed-signaling"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ import (
|
|||
"sync/atomic"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
signaling "github.com/strukturag/nextcloud-spreed-signaling"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue