mirror of
https://github.com/discourse/discourse.git
synced 2025-03-22 23:35:38 +08:00
SECURITY: Add confirmation screen when logging in via user-api OTP
This commit is contained in:
parent
52387be4a4
commit
e6e47f2fb2
app
config
spec/requests
@ -365,12 +365,19 @@ class SessionController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def one_time_password
|
def one_time_password
|
||||||
otp_username = $redis.get "otp_#{params[:token]}"
|
@otp_username = otp_username = $redis.get "otp_#{params[:token]}"
|
||||||
|
|
||||||
if otp_username && user = User.find_by_username(otp_username)
|
if otp_username && user = User.find_by_username(otp_username)
|
||||||
|
if current_user&.username == otp_username
|
||||||
|
$redis.del "otp_#{params[:token]}"
|
||||||
|
return redirect_to path("/")
|
||||||
|
elsif request.post?
|
||||||
log_on_user(user)
|
log_on_user(user)
|
||||||
$redis.del "otp_#{params[:token]}"
|
$redis.del "otp_#{params[:token]}"
|
||||||
return redirect_to path("/")
|
return redirect_to path("/")
|
||||||
|
else
|
||||||
|
# Display the form
|
||||||
|
end
|
||||||
else
|
else
|
||||||
@error = I18n.t('user_api_key.invalid_token')
|
@error = I18n.t('user_api_key.invalid_token')
|
||||||
end
|
end
|
||||||
|
@ -2,4 +2,10 @@
|
|||||||
<div class='alert alert-error'>
|
<div class='alert alert-error'>
|
||||||
<%= @error %>
|
<%= @error %>
|
||||||
</div>
|
</div>
|
||||||
|
<%else%>
|
||||||
|
<%= form_tag do%>
|
||||||
|
<h2><%= t("user_api_key.otp_confirmation.confirm_title", site_name: SiteSetting.title) %></h2>
|
||||||
|
<p><%= t("user_api_key.otp_confirmation.logging_in_as", username: @otp_username) %></p>
|
||||||
|
<%= submit_tag(t("user_api_key.otp_confirmation.confirm_button"), class: "btn btn-primary") %>
|
||||||
|
<%end%>
|
||||||
<%end%>
|
<%end%>
|
||||||
|
@ -939,6 +939,10 @@ en:
|
|||||||
description: '"%{application_name}" is requesting the following access to your account:'
|
description: '"%{application_name}" is requesting the following access to your account:'
|
||||||
instructions: 'We just generated a new user API key for you to use with "%{application_name}", please paste the following key into your application:'
|
instructions: 'We just generated a new user API key for you to use with "%{application_name}", please paste the following key into your application:'
|
||||||
otp_description: 'Would you like to allow "%{application_name}" to access this site?'
|
otp_description: 'Would you like to allow "%{application_name}" to access this site?'
|
||||||
|
otp_confirmation:
|
||||||
|
confirm_title: Continue to %{site_name}
|
||||||
|
logging_in_as: Logging in as %{username}
|
||||||
|
confirm_button: Finish Login
|
||||||
no_trust_level: "Sorry, you do not have the required trust level to access the user API"
|
no_trust_level: "Sorry, you do not have the required trust level to access the user API"
|
||||||
generic_error: "Sorry, we are unable to issue user API keys, this feature may be disabled by the site admin"
|
generic_error: "Sorry, we are unable to issue user API keys, this feature may be disabled by the site admin"
|
||||||
scopes:
|
scopes:
|
||||||
|
@ -340,6 +340,7 @@ Discourse::Application.routes.draw do
|
|||||||
get "session/email-login/:token" => "session#email_login_info"
|
get "session/email-login/:token" => "session#email_login_info"
|
||||||
post "session/email-login/:token" => "session#email_login"
|
post "session/email-login/:token" => "session#email_login"
|
||||||
get "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ }
|
get "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ }
|
||||||
|
post "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ }
|
||||||
get "composer_messages" => "composer_messages#index"
|
get "composer_messages" => "composer_messages#index"
|
||||||
post "composer/parse_html" => "composer#parse_html"
|
post "composer/parse_html" => "composer#parse_html"
|
||||||
|
|
||||||
|
@ -1369,9 +1369,40 @@ RSpec.describe SessionController do
|
|||||||
get "/session/otp/asd1231dasd123"
|
get "/session/otp/asd1231dasd123"
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
expect(response.status).to eq(404)
|
||||||
|
|
||||||
|
post "/session/otp/asd1231dasd123"
|
||||||
|
|
||||||
|
expect(response.status).to eq(404)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when token is valid' do
|
context 'when token is valid' do
|
||||||
|
it "should display the form for GET" do
|
||||||
|
token = SecureRandom.hex
|
||||||
|
$redis.setex "otp_#{token}", 10.minutes, user.username
|
||||||
|
|
||||||
|
get "/session/otp/#{token}"
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.body).to include(
|
||||||
|
I18n.t("user_api_key.otp_confirmation.logging_in_as", username: user.username)
|
||||||
|
)
|
||||||
|
expect($redis.get("otp_#{token}")).to eq(user.username)
|
||||||
|
|
||||||
|
expect(session[:current_user_id]).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should redirect on GET if already logged in" do
|
||||||
|
sign_in(user)
|
||||||
|
token = SecureRandom.hex
|
||||||
|
$redis.setex "otp_#{token}", 10.minutes, user.username
|
||||||
|
|
||||||
|
get "/session/otp/#{token}"
|
||||||
|
expect(response.status).to eq(302)
|
||||||
|
|
||||||
|
expect($redis.get("otp_#{token}")).to eq(nil)
|
||||||
|
expect(session[:current_user_id]).to eq(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
it 'should authenticate user and delete token' do
|
it 'should authenticate user and delete token' do
|
||||||
user = Fabricate(:user)
|
user = Fabricate(:user)
|
||||||
|
|
||||||
@ -1381,7 +1412,7 @@ RSpec.describe SessionController do
|
|||||||
token = SecureRandom.hex
|
token = SecureRandom.hex
|
||||||
$redis.setex "otp_#{token}", 10.minutes, user.username
|
$redis.setex "otp_#{token}", 10.minutes, user.username
|
||||||
|
|
||||||
get "/session/otp/#{token}"
|
post "/session/otp/#{token}"
|
||||||
|
|
||||||
expect(response.status).to eq(302)
|
expect(response.status).to eq(302)
|
||||||
expect(response).to redirect_to("/")
|
expect(response).to redirect_to("/")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user