summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsyeopite <syeopite@syeopite.dev>2025-05-17 16:37:55 -0700
committersyeopite <syeopite@syeopite.dev>2025-05-17 16:37:55 -0700
commit2c857b5ab6af36ec625fad688db6673f5d150d20 (patch)
tree34b9eabda138a4287c94dfac4d58065fadb34136 /src
parent9d18c8699fc4e4abf7bdb002020017be71c6caa6 (diff)
parent00299ca4a06dfb7003bc16baa72cdac1d4624f31 (diff)
downloadinvidious-2c857b5ab6af36ec625fad688db6673f5d150d20.tar.gz
invidious-2c857b5ab6af36ec625fad688db6673f5d150d20.tar.bz2
invidious-2c857b5ab6af36ec625fad688db6673f5d150d20.zip
Remove text captchas from Invidious (#5308)
textcaptcha.com seems to be down since April and it does not appear that service will be restored. Text captchas can be easily automated using free LLMs, so keeping the text captcha is more like a gate to create accounts in mass on public Invidious instances. It also gives headaches like bots automating account creation to modify the videos that appear popular page of each instance (since the popular page is based on the subscriptions of the registered users).
Diffstat (limited to 'src')
-rw-r--r--src/invidious/routes/login.cr52
-rw-r--r--src/invidious/user/captcha.cr16
-rw-r--r--src/invidious/views/user/login.ecr39
3 files changed, 11 insertions, 96 deletions
diff --git a/src/invidious/routes/login.cr b/src/invidious/routes/login.cr
index d0f7ac22..e7de5018 100644
--- a/src/invidious/routes/login.cr
+++ b/src/invidious/routes/login.cr
@@ -21,9 +21,6 @@ module Invidious::Routes::Login
account_type = env.params.query["type"]?
account_type ||= "invidious"
- captcha_type = env.params.query["captcha"]?
- captcha_type ||= "image"
-
templated "user/login"
end
@@ -88,34 +85,14 @@ module Invidious::Routes::Login
password = password.byte_slice(0, 55)
if CONFIG.captcha_enabled
- captcha_type = env.params.body["captcha_type"]?
answer = env.params.body["answer"]?
- change_type = env.params.body["change_type"]?
-
- if !captcha_type || change_type
- if change_type
- captcha_type = change_type
- end
- captcha_type ||= "image"
-
- account_type = "invidious"
- if captcha_type == "image"
- captcha = Invidious::User::Captcha.generate_image(HMAC_KEY)
- else
- captcha = Invidious::User::Captcha.generate_text(HMAC_KEY)
- end
-
- return templated "user/login"
- end
+ account_type = "invidious"
+ captcha = Invidious::User::Captcha.generate_image(HMAC_KEY)
tokens = env.params.body.select { |k, _| k.match(/^token\[\d+\]$/) }.map { |_, v| v }
- answer ||= ""
- captcha_type ||= "image"
-
- case captcha_type
- when "image"
+ if answer
answer = answer.lstrip('0')
answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer)
@@ -124,27 +101,8 @@ module Invidious::Routes::Login
rescue ex
return error_template(400, ex)
end
- else # "text"
- answer = Digest::MD5.hexdigest(answer.downcase.strip)
-
- if tokens.empty?
- return error_template(500, "Erroneous CAPTCHA")
- end
-
- found_valid_captcha = false
- error_exception = Exception.new
- tokens.each do |tok|
- begin
- validate_request(tok, answer, env.request, HMAC_KEY, locale)
- found_valid_captcha = true
- rescue ex
- error_exception = ex
- end
- end
-
- if !found_valid_captcha
- return error_template(500, error_exception)
- end
+ else
+ return templated "user/login"
end
end
diff --git a/src/invidious/user/captcha.cr b/src/invidious/user/captcha.cr
index 8a0f67e5..b175c3b9 100644
--- a/src/invidious/user/captcha.cr
+++ b/src/invidious/user/captcha.cr
@@ -4,8 +4,6 @@ struct Invidious::User
module Captcha
extend self
- private TEXTCAPTCHA_URL = URI.parse("https://textcaptcha.com")
-
def generate_image(key)
second = Random::Secure.rand(12)
second_angle = second * 30
@@ -60,19 +58,5 @@ struct Invidious::User
tokens: {generate_response(answer, {":login"}, key, use_nonce: true)},
}
end
-
- def generate_text(key)
- response = make_client(TEXTCAPTCHA_URL, &.get("/github.com/iv.org/invidious.json").body)
- response = JSON.parse(response)
-
- tokens = response["a"].as_a.map do |answer|
- generate_response(answer.as_s, {":login"}, key, use_nonce: true)
- end
-
- return {
- question: response["q"].as_s,
- tokens: tokens,
- }
- end
end
end
diff --git a/src/invidious/views/user/login.ecr b/src/invidious/views/user/login.ecr
index 2b03d280..7ac96bc6 100644
--- a/src/invidious/views/user/login.ecr
+++ b/src/invidious/views/user/login.ecr
@@ -25,44 +25,17 @@
<% end %>
<% if captcha %>
- <% case captcha_type when %>
- <% when "image" %>
- <% captcha = captcha.not_nil! %>
- <img style="width:50%" src='<%= captcha[:question] %>'/>
- <% captcha[:tokens].each_with_index do |token, i| %>
- <input type="hidden" name="token[<%= i %>]" value="<%= HTML.escape(token) %>">
- <% end %>
- <input type="hidden" name="captcha_type" value="image">
- <label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
- <input type="text" name="answer" type="text" placeholder="h:mm:ss">
- <% else # "text" %>
- <% captcha = captcha.not_nil! %>
- <% captcha[:tokens].each_with_index do |token, i| %>
- <input type="hidden" name="token[<%= i %>]" value="<%= HTML.escape(token) %>">
- <% end %>
- <input type="hidden" name="captcha_type" value="text">
- <label for="answer"><%= captcha[:question] %></label>
- <input type="text" name="answer" type="text" placeholder="<%= translate(locale, "Answer") %>">
+ <% captcha = captcha.not_nil! %>
+ <img style="width:50%" src='<%= captcha[:question] %>'/>
+ <% captcha[:tokens].each_with_index do |token, i| %>
+ <input type="hidden" name="token[<%= i %>]" value="<%= HTML.escape(token) %>">
<% end %>
+ <label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
+ <input type="text" name="answer" type="text" placeholder="h:mm:ss">
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">
<%= translate(locale, "Register") %>
</button>
-
- <% case captcha_type when %>
- <% when "image" %>
- <label>
- <button type="submit" name="change_type" class="pure-button pure-button-primary" value="text">
- <%= translate(locale, "Text CAPTCHA") %>
- </button>
- </label>
- <% else # "text" %>
- <label>
- <button type="submit" name="change_type" class="pure-button pure-button-primary" value="image">
- <%= translate(locale, "Image CAPTCHA") %>
- </button>
- </label>
- <% end %>
<% else %>
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">
<%= translate(locale, "Sign In") %>/<%= translate(locale, "Register") %>