@@ -23,6 +23,8 @@ import (
23
23
"github.com/rs/zerolog/log"
24
24
)
25
25
26
+ const alternativeUserIDClaim = "user_id"
27
+
26
28
type VerifierConfig struct {
27
29
// HMACSecretKey is a secret key used to validate connection and subscription
28
30
// tokens generated using HMAC. Zero value means that HMAC tokens won't be allowed.
@@ -56,6 +58,11 @@ type VerifierConfig struct {
56
58
// IssuerRegex allows setting Issuer in form of Go language regex pattern. Regex groups
57
59
// may be then used in constructing JWKSPublicEndpoint.
58
60
IssuerRegex string
61
+
62
+ // UserIDClaim allows overriding default claim used to extract user ID from token. At this
63
+ // moment only "user_id" alternative claim is supported due to how tokens are parsed.
64
+ // By default, Centrifugo uses "sub".
65
+ UserIDClaim string
59
66
}
60
67
61
68
func (c VerifierConfig ) Validate () error {
@@ -94,6 +101,7 @@ func NewTokenVerifierJWT(config VerifierConfig, ruleContainer *rule.Container) (
94
101
issuerRe : issuerRe ,
95
102
audience : config .Audience ,
96
103
audienceRe : audienceRe ,
104
+ userIDClaim : config .UserIDClaim ,
97
105
}
98
106
99
107
algorithms , err := newAlgorithms (config .HMACSecretKey , config .RSAPublicKey , config .ECDSAPublicKey )
@@ -122,6 +130,7 @@ type VerifierJWT struct {
122
130
audienceRe * regexp.Regexp
123
131
issuer string
124
132
issuerRe * regexp.Regexp
133
+ userIDClaim string
125
134
}
126
135
127
136
var (
@@ -180,6 +189,8 @@ type ConnectTokenClaims struct {
180
189
Channels []string `json:"channels,omitempty"`
181
190
Subs map [string ]SubscribeOptions `json:"subs,omitempty"`
182
191
Meta json.RawMessage `json:"meta,omitempty"`
192
+ // UserID is only used instead of jwt.RegisteredClaims.Subject when explicitly configured.
193
+ UserID string `json:"user_id,omitempty"`
183
194
// Channel must never be set in connection tokens. We check this on verifying.
184
195
Channel string `json:"channel,omitempty"`
185
196
jwt.RegisteredClaims
@@ -191,6 +202,8 @@ type SubscribeTokenClaims struct {
191
202
Channel string `json:"channel,omitempty"`
192
203
Client string `json:"client,omitempty"`
193
204
ExpireAt * int64 `json:"expire_at,omitempty"`
205
+ // UserID is only used instead of jwt.RegisteredClaims.Subject when explicitly configured.
206
+ UserID string `json:"user_id,omitempty"`
194
207
}
195
208
196
209
type jwksManager struct { * jwks.Manager }
@@ -579,13 +592,16 @@ func (verifier *VerifierJWT) VerifyConnectToken(t string, skipVerify bool) (Conn
579
592
}
580
593
581
594
ct := ConnectToken {
582
- UserID : claims .RegisteredClaims .Subject ,
583
595
Info : info ,
584
596
Subs : subs ,
585
597
ExpireAt : expireAt ,
586
598
Meta : claims .Meta ,
587
599
}
588
-
600
+ if verifier .userIDClaim != "" {
601
+ ct .UserID = claims .UserID
602
+ } else {
603
+ ct .UserID = claims .RegisteredClaims .Subject
604
+ }
589
605
return ct , nil
590
606
}
591
607
@@ -736,6 +752,11 @@ func (verifier *VerifierJWT) VerifySubscribeToken(t string, skipVerify bool) (Su
736
752
Data : data ,
737
753
},
738
754
}
755
+ if verifier .userIDClaim != "" {
756
+ st .UserID = claims .UserID
757
+ } else {
758
+ st .UserID = claims .RegisteredClaims .Subject
759
+ }
739
760
return st , nil
740
761
}
741
762
@@ -766,11 +787,11 @@ func (verifier *VerifierJWT) Reload(config VerifierConfig) error {
766
787
return fmt .Errorf ("error compiling issuer regex: %w" , err )
767
788
}
768
789
}
769
-
770
790
verifier .algorithms = alg
771
791
verifier .audience = config .Audience
772
792
verifier .audienceRe = audienceRe
773
793
verifier .issuer = config .Issuer
774
794
verifier .issuerRe = issuerRe
795
+ verifier .userIDClaim = config .UserIDClaim
775
796
return nil
776
797
}
0 commit comments