Project

General

Profile

Feature #5274

Easier HTTP streaming auth/access

Added by Luis Alves 5 months ago. Updated 4 months ago.

Status:
Fixed
Priority:
Normal
Assignee:
-
Category:
-
Target version:
Start date:
2017-05-03
Due date:
% Done:

100%

Estimated time:
(Total: 0.00 h)

Description

I used to have my tvh server only available on my local network but recently I have the need (and bandwidth) to watch tv when I'm not at home so I had to "enable" authentication.
Then I bumped into a bunch of issue/limitation because the way http authentication works.

Tvheadend generates a playlist by pointing at: http://<user>:<pass>@<ip>:<port>/playlist
The generated playlist will only work for a certain period of time (while the ticket is valid).
The problem is that almost all players will only read the playlist once meaning that after a while, the ticket is invalid and the playlist useless.
This happens on basically all smart tv iptv players (ott player, ss iptv, ...) and all android apps that take a playlist as input.
So, speaking for myself, the "ticket" method is completely useless...

Here are my suggestions to solve this:

1) When the playlist is requested with plain authentication, it should include the authentication on each item within the playlist (and discard the ticket arg).
Example:
http://<user>:<pass>@<ip>:<port>/playlist
Should return for each item:
#EXTINF <...>
http://<user>:<pass>
@<ip>:<port>/stream/channelid/<id>?<...>

(this one is more of a fix than an enhancement)

2) Authenticate by using extra arguments (discard ticket, include user/pass arguments on playlist):
Example:
http://<ip>:<port>/playlist?username=<user>&password=<pass>
Returns:
#EXTINF <...>
http://<ip>:<port>/stream/channelid/<id>?username=<user>&password=<pass>&<...>

3) Authenticate by url path (similar to what xtream-codes does):
Example (when the request explicitly includes user/pass return a link which includes auth):
http://<ip>:<port>/playlist?username=<user>&password=<pass>
Returns:
#EXTINF <...>
http://<ip>:<port>/stream2/<user>/<pass>/channelid/<id>?<...>

For whoever wants to try, I have done some quick hacks to the code to implemented both 2) and 3) (but can only generate playlist for method 3):
https://github.com/ljalves/tvheadend/commit/f03fc5f5d82c75a8ce677a88226f2369bc3fec87

On this branch, if you request the playlist with "username" and "password", like in "3)" you will get a playlist with /stream2/<user>/<pass>/channelid/...

To test 2) you can play a stream with:
http://<ip>:<port>/stream/channelid/<id>?username=<user>&password=<pass>&<...>


Subtasks

Feature #4352: Ticket expirationFixedJohn Törnblom

Associated revisions

Revision ee714fc1 (diff)
Added by Jaroslav Kysela 5 months ago

add pernament tickets for the authentization, fixes #5274

Revision a260ce5f (diff)
Added by Jaroslav Kysela 5 months ago

fixes for the pernament tickets, issue #5274

Revision 3e130bab (diff)
Added by Jaroslav Kysela 5 months ago

access: do not use + character for the auth code (HTTP deescaping), issue #5274

Revision 938f6522 (diff)
Added by Jaroslav Kysela 5 months ago

webui: fix http_m3u_playlist_add(), fixes #5274

History

#1 Updated by Jaroslav Kysela 5 months ago

It's a big security hole. I don't want to give back the password at all through any playlists. The good players should support the standard HTTP authentication (ideally the digest one which does not transmit the password directly).

Use IP based authentication for dumb players.

#2 Updated by saen acro 5 months ago

Better to use
user+ip+client_id=hash
as identification

#3 Updated by Luis Alves 5 months ago

Jaroslav Kysela wrote:

It's a big security hole. I don't want to give back the password at all through any playlists. The good players should support the standard HTTP authentication (ideally the digest one which does not transmit the password directly).

Use IP based authentication for dumb players.

IP based is not an option since the client IP is not static.
I don't see it as a security hole as long as the users that were meant to be used with that method would ONLY have access to streaming (no webui/admin access) - not a huge risk...
(also to receive back the password, you need to send it first)
And there would be an option to enable/disable this functionality...

