Add support for Google login verification

This commit is contained in:
Omar Roth 2019-07-22 13:28:36 -05:00
parent d034fecc89
commit 6215259565
No known key found for this signature in database
GPG Key ID: B8254FB7EC3D37F2
2 changed files with 94 additions and 64 deletions

View File

@ -892,6 +892,7 @@ get "/login" do |env|
tfa = env.params.query["tfa"]? tfa = env.params.query["tfa"]?
tfa ||= false tfa ||= false
prompt = ""
templated "login" templated "login"
end end
@ -989,15 +990,22 @@ post "/login" do |env|
next templated "error" next templated "error"
end end
if challenge_results[0][-1]?.try &.[0].as_a?.try &.[0][2]?.try &.== "TWO_STEP_VERIFICATION" prompt_type = challenge_results[0][-1]?.try &.[0].as_a?.try &.[0][2]?
traceback << "User has 2FA.<br/>" if {"TWO_STEP_VERIFICATION", "LOGIN_CHALLENGE"}.includes? prompt_type
traceback << "Handling prompt #{prompt_type}.<br/>"
case prompt_type
when "TWO_STEP_VERIFICATION"
prompt_type = 2
when "LOGIN_CHALLENGE"
prompt_type = 4
end
# Prefer Authenticator app and SMS over unsupported protocols # Prefer Authenticator app and SMS over unsupported protocols
if challenge_results[0][-1][0][0][8] != 6 && challenge_results[0][-1][0][0][8] != 9 if !{6, 9, 12, 15}.includes?(challenge_results[0][-1][0][0][8]) && prompt_type == 4
tfa = challenge_results[0][-1][0].as_a.select { |auth_type| auth_type[8] == 6 || auth_type[8] == 9 }[0] tfa = challenge_results[0][-1][0].as_a.select { |auth_type| {6, 9, 12, 15}.includes? auth_type[8] }[0]
traceback << "Selecting challenge #{tfa[8]}..." traceback << "Selecting challenge #{tfa[8]}..."
select_challenge = {2, nil, nil, nil, {tfa[8]}}.to_json select_challenge = {prompt_type, nil, nil, nil, {tfa[8]}}.to_json
tl = challenge_results[1][2] tl = challenge_results[1][2]
@ -1011,7 +1019,6 @@ post "/login" do |env|
tfa = challenge_results[0][-1][0][0] tfa = challenge_results[0][-1][0][0]
end end
if tfa[2] == "TWO_STEP_VERIFICATION"
if tfa[5] == "QUOTA_EXCEEDED" if tfa[5] == "QUOTA_EXCEEDED"
error_message = translate(locale, "Quota exceeded, try again in a few hours") error_message = translate(locale, "Quota exceeded, try again in a few hours")
env.response.status_code = 423 env.response.status_code = 423
@ -1021,6 +1028,18 @@ post "/login" do |env|
if !tfa_code if !tfa_code
account_type = "google" account_type = "google"
captcha_type = "image" captcha_type = "image"
case tfa[8]
when 6, 9
prompt = "Google verification code"
when 12
prompt = "Login verification, recovery email: #{tfa[-1][tfa[-1].as_h.keys[0]][0]}"
when 15
prompt = "Login verification, security question: #{tfa[-1][tfa[-1].as_h.keys[0]][0]}"
else
prompt = "Google verification code"
end
tfa = true tfa = true
captcha = nil captcha = nil
next templated "login" next templated "login"
@ -1030,22 +1049,34 @@ post "/login" do |env|
request_type = tfa[8] request_type = tfa[8]
case request_type case request_type
when 6 when 6 # Authenticator app
# Authenticator app
tfa_req = { tfa_req = {
user_hash, nil, 2, nil, user_hash, nil, 2, nil,
{6, nil, nil, nil, nil, {6, nil, nil, nil, nil,
{tfa_code, false}, {tfa_code, false},
}, },
}.to_json }.to_json
when 9 when 9 # Voice or text message
# Voice or text message
tfa_req = { tfa_req = {
user_hash, nil, 2, nil, user_hash, nil, 2, nil,
{9, nil, nil, nil, nil, nil, nil, nil, {9, nil, nil, nil, nil, nil, nil, nil,
{nil, tfa_code, false, 2}, {nil, tfa_code, false, 2},
}, },
}.to_json }.to_json
when 12 # Recovery email
tfa_req = {
user_hash, nil, 4, nil,
{12, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{tfa_code},
},
}.to_json
when 15 # Security question
tfa_req = {
user_hash, nil, 5, nil,
{15, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{tfa_code},
},
}.to_json
else else
error_message = translate(locale, "Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.") error_message = translate(locale, "Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.")
env.response.status_code = 500 env.response.status_code = 500
@ -1067,7 +1098,6 @@ post "/login" do |env|
traceback << "done.<br/>" traceback << "done.<br/>"
end end
end
traceback << "Logging in..." traceback << "Logging in..."
@ -1080,8 +1110,7 @@ post "/login" do |env|
end end
# TODO: Occasionally there will be a second page after login confirming # TODO: Occasionally there will be a second page after login confirming
# the user's phone number, which we will likely choke on. # the user's phone number ("/b/0/SmsAuthInterstitial"), which we currently choke on.
# if location.includes? "SmsAuthInterstitial"
login = client.get(location, headers) login = client.get(location, headers)
headers = login.cookies.add_request_headers(headers) headers = login.cookies.add_request_headers(headers)
@ -1225,6 +1254,7 @@ post "/login" do |env|
account_type = "invidious" account_type = "invidious"
tfa = false tfa = false
prompt = ""
if captcha_type == "image" if captcha_type == "image"
captcha = generate_captcha(HMAC_KEY, PG_DB) captcha = generate_captcha(HMAC_KEY, PG_DB)

View File

@ -102,8 +102,8 @@
<% end %> <% end %>
<% if tfa %> <% if tfa %>
<label for="tfa"><%= translate(locale, "Google verification code") %> :</label> <label for="tfa"><%= translate(locale, prompt) %> :</label>
<input required class="pure-input-1" name="tfa" type="text" placeholder="<%= translate(locale, "Google verification code") %>"> <input required class="pure-input-1" name="tfa" type="text" placeholder="<%= translate(locale, prompt) %>">
<% end %> <% end %>
<button type="submit" class="pure-button pure-button-primary"><%= translate(locale, "Sign In") %></button> <button type="submit" class="pure-button pure-button-primary"><%= translate(locale, "Sign In") %></button>