mirror of
https://github.com/iv-org/invidious.git
synced 2026-01-28 07:48:31 -06:00
Add Invidious check ID for storyboards (used for video storyboards in the video timeline)
The storyboards API endpoint is unprotected and it allows anyone, including bots and abusers to spam that endpoint without having to enter the `/watch` endpoint (most of the time, is protected by some sort of bot protection by current instance owners to prevent abuse) I wonder if there is a better way to do this, but this works fine
This commit is contained in:
parent
66c67f4c7a
commit
c28be6720f
@ -434,7 +434,7 @@ if (!video_data.params.listen && video_data.params.quality === 'dash') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.vttThumbnails({
|
player.vttThumbnails({
|
||||||
src: '/api/v1/storyboards/' + video_data.id + '?height=90',
|
src: '/api/v1/storyboards/' + video_data.id + '?height=90' + `${video_data.invidious_companion_check_id ? `&check=${video_data.invidious_companion_check_id}` : ""}`,
|
||||||
showTimestamp: true
|
showTimestamp: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -89,6 +89,16 @@ db:
|
|||||||
##
|
##
|
||||||
#invidious_companion_key: "CHANGE_ME!!"
|
#invidious_companion_key: "CHANGE_ME!!"
|
||||||
|
|
||||||
|
##
|
||||||
|
## API key for Invidious companion, used for securing the communication
|
||||||
|
## between Invidious and Invidious companion.
|
||||||
|
## The key needs to be exactly 16 characters long.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#invidious_companion_verify_requests: true
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
#
|
#
|
||||||
# Server config
|
# Server config
|
||||||
|
|||||||
@ -173,6 +173,9 @@ class Config
|
|||||||
# Invidious companion API key
|
# Invidious companion API key
|
||||||
property invidious_companion_key : String = ""
|
property invidious_companion_key : String = ""
|
||||||
|
|
||||||
|
# Verify requests on endpoints that use Invidious companion
|
||||||
|
property invidious_companion_verify_requests : Bool = true
|
||||||
|
|
||||||
# Saved cookies in "name1=value1; name2=value2..." format
|
# Saved cookies in "name1=value1; name2=value2..." format
|
||||||
@[YAML::Field(converter: Preferences::StringToCookies)]
|
@[YAML::Field(converter: Preferences::StringToCookies)]
|
||||||
property cookies : HTTP::Cookies = HTTP::Cookies.new
|
property cookies : HTTP::Cookies = HTTP::Cookies.new
|
||||||
|
|||||||
@ -384,9 +384,13 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String)
|
|||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypt_ecb_without_salt(data, key)
|
def ecb_without_salt(data, key, encrypt : Bool)
|
||||||
cipher = OpenSSL::Cipher.new("aes-128-ecb")
|
cipher = OpenSSL::Cipher.new("aes-128-ecb")
|
||||||
cipher.encrypt
|
if encrypt
|
||||||
|
cipher.encrypt
|
||||||
|
else
|
||||||
|
cipher.decrypt
|
||||||
|
end
|
||||||
cipher.key = key
|
cipher.key = key
|
||||||
|
|
||||||
io = IO::Memory.new
|
io = IO::Memory.new
|
||||||
@ -394,11 +398,25 @@ def encrypt_ecb_without_salt(data, key)
|
|||||||
io.write(cipher.final)
|
io.write(cipher.final)
|
||||||
io.rewind
|
io.rewind
|
||||||
|
|
||||||
return io
|
if encrypt
|
||||||
|
return io
|
||||||
|
else
|
||||||
|
return io.gets_to_end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def invidious_companion_encrypt(data)
|
def invidious_companion_encrypt(data)
|
||||||
timestamp = Time.utc.to_unix
|
timestamp = Time.utc.to_unix
|
||||||
encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key)
|
encrypted_data = ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key, encrypt: true)
|
||||||
return Base64.urlsafe_encode(encrypted_data)
|
return Base64.urlsafe_encode(encrypted_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def invidious_companion_decrypt(check_id)
|
||||||
|
check_id_decoded = Base64.decode_string(check_id)
|
||||||
|
begin
|
||||||
|
decrypted_data = ecb_without_salt(check_id_decoded, CONFIG.invidious_companion_key, encrypt: false)
|
||||||
|
rescue
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return decrypted_data.as(String).split("|")
|
||||||
|
end
|
||||||
|
|||||||
@ -181,6 +181,18 @@ module Invidious::Routes::API::V1::Videos
|
|||||||
id = env.params.url["id"]
|
id = env.params.url["id"]
|
||||||
region = env.params.query["region"]?
|
region = env.params.query["region"]?
|
||||||
|
|
||||||
|
if CONFIG.invidious_companion.present? && CONFIG.invidious_companion_verify_requests
|
||||||
|
invidious_companion_check_id = env.params.query["check"]?
|
||||||
|
if check_id = invidious_companion_check_id
|
||||||
|
video_id = invidious_companion_decrypt(check_id).try &.[1]
|
||||||
|
if id != video_id
|
||||||
|
haltf env, 401, "ID incorrect."
|
||||||
|
end
|
||||||
|
else
|
||||||
|
haltf env, 401, "No check ID."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
video = get_video(id, region: region)
|
video = get_video(id, region: region)
|
||||||
rescue ex : NotFoundException
|
rescue ex : NotFoundException
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
<%
|
|
||||||
invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion
|
|
||||||
%>
|
|
||||||
<video style="outline:none;width:100%;background-color:#000" playsinline poster="<%= thumbnail %>"
|
<video style="outline:none;width:100%;background-color:#000" playsinline poster="<%= thumbnail %>"
|
||||||
id="player" class="on-video_player video-js player-style-<%= params.player_style %>"
|
id="player" class="on-video_player video-js player-style-<%= params.player_style %>"
|
||||||
preload="<% if params.preload %>auto<% else %>none<% end %>"
|
preload="<% if params.preload %>auto<% else %>none<% end %>"
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<%
|
||||||
|
invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion
|
||||||
|
%>
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="<%= preferences.locale %>">
|
<html lang="<%= preferences.locale %>">
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<% ucid = video.ucid %>
|
<% ucid = video.ucid %>
|
||||||
<% title = HTML.escape(video.title) %>
|
<% title = HTML.escape(video.title) %>
|
||||||
<% author = HTML.escape(video.author) %>
|
<% author = HTML.escape(video.author) %>
|
||||||
|
<% invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion %>
|
||||||
|
|
||||||
|
|
||||||
<% content_for "header" do %>
|
<% content_for "header" do %>
|
||||||
@ -66,7 +67,8 @@ we're going to need to do it here in order to allow for translations.
|
|||||||
"projection_type" => video.projection_type,
|
"projection_type" => video.projection_type,
|
||||||
"local_disabled" => CONFIG.disabled?("local"),
|
"local_disabled" => CONFIG.disabled?("local"),
|
||||||
"support_reddit" => true,
|
"support_reddit" => true,
|
||||||
"live_now" => video.live_now
|
"live_now" => video.live_now,
|
||||||
|
"invidious_companion_check_id" => invidious_companion_check_id,
|
||||||
}.to_pretty_json
|
}.to_pretty_json
|
||||||
%>
|
%>
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user