@@ -163,6 +163,15 @@ func TokenIdAuthed(clientManager *structs.ClientManager, token string) bool {
163163 return exists
164164}
165165
166+ // is this tokenid in the unauth map?
167+ func TokenIdUnauthed (clientManager * structs.ClientManager , token string ) bool {
168+ clientManager .Mu .RLock ()
169+ defer clientManager .Mu .RUnlock ()
170+ _ , exists := clientManager .UnauthClients [token ]
171+ zap .L ().Debug (fmt .Sprintf ("%s present in unauthmap: %v" , token , exists ))
172+ return exists
173+ }
174+
166175// this takes a bool for auth/unauth
167176// purge token/conn from opposite map
168177// persists to config
@@ -247,6 +256,49 @@ func CheckToken(token map[string]string, r *http.Request) (string, bool) {
247256 return token ["token" ], false
248257}
249258
259+ // CheckStreamToken validates a token for streamed HTTP transports such as SSE.
260+ // It returns the possibly refreshed token content, whether the token is known,
261+ // and whether the known token is authorized.
262+ func CheckStreamToken (token structs.WsTokenStruct , r * http.Request ) (string , bool , bool ) {
263+ if token .Token == "" {
264+ return "" , false , false
265+ }
266+ conf := config .Conf ()
267+ key := conf .KeyFile
268+ res , err := KeyfileDecrypt (token .Token , key )
269+ if err != nil {
270+ zap .L ().Warn (fmt .Sprintf ("Invalid stream token provided: %v" , err ))
271+ return token .Token , false , false
272+ }
273+ var ip string
274+ if forwarded := r .Header .Get ("X-Forwarded-For" ); forwarded != "" {
275+ ip = strings .Split (forwarded , "," )[0 ]
276+ } else {
277+ ip , _ , _ = net .SplitHostPort (r .RemoteAddr )
278+ }
279+ userAgent := r .Header .Get ("User-Agent" )
280+ if ip != res ["ip" ] || userAgent != res ["user_agent" ] || res ["id" ] != token .ID {
281+ zap .L ().Warn ("Stream token metadata doesn't match session" )
282+ return token .Token , false , false
283+ }
284+ if TokenIdAuthed (ClientManager , token .ID ) {
285+ if res ["authorized" ] == "true" {
286+ return token .Token , true , true
287+ }
288+ res ["authorized" ] = "true"
289+ encryptedText , err := KeyfileEncrypt (res , key )
290+ if err != nil {
291+ zap .L ().Error ("Error encrypting stream token" )
292+ return token .Token , false , false
293+ }
294+ return encryptedText , true , true
295+ }
296+ if TokenIdUnauthed (ClientManager , token .ID ) {
297+ return token .Token , true , false
298+ }
299+ return token .Token , false , false
300+ }
301+
250302// make a token authed
251303func AuthToken (token string ) (string , error ) {
252304 conf := config .Conf ()
0 commit comments