mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 22:43:49 +08:00
SECURITY: inactive/suspended accounts should be banned from api
Also fixes edge cases around users presenting multiple credentials
This commit is contained in:
parent
c0e1722ca6
commit
7a85469c4c
|
@ -36,7 +36,10 @@ class Auth::DefaultCurrentUserProvider
|
||||||
|
|
||||||
request = @request
|
request = @request
|
||||||
|
|
||||||
auth_token = request.cookies[TOKEN_COOKIE]
|
user_api_key = @env[USER_API_KEY]
|
||||||
|
api_key = request[API_KEY]
|
||||||
|
|
||||||
|
auth_token = request.cookies[TOKEN_COOKIE] unless user_api_key || api_key
|
||||||
|
|
||||||
current_user = nil
|
current_user = nil
|
||||||
|
|
||||||
|
@ -61,10 +64,6 @@ class Auth::DefaultCurrentUserProvider
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_user && (current_user.suspended? || !current_user.active)
|
|
||||||
current_user = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if current_user && should_update_last_seen?
|
if current_user && should_update_last_seen?
|
||||||
u = current_user
|
u = current_user
|
||||||
Scheduler::Defer.later "Updating Last Seen" do
|
Scheduler::Defer.later "Updating Last Seen" do
|
||||||
|
@ -74,17 +73,18 @@ class Auth::DefaultCurrentUserProvider
|
||||||
end
|
end
|
||||||
|
|
||||||
# possible we have an api call, impersonate
|
# possible we have an api call, impersonate
|
||||||
if api_key = request[API_KEY]
|
if api_key
|
||||||
current_user = lookup_api_user(api_key, request)
|
current_user = lookup_api_user(api_key, request)
|
||||||
raise Discourse::InvalidAccess unless current_user
|
raise Discourse::InvalidAccess unless current_user
|
||||||
|
raise Discourse::InvalidAccess if current_user.suspended? || !current_user.active
|
||||||
@env[API_KEY_ENV] = true
|
@env[API_KEY_ENV] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
# user api key handling
|
# user api key handling
|
||||||
if api_key = @env[USER_API_KEY]
|
if user_api_key
|
||||||
|
|
||||||
limiter_min = RateLimiter.new(nil, "user_api_min_#{api_key}", SiteSetting.max_user_api_reqs_per_minute, 60)
|
limiter_min = RateLimiter.new(nil, "user_api_min_#{user_api_key}", SiteSetting.max_user_api_reqs_per_minute, 60)
|
||||||
limiter_day = RateLimiter.new(nil, "user_api_day_#{api_key}", SiteSetting.max_user_api_reqs_per_day, 86400)
|
limiter_day = RateLimiter.new(nil, "user_api_day_#{user_api_key}", SiteSetting.max_user_api_reqs_per_day, 86400)
|
||||||
|
|
||||||
unless limiter_day.can_perform?
|
unless limiter_day.can_perform?
|
||||||
limiter_day.performed!
|
limiter_day.performed!
|
||||||
|
@ -94,8 +94,9 @@ class Auth::DefaultCurrentUserProvider
|
||||||
limiter_min.performed!
|
limiter_min.performed!
|
||||||
end
|
end
|
||||||
|
|
||||||
current_user = lookup_user_api_user_and_update_key(api_key, @env[USER_API_CLIENT_ID])
|
current_user = lookup_user_api_user_and_update_key(user_api_key, @env[USER_API_CLIENT_ID])
|
||||||
raise Discourse::InvalidAccess unless current_user
|
raise Discourse::InvalidAccess unless current_user
|
||||||
|
raise Discourse::InvalidAccess if current_user.suspended? || !current_user.active
|
||||||
|
|
||||||
limiter_min.performed!
|
limiter_min.performed!
|
||||||
limiter_day.performed!
|
limiter_day.performed!
|
||||||
|
@ -103,6 +104,12 @@ class Auth::DefaultCurrentUserProvider
|
||||||
@env[USER_API_KEY_ENV] = true
|
@env[USER_API_KEY_ENV] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# keep this rule here as a safeguard
|
||||||
|
# under no conditions to suspended or inactive accounts get current_user
|
||||||
|
if current_user && (current_user.suspended? || !current_user.active)
|
||||||
|
current_user = nil
|
||||||
|
end
|
||||||
|
|
||||||
@env[CURRENT_USER_KEY] = current_user
|
@env[CURRENT_USER_KEY] = current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -112,7 +119,7 @@ class Auth::DefaultCurrentUserProvider
|
||||||
# it could be an anonymous path, this would add cost
|
# it could be an anonymous path, this would add cost
|
||||||
return if is_api? || !@env.key?(CURRENT_USER_KEY)
|
return if is_api? || !@env.key?(CURRENT_USER_KEY)
|
||||||
|
|
||||||
if @user_token && @user_token.user == user
|
if !is_user_api? && @user_token && @user_token.user == user
|
||||||
rotated_at = @user_token.rotated_at
|
rotated_at = @user_token.rotated_at
|
||||||
|
|
||||||
needs_rotation = @user_token.auth_token_seen ? rotated_at < UserAuthToken::ROTATE_TIME.ago : rotated_at < UserAuthToken::URGENT_ROTATE_TIME.ago
|
needs_rotation = @user_token.auth_token_seen ? rotated_at < UserAuthToken::ROTATE_TIME.ago : rotated_at < UserAuthToken::URGENT_ROTATE_TIME.ago
|
||||||
|
|
|
@ -26,6 +26,18 @@ describe Auth::DefaultCurrentUserProvider do
|
||||||
user = Fabricate(:user)
|
user = Fabricate(:user)
|
||||||
ApiKey.create!(key: "hello", user_id: user.id, created_by_id: -1)
|
ApiKey.create!(key: "hello", user_id: user.id, created_by_id: -1)
|
||||||
expect(provider("/?api_key=hello").current_user.id).to eq(user.id)
|
expect(provider("/?api_key=hello").current_user.id).to eq(user.id)
|
||||||
|
|
||||||
|
user.update_columns(active: false)
|
||||||
|
|
||||||
|
expect{
|
||||||
|
provider("/?api_key=hello").current_user
|
||||||
|
}.to raise_error(Discourse::InvalidAccess)
|
||||||
|
|
||||||
|
user.update_columns(active: true, suspended_till: 1.day.from_now)
|
||||||
|
|
||||||
|
expect{
|
||||||
|
provider("/?api_key=hello").current_user
|
||||||
|
}.to raise_error(Discourse::InvalidAccess)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises for a user pretending" do
|
it "raises for a user pretending" do
|
||||||
|
@ -248,6 +260,13 @@ describe Auth::DefaultCurrentUserProvider do
|
||||||
provider("/", params.merge({"REQUEST_METHOD" => "POST"})).current_user
|
provider("/", params.merge({"REQUEST_METHOD" => "POST"})).current_user
|
||||||
}.to raise_error(Discourse::InvalidAccess)
|
}.to raise_error(Discourse::InvalidAccess)
|
||||||
|
|
||||||
|
|
||||||
|
user.update_columns(suspended_till: 1.year.from_now)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
provider("/", params).current_user
|
||||||
|
}.to raise_error(Discourse::InvalidAccess)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "rate limits api usage" do
|
it "rate limits api usage" do
|
||||||
|
|
Loading…
Reference in New Issue
Block a user