So, in summary, it's not possible to setup a http streaming player which takes as input a playlist, right? (example: android "perfect iptv player", and all above smart tv iptv apps)

#4 Updated by saen acro 5 months ago

@Luis Alves
cross fingers ;)
https://tvheadend.org/issues/3699

#5 Updated by Jaroslav Kysela 5 months ago

Luis Alves wrote:

So, in summary, it's not possible to setup a http streaming player which takes as input a playlist, right? (example: android "perfect iptv player", and all above smart tv iptv apps)

In summary, the client is crappy. VLC can do user/pass authentication, any browser can do user/pass authentication, wget can do user/pass authentication..

We can talk probably about some persistent ticket hashes for those clients (valid only for HTTP streaming) but not to send any credentals in URLs.

#6 Updated by Pablo R. 5 months ago

Jaroslav Kysela wrote:

We can talk probably about some persistent ticket hashes for those clients (valid only for HTTP streaming) but not to send any credentals in URLs.

It looks good, but it is good to have some kind of management from the webui, enable and disable those clients, comments for the user, connection limits, etc.

Maybe another section near the user tab?

#7 Updated by Jaroslav Kysela 5 months ago

Pablo R. wrote:

Jaroslav Kysela wrote:

We can talk probably about some persistent ticket hashes for those clients (valid only for HTTP streaming) but not to send any credentals in URLs.

It looks good, but it is good to have some kind of management from the webui, enable and disable those clients, comments for the user, connection limits, etc.

Nope. I would just add it to the ACL entries. So, enable/disable/reset and that's all. The code will be generated automatically. The rest is about URL to get such playlists like /playlist/channels?persistent=1 or /playlist/persistent/channels (probably more readable).

#8 Updated by Luis Alves 5 months ago

Jaroslav Kysela wrote:

In summary, the client is crappy. VLC can do user/pass authentication, any browser can do user/pass authentication, wget can do user/pass authentication..

It's true that there are some "crappy" clients out there :) but it's not even the case of not supporting the authentication methods.
They do support but will only use it to save the channels from the playlist they get - once the ticket expires the client doesn't know how to play the channels again.
I use tvheadend clients as I use a TV - while zapping it's annoying to keep entering credentials once the ticket expires... (not even practical if using a tv remote).

#9 Updated by Luis Alves 5 months ago

Jaroslav Kysela wrote:

Nope. I would just add it to the ACL entries. So, enable/disable/reset and that's all. The code will be generated automatically. The rest is about URL to get such playlists like /playlist/channels?persistent=1 or /playlist/persistent/channels (probably more readable).

This seems to be a good solution.
I assume the enable/disable/reset is per user (on the user config tab).
(one might want to disable or reset the tickets just for a specific user)

#10 Updated by Jaroslav Kysela 5 months ago

Luis Alves wrote:

Jaroslav Kysela wrote:

In summary, the client is crappy. VLC can do user/pass authentication, any browser can do user/pass authentication, wget can do user/pass authentication..

It's true that there are some "crappy" clients out there :) but it's not even the case of not supporting the authentication methods.
They do support but will only use it to save the channels from the playlist they get - once the ticket expires the client doesn't know how to play the channels again.
I use tvheadend clients as I use a TV - while zapping it's annoying to keep entering credentials once the ticket expires... (not even practical if using a tv remote).

Yep, but clients can store credentals to an own database pernamently like browsers/vlc do. So basically, the problem is not on the tvheadend's side, but we have to deal with this situation.

#11 Updated by saen acro 5 months ago

What if security is based on this scenario
currently
http://tvh.ip:9981/stream/channelid/1165510174

new optional way
http://tvh.ip:9981/$ip_hash/$user_hash/stream/channelid/1122334455
Salt for hash is good option, placed in user profile

and if user have enabled option, requested playlist by regular way will receive new stile playlist.
sound good realisation unknown ;)

#12 Updated by Jaroslav Kysela 5 months ago

Added to v4.3-1481-gee714fc11 . The auth code is in the password table . The playlist can be obtained through /playlist/auth/ path.

#13 Updated by kodiaq kodiaq 5 months ago

