mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 18:30:26 -06:00
DEV: Update associate_accounts_controller to use secure_session
This is much cleaner than using redis directly. It also opens the door to more complex association change flows which may happen during login.
This commit is contained in:
parent
97f701bc4c
commit
2cae29f644
@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Users::AssociateAccountsController < ApplicationController
|
||||
REDIS_PREFIX ||= "omniauth_reconnect"
|
||||
SECURE_SESSION_PREFIX ||= "omniauth_reconnect"
|
||||
|
||||
def connect_info
|
||||
auth = get_auth_hash
|
||||
@ -17,7 +17,7 @@ class Users::AssociateAccountsController < ApplicationController
|
||||
|
||||
def connect
|
||||
auth = get_auth_hash
|
||||
Discourse.redis.del "#{REDIS_PREFIX}_#{current_user&.id}_#{params[:token]}"
|
||||
secure_session[self.class.key(params[:token])] = nil
|
||||
|
||||
provider_name = auth.provider
|
||||
authenticator = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
|
||||
@ -34,9 +34,13 @@ class Users::AssociateAccountsController < ApplicationController
|
||||
|
||||
def get_auth_hash
|
||||
token = params[:token]
|
||||
json = Discourse.redis.get "#{REDIS_PREFIX}_#{current_user&.id}_#{token}"
|
||||
json = secure_session[self.class.key(token)]
|
||||
raise Discourse::NotFound if json.nil?
|
||||
|
||||
OmniAuth::AuthHash.new(JSON.parse(json))
|
||||
end
|
||||
|
||||
def self.key(token)
|
||||
"#{SECURE_SESSION_PREFIX}_#{token}"
|
||||
end
|
||||
end
|
||||
|
@ -30,7 +30,7 @@ class Users::OmniauthCallbacksController < ApplicationController
|
||||
if session.delete(:auth_reconnect) && authenticator.can_connect_existing_user? && current_user
|
||||
# Save to redis, with a secret token, then redirect to confirmation screen
|
||||
token = SecureRandom.hex
|
||||
Discourse.redis.setex "#{Users::AssociateAccountsController::REDIS_PREFIX}_#{current_user.id}_#{token}", 10.minutes, auth.to_json
|
||||
secure_session.set "#{Users::AssociateAccountsController.key(token)}", auth.to_json, expires: 10.minutes
|
||||
return redirect_to "#{Discourse.base_path}/associate/#{token}"
|
||||
else
|
||||
DiscourseEvent.trigger(:before_auth, authenticator, auth, session, cookies, request)
|
||||
|
@ -56,17 +56,6 @@ RSpec.describe Users::AssociateAccountsController do
|
||||
expect(data["provider_name"]).to eq("google_oauth2")
|
||||
expect(data["account_description"]).to eq("someemail@test.com")
|
||||
|
||||
# Request as different user, should not work
|
||||
sign_in(user2)
|
||||
get "#{uri.path}.json"
|
||||
expect(response.status).to eq(404)
|
||||
|
||||
# Back to first user
|
||||
sign_in(user)
|
||||
get "#{uri.path}.json"
|
||||
data = response.parsed_body
|
||||
expect(data["provider_name"]).to eq("google_oauth2")
|
||||
|
||||
# Make the connection
|
||||
events = DiscourseEvent.track_events { post "#{uri.path}.json" }
|
||||
expect(events.any? { |e| e[:event_name] == :before_auth }).to eq(true)
|
||||
@ -80,6 +69,32 @@ RSpec.describe Users::AssociateAccountsController do
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it 'should only work within the current session' do
|
||||
sign_in(user)
|
||||
|
||||
post "/auth/google_oauth2?reconnect=true"
|
||||
expect(response.status).to eq(302)
|
||||
expect(session[:auth_reconnect]).to eq(true)
|
||||
|
||||
OmniAuth.config.mock_auth[:google_oauth2].uid = "123456"
|
||||
get "/auth/google_oauth2/callback.json"
|
||||
expect(response.status).to eq(302)
|
||||
|
||||
expect(session[:current_user_id]).to eq(user.id) # Still logged in
|
||||
expect(UserAssociatedAccount.count).to eq(0) # Reconnect has not yet happened
|
||||
|
||||
uri = URI.parse(response.redirect_url)
|
||||
get "#{uri.path}.json"
|
||||
data = response.parsed_body
|
||||
expect(data["provider_name"]).to eq("google_oauth2")
|
||||
expect(data["account_description"]).to eq("someemail@test.com")
|
||||
|
||||
cookies.delete "_forum_session"
|
||||
|
||||
get "#{uri.path}.json"
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "returns the correct response for non-existent tokens" do
|
||||
get "/associate/12345678901234567890123456789012.json"
|
||||
expect(response.status).to eq(404)
|
||||
|
Loading…
Reference in New Issue
Block a user