2017-12-11 08:07:22 +08:00
|
|
|
# frozen_string_literal: true
|
2020-10-07 00:20:15 +08:00
|
|
|
require_relative "../route_matcher"
|
2017-12-11 08:07:22 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
# You may have seen references to v0 and v1 of our auth cookie in the codebase
|
|
|
|
# and you're not sure how they differ, so here is an explanation:
|
|
|
|
#
|
|
|
|
# From the very early days of Discourse, the auth cookie (_t) consisted only of
|
|
|
|
# a 32 characters random string that Discourse used to identify/lookup the
|
|
|
|
# current user. We didn't include any metadata with the cookie or encrypt/sign
|
|
|
|
# it.
|
|
|
|
#
|
|
|
|
# That was v0 of the auth cookie until Nov 2021 when we merged a change that
|
|
|
|
# required us to store additional metadata with the cookie so we could get more
|
|
|
|
# information about current user early in the request lifecycle before we
|
|
|
|
# performed database lookup. We also started encrypting and signing the cookie
|
|
|
|
# to prevent tampering and obfuscate user information that we include in the
|
|
|
|
# cookie. This is v1 of our auth cookie and we still use it to this date.
|
|
|
|
#
|
|
|
|
# We still accept v0 of the auth cookie to keep users logged in, but upon
|
|
|
|
# cookie rotation (which happen every 10 minutes) they'll be switched over to
|
|
|
|
# the v1 format.
|
|
|
|
#
|
|
|
|
# We'll drop support for v0 after Discourse 2.9 is released.
|
|
|
|
|
2013-10-09 12:10:37 +08:00
|
|
|
class Auth::DefaultCurrentUserProvider
|
2024-10-16 10:09:07 +08:00
|
|
|
CURRENT_USER_KEY = "_DISCOURSE_CURRENT_USER"
|
|
|
|
USER_TOKEN_KEY = "_DISCOURSE_USER_TOKEN"
|
|
|
|
API_KEY = "api_key"
|
|
|
|
API_USERNAME = "api_username"
|
|
|
|
HEADER_API_KEY = "HTTP_API_KEY"
|
|
|
|
HEADER_API_USERNAME = "HTTP_API_USERNAME"
|
|
|
|
HEADER_API_USER_EXTERNAL_ID = "HTTP_API_USER_EXTERNAL_ID"
|
|
|
|
HEADER_API_USER_ID = "HTTP_API_USER_ID"
|
|
|
|
PARAMETER_USER_API_KEY = "user_api_key"
|
|
|
|
USER_API_KEY = "HTTP_USER_API_KEY"
|
|
|
|
USER_API_CLIENT_ID = "HTTP_USER_API_CLIENT_ID"
|
|
|
|
API_KEY_ENV = "_DISCOURSE_API"
|
|
|
|
USER_API_KEY_ENV = "_DISCOURSE_USER_API"
|
|
|
|
TOKEN_COOKIE = ENV["DISCOURSE_TOKEN_COOKIE"] || "_t"
|
|
|
|
PATH_INFO = "PATH_INFO"
|
|
|
|
COOKIE_ATTEMPTS_PER_MIN = 10
|
|
|
|
BAD_TOKEN = "_DISCOURSE_BAD_TOKEN"
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
DECRYPTED_AUTH_COOKIE = "_DISCOURSE_DECRYPTED_AUTH_COOKIE"
|
|
|
|
|
|
|
|
TOKEN_SIZE = 32
|
2013-10-09 12:10:37 +08:00
|
|
|
|
2024-10-16 10:09:07 +08:00
|
|
|
PARAMETER_API_PATTERNS = [
|
2020-10-07 00:20:15 +08:00
|
|
|
RouteMatcher.new(
|
|
|
|
methods: :get,
|
|
|
|
actions: [
|
2020-05-12 20:35:36 +08:00
|
|
|
"posts#latest",
|
|
|
|
"posts#user_posts_feed",
|
|
|
|
"groups#posts_feed",
|
|
|
|
"groups#mentions_feed",
|
2020-05-12 23:08:35 +08:00
|
|
|
"list#user_topics_feed",
|
2020-05-12 20:35:36 +08:00
|
|
|
"list#category_feed",
|
2020-05-12 23:08:35 +08:00
|
|
|
"topics#feed",
|
|
|
|
"badges#show",
|
|
|
|
"tags#tag_feed",
|
|
|
|
"tags#show",
|
|
|
|
*%i[latest unread new read posted bookmarks].map { |f| "list##{f}_feed" },
|
|
|
|
*%i[all yearly quarterly monthly weekly daily].map { |p| "list#top_#{p}_feed" },
|
|
|
|
*%i[latest unread new read posted bookmarks].map { |f| "tags#show_#{f}" },
|
2020-05-12 20:35:36 +08:00
|
|
|
],
|
2020-10-07 00:20:15 +08:00
|
|
|
formats: :rss,
|
2021-05-06 10:59:52 +08:00
|
|
|
),
|
2020-10-07 00:20:15 +08:00
|
|
|
RouteMatcher.new(methods: :get, actions: "users#bookmarks", formats: :ics),
|
|
|
|
RouteMatcher.new(methods: :post, actions: "admin/email#handle_mail", formats: nil),
|
2020-05-12 20:35:36 +08:00
|
|
|
]
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def self.find_v0_auth_cookie(request)
|
2022-06-07 19:00:25 +08:00
|
|
|
cookie = request.cookies[TOKEN_COOKIE]
|
|
|
|
|
|
|
|
cookie if cookie&.valid_encoding? && cookie.present? && cookie.size == TOKEN_SIZE
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.find_v1_auth_cookie(env)
|
|
|
|
return env[DECRYPTED_AUTH_COOKIE] if env.key?(DECRYPTED_AUTH_COOKIE)
|
|
|
|
|
|
|
|
env[DECRYPTED_AUTH_COOKIE] = begin
|
|
|
|
request = ActionDispatch::Request.new(env)
|
2022-06-07 19:00:25 +08:00
|
|
|
cookie = request.cookies[TOKEN_COOKIE]
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
# don't even initialize a cookie jar if we don't have a cookie at all
|
2022-06-07 19:00:25 +08:00
|
|
|
if cookie&.valid_encoding? && cookie.present?
|
2022-04-21 02:15:40 +08:00
|
|
|
request.cookie_jar.encrypted[TOKEN_COOKIE]&.with_indifferent_access
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-10-09 12:10:37 +08:00
|
|
|
# do all current user initialization here
|
2018-09-04 14:17:05 +08:00
|
|
|
def initialize(env)
|
2013-10-09 12:10:37 +08:00
|
|
|
@env = env
|
|
|
|
@request = Rack::Request.new(env)
|
2022-07-04 23:01:19 +08:00
|
|
|
@user_token = env[USER_TOKEN_KEY]
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
# our current user, return nil if none is found
|
|
|
|
def current_user
|
|
|
|
return @env[CURRENT_USER_KEY] if @env.key?(CURRENT_USER_KEY)
|
|
|
|
|
2014-10-24 10:38:00 +08:00
|
|
|
# bypass if we have the shared session header
|
|
|
|
if shared_key = @env["HTTP_X_SHARED_SESSION_KEY"]
|
2019-12-03 17:05:53 +08:00
|
|
|
uid = Discourse.redis.get("shared_session_key_#{shared_key}")
|
2014-10-24 10:38:00 +08:00
|
|
|
user = nil
|
|
|
|
user = User.find_by(id: uid.to_i) if uid
|
|
|
|
@env[CURRENT_USER_KEY] = user
|
|
|
|
return user
|
|
|
|
end
|
|
|
|
|
2014-05-23 06:13:25 +08:00
|
|
|
request = @request
|
2013-10-09 12:10:37 +08:00
|
|
|
|
2017-02-18 00:02:33 +08:00
|
|
|
user_api_key = @env[USER_API_KEY]
|
2020-05-12 20:35:36 +08:00
|
|
|
api_key = @env[HEADER_API_KEY]
|
|
|
|
|
|
|
|
if !@env.blank? && request[PARAMETER_USER_API_KEY] && api_parameter_allowed?
|
|
|
|
user_api_key ||= request[PARAMETER_USER_API_KEY]
|
|
|
|
end
|
|
|
|
|
|
|
|
api_key ||= request[API_KEY] if !@env.blank? && request[API_KEY] && api_parameter_allowed?
|
2017-02-18 00:02:33 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
auth_token = find_auth_token
|
2013-10-09 12:10:37 +08:00
|
|
|
current_user = nil
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
if auth_token
|
2016-08-09 08:02:18 +08:00
|
|
|
limiter = RateLimiter.new(nil, "cookie_auth_#{request.ip}", COOKIE_ATTEMPTS_PER_MIN, 60)
|
|
|
|
|
2018-02-10 08:09:54 +08:00
|
|
|
if limiter.can_perform?
|
2022-07-04 23:01:19 +08:00
|
|
|
@env[USER_TOKEN_KEY] = @user_token =
|
|
|
|
begin
|
2020-06-03 16:36:51 +08:00
|
|
|
UserAuthToken.lookup(
|
|
|
|
auth_token,
|
|
|
|
seen: true,
|
|
|
|
user_agent: @env["HTTP_USER_AGENT"],
|
|
|
|
path: @env["REQUEST_PATH"],
|
|
|
|
client_ip: @request.ip,
|
|
|
|
)
|
|
|
|
rescue ActiveRecord::ReadOnlyError
|
|
|
|
nil
|
|
|
|
end
|
2017-02-14 03:01:01 +08:00
|
|
|
|
2017-02-01 06:21:37 +08:00
|
|
|
current_user = @user_token.try(:user)
|
2024-07-24 15:19:58 +08:00
|
|
|
current_user.authenticated_with_oauth = @user_token.authenticated_with_oauth if current_user
|
2016-08-09 08:02:18 +08:00
|
|
|
end
|
2016-07-28 10:58:49 +08:00
|
|
|
|
2018-03-06 13:49:31 +08:00
|
|
|
if !current_user
|
|
|
|
@env[BAD_TOKEN] = true
|
2016-07-28 10:58:49 +08:00
|
|
|
begin
|
2018-09-04 14:17:05 +08:00
|
|
|
limiter.performed!
|
2016-07-28 10:58:49 +08:00
|
|
|
rescue RateLimiter::LimitExceeded
|
2018-02-10 08:09:54 +08:00
|
|
|
raise Discourse::InvalidAccess.new("Invalid Access", nil, delete_cookie: TOKEN_COOKIE)
|
2016-07-28 10:58:49 +08:00
|
|
|
end
|
|
|
|
end
|
2018-03-06 13:49:31 +08:00
|
|
|
elsif @env["HTTP_DISCOURSE_LOGGED_IN"]
|
|
|
|
@env[BAD_TOKEN] = true
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
# possible we have an api call, impersonate
|
2017-02-18 00:02:33 +08:00
|
|
|
if api_key
|
2014-05-23 06:13:25 +08:00
|
|
|
current_user = lookup_api_user(api_key, request)
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
if !current_user
|
|
|
|
raise Discourse::InvalidAccess.new(
|
|
|
|
I18n.t("invalid_api_credentials"),
|
|
|
|
nil,
|
|
|
|
custom_message: "invalid_api_credentials",
|
|
|
|
)
|
|
|
|
end
|
2017-02-18 00:02:33 +08:00
|
|
|
raise Discourse::InvalidAccess if current_user.suspended? || !current_user.active
|
2024-06-18 02:21:11 +08:00
|
|
|
|
|
|
|
if !Rails.env.profile?
|
|
|
|
admin_api_key_limiter.performed!
|
|
|
|
|
|
|
|
# Don't enforce the default per ip limits for authenticated admin api
|
|
|
|
# requests
|
|
|
|
(@env["DISCOURSE_RATE_LIMITERS"] || []).each(&:rollback!)
|
|
|
|
end
|
|
|
|
|
2014-05-23 06:13:25 +08:00
|
|
|
@env[API_KEY_ENV] = true
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|
|
|
|
|
2016-08-15 15:58:33 +08:00
|
|
|
# user api key handling
|
2017-02-18 00:02:33 +08:00
|
|
|
if user_api_key
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
@hashed_user_api_key = ApiKey.hash_key(user_api_key)
|
2016-08-15 15:58:33 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
user_api_key_obj =
|
|
|
|
UserApiKey
|
|
|
|
.active
|
|
|
|
.joins(:user)
|
|
|
|
.where(key_hash: @hashed_user_api_key)
|
|
|
|
.includes(:user, :scopes)
|
|
|
|
.first
|
2016-08-15 15:58:33 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
raise Discourse::InvalidAccess unless user_api_key_obj
|
2016-08-15 15:58:33 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
user_api_key_limiter_60_secs.performed!
|
|
|
|
user_api_key_limiter_1_day.performed!
|
2016-08-15 15:58:33 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
user_api_key_obj.ensure_allowed!(@env)
|
|
|
|
|
|
|
|
current_user = user_api_key_obj.user
|
2017-02-18 00:02:33 +08:00
|
|
|
raise Discourse::InvalidAccess if current_user.suspended? || !current_user.active
|
2016-08-15 15:58:33 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
user_api_key_obj.update_last_used(@env[USER_API_CLIENT_ID]) if can_write?
|
2016-08-15 15:58:33 +08:00
|
|
|
|
2016-12-16 09:05:20 +08:00
|
|
|
@env[USER_API_KEY_ENV] = true
|
2016-08-15 15:58:33 +08:00
|
|
|
end
|
|
|
|
|
2017-02-18 00:02:33 +08:00
|
|
|
# keep this rule here as a safeguard
|
|
|
|
# under no conditions to suspended or inactive accounts get current_user
|
|
|
|
current_user = nil if current_user && (current_user.suspended? || !current_user.active)
|
|
|
|
|
2018-07-18 23:04:57 +08:00
|
|
|
if current_user && should_update_last_seen?
|
2020-03-11 14:42:56 +08:00
|
|
|
ip = request.ip
|
2022-05-03 06:50:56 +08:00
|
|
|
user_id = current_user.id
|
|
|
|
old_ip = current_user.ip_address
|
2020-03-11 14:42:56 +08:00
|
|
|
|
2018-07-18 23:04:57 +08:00
|
|
|
Scheduler::Defer.later "Updating Last Seen" do
|
2022-05-03 06:50:56 +08:00
|
|
|
if User.should_update_last_seen?(user_id)
|
|
|
|
if u = User.find_by(id: user_id)
|
|
|
|
u.update_last_seen!(Time.zone.now, force: true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
User.update_ip_address!(user_id, new_ip: ip, old_ip: old_ip)
|
2018-07-18 23:04:57 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-10-09 12:10:37 +08:00
|
|
|
@env[CURRENT_USER_KEY] = current_user
|
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def refresh_session(user, session, cookie_jar)
|
2017-02-01 06:21:37 +08:00
|
|
|
# if user was not loaded, no point refreshing session
|
|
|
|
# it could be an anonymous path, this would add cost
|
|
|
|
return if is_api? || !@env.key?(CURRENT_USER_KEY)
|
|
|
|
|
2017-02-18 00:02:33 +08:00
|
|
|
if !is_user_api? && @user_token && @user_token.user == user
|
2017-02-01 06:21:37 +08:00
|
|
|
rotated_at = @user_token.rotated_at
|
|
|
|
|
|
|
|
needs_rotation =
|
2023-01-09 20:10:19 +08:00
|
|
|
(
|
2017-02-01 06:21:37 +08:00
|
|
|
if @user_token.auth_token_seen
|
|
|
|
rotated_at < UserAuthToken::ROTATE_TIME.ago
|
2023-01-09 20:10:19 +08:00
|
|
|
else
|
2017-02-01 06:21:37 +08:00
|
|
|
rotated_at < UserAuthToken::URGENT_ROTATE_TIME.ago
|
2023-01-09 20:10:19 +08:00
|
|
|
end
|
|
|
|
)
|
2017-02-01 06:21:37 +08:00
|
|
|
|
2018-05-04 09:11:44 +08:00
|
|
|
if needs_rotation
|
2017-02-01 06:21:37 +08:00
|
|
|
if @user_token.rotate!(
|
|
|
|
user_agent: @env["HTTP_USER_AGENT"],
|
2017-03-08 02:27:34 +08:00
|
|
|
client_ip: @request.ip,
|
|
|
|
path: @env["REQUEST_PATH"],
|
|
|
|
)
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
set_auth_cookie!(@user_token.unhashed_auth_token, user, cookie_jar)
|
2020-04-15 00:32:24 +08:00
|
|
|
DiscourseEvent.trigger(:user_session_refreshed, user)
|
2017-02-01 06:21:37 +08:00
|
|
|
end
|
|
|
|
end
|
2016-07-25 10:07:31 +08:00
|
|
|
end
|
2017-02-01 06:21:37 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
cookie_jar.delete(TOKEN_COOKIE) if !user && cookie_jar.key?(TOKEN_COOKIE)
|
2016-07-25 10:07:31 +08:00
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def log_on_user(user, session, cookie_jar, opts = {})
|
2022-07-04 23:01:19 +08:00
|
|
|
@env[USER_TOKEN_KEY] = @user_token =
|
|
|
|
UserAuthToken.generate!(
|
2018-10-26 06:29:28 +08:00
|
|
|
user_id: user.id,
|
|
|
|
user_agent: @env["HTTP_USER_AGENT"],
|
|
|
|
path: @env["REQUEST_PATH"],
|
|
|
|
client_ip: @request.ip,
|
2018-11-12 22:34:12 +08:00
|
|
|
staff: user.staff?,
|
2018-11-12 23:00:12 +08:00
|
|
|
impersonate: opts[:impersonate],
|
2024-07-24 15:19:58 +08:00
|
|
|
authenticated_with_oauth: opts[:authenticated_with_oauth],
|
2018-11-12 23:00:12 +08:00
|
|
|
)
|
2016-07-26 09:37:41 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
set_auth_cookie!(@user_token.unhashed_auth_token, user, cookie_jar)
|
2020-03-17 23:48:24 +08:00
|
|
|
user.unstage!
|
2013-11-02 07:25:43 +08:00
|
|
|
make_developer_admin(user)
|
2016-04-27 01:08:19 +08:00
|
|
|
enable_bootstrap_mode(user)
|
2019-11-27 20:39:31 +08:00
|
|
|
|
|
|
|
UserAuthToken.enforce_session_count_limit!(user.id)
|
|
|
|
|
2013-10-09 12:10:37 +08:00
|
|
|
@env[CURRENT_USER_KEY] = user
|
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def set_auth_cookie!(unhashed_auth_token, user, cookie_jar)
|
|
|
|
data = {
|
|
|
|
token: unhashed_auth_token,
|
|
|
|
user_id: user.id,
|
2024-01-16 03:50:37 +08:00
|
|
|
username: user.username,
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
trust_level: user.trust_level,
|
|
|
|
issued_at: Time.zone.now.to_i,
|
2016-10-17 09:11:15 +08:00
|
|
|
}
|
2017-02-24 01:01:28 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
expires = SiteSetting.maximum_session_age.hours.from_now if SiteSetting.persistent_sessions
|
2020-09-11 13:11:13 +08:00
|
|
|
|
2017-02-24 01:01:28 +08:00
|
|
|
same_site = SiteSetting.same_site_cookies if SiteSetting.same_site_cookies != "Disabled"
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
cookie_jar.encrypted[TOKEN_COOKIE] = {
|
|
|
|
value: data,
|
|
|
|
httponly: true,
|
|
|
|
secure: SiteSetting.force_https,
|
|
|
|
expires: expires,
|
|
|
|
same_site: same_site,
|
|
|
|
}
|
2016-10-17 09:11:15 +08:00
|
|
|
end
|
|
|
|
|
2022-10-06 13:16:38 +08:00
|
|
|
# This is also used to set the first admin of the site via
|
|
|
|
# the finish installation & register -> user account activation
|
|
|
|
# for signup flow, since all admin emails are stored in
|
|
|
|
# DISCOURSE_DEVELOPER_EMAILS for self-hosters.
|
2013-11-02 07:25:43 +08:00
|
|
|
def make_developer_admin(user)
|
|
|
|
if user.active? && !user.admin && Rails.configuration.respond_to?(:developer_emails) &&
|
|
|
|
Rails.configuration.developer_emails.include?(user.email)
|
2014-03-24 15:03:39 +08:00
|
|
|
user.admin = true
|
|
|
|
user.save
|
2022-10-06 13:16:38 +08:00
|
|
|
Group.refresh_automatic_groups!(:staff, :admins)
|
2013-11-02 07:25:43 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-04-27 01:08:19 +08:00
|
|
|
def enable_bootstrap_mode(user)
|
2018-05-13 23:00:02 +08:00
|
|
|
return if SiteSetting.bootstrap_mode_enabled
|
|
|
|
|
|
|
|
if user.admin && user.last_seen_at.nil? && user.is_singular_admin?
|
|
|
|
Jobs.enqueue(:enable_bootstrap_mode, user_id: user.id)
|
|
|
|
end
|
2016-04-27 01:08:19 +08:00
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def log_off_user(session, cookie_jar)
|
2017-02-01 06:21:37 +08:00
|
|
|
user = current_user
|
2018-05-13 23:00:02 +08:00
|
|
|
|
2017-02-01 06:21:37 +08:00
|
|
|
if SiteSetting.log_out_strict && user
|
|
|
|
user.user_auth_tokens.destroy_all
|
2016-05-18 15:27:54 +08:00
|
|
|
|
|
|
|
if user.admin && defined?(Rack::MiniProfiler)
|
|
|
|
# clear the profiling cookie to keep stuff tidy
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
cookie_jar.delete("__profilin")
|
2016-05-18 15:27:54 +08:00
|
|
|
end
|
|
|
|
|
2016-07-04 17:20:30 +08:00
|
|
|
user.logged_out
|
2017-02-01 06:21:37 +08:00
|
|
|
elsif user && @user_token
|
|
|
|
@user_token.destroy
|
2024-08-22 21:48:27 +08:00
|
|
|
DiscourseEvent.trigger(:user_logged_out, user)
|
2015-01-28 09:56:25 +08:00
|
|
|
end
|
2017-08-31 12:06:56 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
cookie_jar.delete("authentication_data")
|
|
|
|
cookie_jar.delete(TOKEN_COOKIE)
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
# api has special rights return true if api was detected
|
|
|
|
def is_api?
|
|
|
|
current_user
|
2016-12-16 09:05:20 +08:00
|
|
|
!!(@env[API_KEY_ENV])
|
|
|
|
end
|
|
|
|
|
|
|
|
def is_user_api?
|
|
|
|
current_user
|
|
|
|
!!(@env[USER_API_KEY_ENV])
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def has_auth_cookie?
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
find_auth_token.present?
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|
2014-05-23 06:13:25 +08:00
|
|
|
|
|
|
|
def should_update_last_seen?
|
2020-07-21 13:43:28 +08:00
|
|
|
return false unless can_write?
|
2019-01-22 18:07:48 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
api = !!@env[API_KEY_ENV] || !!@env[USER_API_KEY_ENV]
|
2019-04-16 00:34:34 +08:00
|
|
|
|
|
|
|
if @request.xhr? || api
|
2020-03-26 14:35:32 +08:00
|
|
|
@env["HTTP_DISCOURSE_PRESENT"] == "true"
|
2017-03-01 01:34:57 +08:00
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
2014-05-23 06:13:25 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def lookup_api_user(api_key_value, request)
|
2019-12-12 19:45:00 +08:00
|
|
|
if api_key = ApiKey.active.with_key(api_key_value).includes(:user).first
|
2019-03-13 07:16:42 +08:00
|
|
|
api_username = header_api_key? ? @env[HEADER_API_USERNAME] : request[API_USERNAME]
|
2019-11-09 08:28:48 +08:00
|
|
|
|
2021-12-29 20:22:21 +08:00
|
|
|
return nil if !api_key.request_allowed?(@env)
|
2014-11-20 12:21:49 +08:00
|
|
|
|
2019-09-03 16:10:29 +08:00
|
|
|
user =
|
|
|
|
if api_key.user
|
|
|
|
api_key.user if !api_username || (api_key.user.username_lower == api_username.downcase)
|
|
|
|
elsif api_username
|
|
|
|
User.find_by(username_lower: api_username.downcase)
|
|
|
|
elsif user_id = header_api_key? ? @env[HEADER_API_USER_ID] : request["api_user_id"]
|
|
|
|
User.find_by(id: user_id.to_i)
|
|
|
|
elsif external_id =
|
|
|
|
header_api_key? ? @env[HEADER_API_USER_EXTERNAL_ID] : request["api_user_external_id"]
|
|
|
|
SingleSignOnRecord.find_by(external_id: external_id.to_s).try(:user)
|
|
|
|
end
|
|
|
|
|
2020-07-21 13:43:28 +08:00
|
|
|
if user && can_write?
|
2022-04-06 22:01:52 +08:00
|
|
|
Scheduler::Defer.later "Updating api_key last_used" do
|
|
|
|
api_key.update_last_used!
|
|
|
|
end
|
2014-05-23 06:13:25 +08:00
|
|
|
end
|
2019-09-03 16:10:29 +08:00
|
|
|
|
|
|
|
user
|
2014-05-23 06:13:25 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-09-04 16:35:49 +08:00
|
|
|
private
|
|
|
|
|
2020-08-24 17:24:52 +08:00
|
|
|
def parameter_api_patterns
|
|
|
|
PARAMETER_API_PATTERNS + DiscoursePluginRegistry.api_parameter_routes
|
|
|
|
end
|
|
|
|
|
2020-05-12 20:35:36 +08:00
|
|
|
# By default we only allow headers for sending API credentials
|
|
|
|
# However, in some scenarios it is essential to send them via url parameters
|
|
|
|
# so we need to add some exceptions
|
|
|
|
def api_parameter_allowed?
|
2020-10-07 00:20:15 +08:00
|
|
|
parameter_api_patterns.any? { |p| p.match?(env: @env) }
|
2020-03-17 02:05:24 +08:00
|
|
|
end
|
|
|
|
|
2019-03-13 07:16:42 +08:00
|
|
|
def header_api_key?
|
|
|
|
!!@env[HEADER_API_KEY]
|
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def can_write?
|
|
|
|
@can_write ||= !Discourse.pg_readonly_mode?
|
|
|
|
end
|
|
|
|
|
|
|
|
def admin_api_key_limiter
|
|
|
|
return @admin_api_key_limiter if @admin_api_key_limiter
|
2018-09-04 16:35:49 +08:00
|
|
|
|
2021-06-03 17:52:43 +08:00
|
|
|
limit = GlobalSetting.max_admin_api_reqs_per_minute.to_i
|
|
|
|
if GlobalSetting.respond_to?(:max_admin_api_reqs_per_key_per_minute)
|
2021-11-12 22:52:59 +08:00
|
|
|
Discourse.deprecate(
|
|
|
|
"DISCOURSE_MAX_ADMIN_API_REQS_PER_KEY_PER_MINUTE is deprecated. Please use DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE",
|
|
|
|
drop_from: "2.9.0",
|
|
|
|
)
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
limit = [GlobalSetting.max_admin_api_reqs_per_key_per_minute.to_i, limit].max
|
2021-06-03 17:52:43 +08:00
|
|
|
end
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
@admin_api_key_limiter =
|
|
|
|
RateLimiter.new(nil, "admin_api_min", limit, 60, error_code: "admin_api_key_rate_limit")
|
|
|
|
end
|
2021-06-03 17:52:43 +08:00
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def user_api_key_limiter_60_secs
|
|
|
|
@user_api_key_limiter_60_secs ||=
|
|
|
|
RateLimiter.new(
|
|
|
|
nil,
|
|
|
|
"user_api_min_#{@hashed_user_api_key}",
|
|
|
|
GlobalSetting.max_user_api_reqs_per_minute,
|
|
|
|
60,
|
|
|
|
error_code: "user_api_key_limiter_60_secs",
|
|
|
|
)
|
2018-09-04 16:35:49 +08:00
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def user_api_key_limiter_1_day
|
|
|
|
@user_api_key_limiter_1_day ||=
|
|
|
|
RateLimiter.new(
|
|
|
|
nil,
|
|
|
|
"user_api_day_#{@hashed_user_api_key}",
|
|
|
|
GlobalSetting.max_user_api_reqs_per_day,
|
|
|
|
86_400,
|
|
|
|
error_code: "user_api_key_limiter_1_day",
|
|
|
|
)
|
2020-07-21 13:43:28 +08:00
|
|
|
end
|
|
|
|
|
FEATURE: Apply rate limits per user instead of IP for trusted users (#14706)
Currently, Discourse rate limits all incoming requests by the IP address they
originate from regardless of the user making the request. This can be
frustrating if there are multiple users using Discourse simultaneously while
sharing the same IP address (e.g. employees in an office).
This commit implements a new feature to make Discourse apply rate limits by
user id rather than IP address for users at or higher than the configured trust
level (1 is the default).
For example, let's say a Discourse instance is configured to allow 200 requests
per minute per IP address, and we have 10 users at trust level 4 using
Discourse simultaneously from the same IP address. Before this feature, the 10
users could only make a total of 200 requests per minute before they got rate
limited. But with the new feature, each user is allowed to make 200 requests
per minute because the rate limits are applied on user id rather than the IP
address.
The minimum trust level for applying user-id-based rate limits can be
configured by the `skip_per_ip_rate_limit_trust_level` global setting. The
default is 1, but it can be changed by either adding the
`DISCOURSE_SKIP_PER_IP_RATE_LIMIT_TRUST_LEVEL` environment variable with the
desired value to your `app.yml`, or changing the setting's value in the
`discourse.conf` file.
Requests made with API keys are still rate limited by IP address and the
relevant global settings that control API keys rate limits.
Before this commit, Discourse's auth cookie (`_t`) was simply a 32 characters
string that Discourse used to lookup the current user from the database and the
cookie contained no additional information about the user. However, we had to
change the cookie content in this commit so we could identify the user from the
cookie without making a database query before the rate limits logic and avoid
introducing a bottleneck on busy sites.
Besides the 32 characters auth token, the cookie now includes the user id,
trust level and the cookie's generation date, and we encrypt/sign the cookie to
prevent tampering.
Internal ticket number: t54739.
2021-11-18 04:27:30 +08:00
|
|
|
def find_auth_token
|
|
|
|
return @auth_token if defined?(@auth_token)
|
|
|
|
|
|
|
|
@auth_token =
|
|
|
|
begin
|
|
|
|
if v0 = self.class.find_v0_auth_cookie(@request)
|
|
|
|
v0
|
|
|
|
elsif v1 = self.class.find_v1_auth_cookie(@env)
|
|
|
|
v1[:token] if v1[:issued_at] >= SiteSetting.maximum_session_age.hours.ago.to_i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-10-09 12:10:37 +08:00
|
|
|
end
|