I've enabled persistent authentication for user and it automatically generated authentication code PMYEtflgGdJxsWJHQhvS+4y6AddA

I requested playlist in format http://tvh.ip:9981/playlist/PMYEtflgGdJxsWJHQhvS+4y6AddA but I am getting 400 Bad Request (HTTP/1.1 GET (1) /playlist/PMYEtflgGdJxsWJHQhvS+4y6AddA -- 400).

How do I request playlist properly via this new way?

#14 Updated by Jaroslav Kysela 5 months ago

playlist through HTTP authentication:    http://ip:9981/playlist/auth      # tvh will fetch the authcode from the passwd table
playlist through authcode:               http://ip:9981/playlist/auth?auth={authcode}
streaming:                               http://ip:9981/play/stream/channelname/CHANNELNAME?auth={authcode}

I fixed some bugs and added playlist URLs to the buildin help in v4.3-1484-g7f841a351 .

#15 Updated by saen acro 5 months ago

Jaroslav Kysela wrote:

Added to v4.3-1481-gee714fc11 . The auth code is in the password table . The playlist can be obtained through /playlist/auth/ path.

is there something wrong in url?

curl http://11:[email protected]:9981/playlist/auth/channels
#EXTM3U

in passwords tab I see The code which may be used for the HTTP streaming.

p.s.
Why unselectable="on" in UI?

#16 Updated by saen acro 5 months ago

Tested with v4.3-1484 playlist is ok (/)

#17 Updated by saen acro 5 months ago

(!) No information who use stream in Status > Subscription

suggestion:
(IP) - ip enabled
(HA) - http authentificated
(AC) - auth code

#18 Updated by kodiaq kodiaq 5 months ago

In v4.3-1484 when I enter playlist to VLC in format http://ip:9981/playlist/auth?auth={authcode} it still asks me for username and password.

Is this correct behaviour?

Shouldn't be playlist generated without these credentials purely based on authcode?

#19 Updated by Luis Alves 5 months ago

Hi Jaroslav,
I have tried and the playlist I get still doesn't contain the auth code on each entry.
I believe this is what kodiaq above is seeying also.

#20 Updated by Luis Alves 5 months ago

Hmmm... I believe this is only an issue with priorities.
I have observed that:
- When I use the new auth method on an IP that doesn't fall into the "no auth user" it works.
- When I use it on a machine with an IP that falls in the "no auth user" it always gets a playlist without the auth string unless it is forced as an argument.

This will return a playlist without "auth" argument if your IP falls in the "no auth user = *".
http://ip:9981/playlist/auth
http://user:pass@ip:9981/playlist/auth
(the second one should not)

This will return a playlist with "auth" argument:
http://ip:9981/playlist/auth?auth=<auth>

I believe it is fine as it is...
Thanks a lot Jaroslav!

#21 Updated by kodiaq kodiaq 5 months ago

