From 5025d06c00c40cf63da20d0f71b8a427e6c14a14 Mon Sep 17 00:00:00 2001 From: NeskireDK <10115530+NeskireDK@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:02:26 +0200 Subject: [PATCH] Allow SSO sessions to set a password without the current one Accounts provisioned by trusted-header SSO get a random password the user never saw, so /change_password was unusable for them. When the trusted header asserts the same email as the session user, waive the current password check and hide the field, so native clients (Yattee) can be given a password to log in with. Co-Authored-By: Claude Fable 5 --- src/invidious/routes/account.cr | 15 ++++++++++++--- src/invidious/views/user/change_password.ecr | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/invidious/routes/account.cr b/src/invidious/routes/account.cr index c8db207c2..31bc69ea6 100644 --- a/src/invidious/routes/account.cr +++ b/src/invidious/routes/account.cr @@ -23,6 +23,8 @@ module Invidious::Routes::Account sid = sid.as(String) csrf_token = generate_response(sid, {":change_password"}, HMAC_KEY) + sso_verified = Invidious::TrustedHeaderAuth.asserted_email(env) == user.email + templated "user/change_password" end @@ -48,8 +50,13 @@ module Invidious::Routes::Account return error_template(400, ex) end + # An SSO session proves the identity through the trusted header already, so + # the current password is waived. Accounts provisioned by SSO were given a + # random password the user never saw and could never type here. + sso_verified = Invidious::TrustedHeaderAuth.asserted_email(env) == user.email + password = env.params.body["password"]? - if password.nil? || password.empty? + if !sso_verified && (password.nil? || password.empty?) return error_template(401, "Password is a required field") end @@ -68,8 +75,10 @@ module Invidious::Routes::Account return error_template(400, "Password cannot be longer than 55 characters") end - if !Crypto::Bcrypt::Password.new(user.password.not_nil!).verify(password.byte_slice(0, 55)) - return error_template(401, "Incorrect password") + if !sso_verified + if !Crypto::Bcrypt::Password.new(user.password.not_nil!).verify(password.not_nil!.byte_slice(0, 55)) + return error_template(401, "Incorrect password") + end end new_password = Crypto::Bcrypt::Password.create(new_password, cost: 10) diff --git a/src/invidious/views/user/change_password.ecr b/src/invidious/views/user/change_password.ecr index e22891d69..0ac5336bb 100644 --- a/src/invidious/views/user/change_password.ecr +++ b/src/invidious/views/user/change_password.ecr @@ -10,8 +10,10 @@ <%= I18n.translate(locale, "Change password") %>
+ <% if !sso_verified %> "> + <% end %> ">