@Luis Alves - Did you try new auth method in VLC (With IP that doesn't falls in the "no auth user = *")?

On my side, I need to enter username and password credentials everytime I change the channel even though persistent authentication for that user is enabled.

Therefore I still miss the point of this new feature as VLC behaves as previously with temporary ticket.

In my understanding the expected behavior should be, that if I enter to VLC link like this: http://ip:9981/stream/channelid/1?auth=PMYEtflgGdJxsWJHQhvS+4y6AddA&profile=pass than tvheadend should recognize that this request is from specific existing user that have persistent authentication enabled and should not require username and password credentials anymore.

Isn't the authcode introduction meant also as sort of username:password replacement?

#22 Updated by saen acro 5 months ago

I paste in vlc from no ip permited network

http://user:[email protected]:9981/playlist/auth/channels

no need to add any more credentials.

Maby more correct is to use old url style

http://user:[email protected]:9981/playlist/channels

and if in user profile enabled auth to be added automatically

Option is very I mean Extremely useful with dynamic ip and tvh automatic network iptv input

p.s.
Anyone with permission to add wiki information how to use export url options

#23 Updated by Jaroslav Kysela 5 months ago

Luis Alves wrote:

Hmmm... I believe this is only an issue with priorities.
I have observed that:
- When I use the new auth method on an IP that doesn't fall into the "no auth user" it works.
- When I use it on a machine with an IP that falls in the "no auth user" it always gets a playlist without the auth string unless it is forced as an argument.

This will return a playlist without "auth" argument if your IP falls in the "no auth user = *".
http://ip:9981/playlist/auth
http://user:pass@ip:9981/playlist/auth
(the second one should not)

If user has enabled the authcode, then the playlist for the second (user:pass) URL should be with ?auth={authcode} parameters, but you must force the HTTP authentication in client (perhaps, it used the anonymous access without HTTP authentication).

#24 Updated by Jaroslav Kysela 5 months ago

Jaroslav Kysela wrote:

If user has enabled the authcode, then the playlist for the second (user:pass) URL should be with ?auth={authcode} parameters, but you must force the HTTP authentication in client (perhaps, it used the anonymous access without HTTP authentication).

Thinking more about this - I think that tvh should return 401 HTTP error code in this case to force the authentication.

#25 Updated by Jaroslav Kysela 5 months ago

Retest with v4.3-1485-gb7e8102ce . The user:[email protected]/playlist/auth should work now even for the anonymous (allowed) IPs.

#26 Updated by kodiaq kodiaq 5 months ago

v4.3-1485-gb7e8102ce - New auth method works great with VLC using: http://user:[email protected]:9981/playlist/auth/channels . Great milestone Jaroslav!

Would it be now also possible to create new user account for users with dynamic IP address, which will be authenticated only via authcode?

Dumb players do not prompt for username and password and IP based authentication is not practical with dynamic IP. I think many tvh users would welcome this feature.

#27 Updated by Luis Alves 5 months ago

It's perfect now.

Thanks a lot for the quick implementation!

#28 Updated by Jaroslav Kysela 5 months ago

kodiaq kodiaq wrote:

Dumb players do not prompt for username and password and IP based authentication is not practical with dynamic IP. I think many tvh users would welcome this feature.

Just use /playlist/auth?auth={authcode} for those players...

#29 Updated by Jaroslav Kysela 5 months ago

  • Target version set to 4.4

#30 Updated by kodiaq kodiaq 5 months ago

Jaroslav Kysela wrote:

kodiaq kodiaq wrote:

Dumb players do not prompt for username and password and IP based authentication is not practical with dynamic IP. I think many tvh users would welcome this feature.

Just use /playlist/auth?auth={authcode} for those players...

If I use /playlist/auth?auth={authcode} I always get 401 Unauthorized error. I've tried to reset authcode couple of times, but no change. I've set my server for both plain and digest authentication.

#31 Updated by kodiaq kodiaq 5 months ago

Was looking closely to /playlist/auth?auth={authcode} method and noticed that it does not work for user accounts created in the past.

If I create new account and enable authcode it works straight away for that particular account.

I am running xenial version.

#32 Updated by Luis Alves 5 months ago

I noticed that profiles stopped working when requesting without auth:

Like this: (no auth)
http://ip:9981/playlist?profile=<profile>

No matter which profile I specify on the argument, it always uses the default one.

Can someone confirm?

#33 Updated by kodiaq kodiaq 5 months ago

kodiaq kodiaq wrote:

Was looking closely to /playlist/auth?auth={authcode} method and noticed that it does not work for user accounts created in the past.

If I create new account and enable authcode it works straight away for that particular account.

I am running xenial version.

@Jaroslav - Ignore my previous observation, it has nothing to do with the old or new account. It is related to the authcode itself. If the authcode consists of special characters (for example + ) than using auth method returns 401 Unauthorized error.

@Luis Alves - http://ip:9981/playlist?profile=&lt;profile> seems to work fine for me. I've used pass and matroska profiles and it generated corresponding playlists.

#34 Updated by Jaroslav Kysela 5 months ago

  • Status changed from New to Fixed

Ok, thanks. I changed plus to dot ('+' -> '.'). v4.3-1490-g3e130baba . Closing as fixed.

#35 Updated by Luis Alves 5 months ago

kodiaq kodiaq wrote:

@Luis Alves - http://ip:9981/playlist?profile=&lt;profile> seems to work fine for me. I've used pass and matroska profiles and it generated corresponding playlists.

It does generate the correct playlists but when playing them, it will ignore the profile selection (always uses the default profile).
Remember this is for "no auth" (global account)

#36 Updated by Luis Alves 5 months ago

Found the issue:
When "playlist" is the only argument, it is added with the '&' char instead of '?'

Possible fix:
https://github.com/tvheadend/tvheadend/pull/1190

#37 Updated by Jaroslav Kysela 5 months ago

The github seems really inconsistent those hours: https://status.github.com/messages .

#38 Updated by Jaroslav Kysela 5 months ago

Luis Alves wrote:

kodiaq kodiaq wrote:

@Luis Alves - http://ip:9981/playlist?profile=&lt;profile> seems to work fine for me. I've used pass and matroska profiles and it generated corresponding playlists.

It does generate the correct playlists but when playing them, it will ignore the profile selection (always uses the default profile).
Remember this is for "no auth" (global account)

The profile should be restricted to username lines in ACL. Do you have allowed that profile for the given user?

#39 Updated by Luis Alves 5 months ago

Hi,
It's really a syntax error: if no auth or ticket are sent to the string, the profile argument can't start with '&' but with '?'.

I think github is back to normal and PR is visible now.
If not you'll be able to see what I mean here: [https://github.com/ljalves/tvheadend/commit/ad00441a72b4ba47e54ab7b037383159627e9e2c]

#40 Updated by Jaroslav Kysela 5 months ago

Fixed in v4.3-1494-g26dc2643e .

#41 Updated by An Lu 5 months ago

This is working perfect for me, great job!!
But I have a little problem. I use Tvheadend with an reverse proxy to watch tv on the road. If I generate the playlist it contains http:// in the url so I have to manually edit it to https://domain.domain/tvheadend... is there a way to force TVH to create the playlist with https links?

#43 Updated by An Lu 5 months ago

Jaroslav Kysela wrote:

Set X-Forwarded-Proto : https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/

Works! Perfect thanks :)

#44 Updated by Fausto Kbsa 4 months ago

Hello

I use TVH for about 1 year and am very happy, especially with this Feature #5274 (authcode).

I upgraded TVH to version 4.3-1532~g409a70630 and the authentication code worked very well, but I see that TVH started responding for anonymous accesses (URL without http://user:pass@ or ?auth={authcode}).

Another point is that user Streaming profiles (Basic, Advanced and/or HTSP) may be not working.
I tried and a user with only the HTSP profile can request and receive IPTV Streaming (TCP 9981).

#45 Updated by kodiaq kodiaq 4 months ago

@Fausto Kbsa - I am not able to re-create your issue. If I disable HTSP profile for certain user, of course I can still request playlist on TCP 9981, but I only get "HTTP/1.1 401 Unauthorized" error so this is acceptable behaviour. With anonymous access same reply "HTTP/1.1 401 Unauthorized". . .

#46 Updated by Fausto Kbsa 4 months ago

kodiaq kodiaq wrote:

@Fausto Kbsa - I am not able to re-create your issue. If I disable HTSP profile for certain user, of course I can still request playlist on TCP 9981, but I only get "HTTP/1.1 401 Unauthorized" error so this is acceptable behaviour. With anonymous access same reply "HTTP/1.1 401 Unauthorized". . .

Can I open a another issue?

#47 Updated by Jaroslav Kysela 4 months ago

Fausto Kbsa wrote:

kodiaq kodiaq wrote:

@Fausto Kbsa - I am not able to re-create your issue. If I disable HTSP profile for certain user, of course I can still request playlist on TCP 9981, but I only get "HTTP/1.1 401 Unauthorized" error so this is acceptable behaviour. With anonymous access same reply "HTTP/1.1 401 Unauthorized". . .

Can I open a another issue?

Yes, but look to '--trace http' logs before, to check if the anonymous access in your ACLs is not activated. https://tvheadend.org/projects/tvheadend/wiki/Traces

Also available in: Atom PDF