Commit Graph

169 Commits

Author SHA1 Message Date
Dan Ungureanu 5b7bddf966
FIX: Prefer email when resetting password (#15650)
The UI used to request a password reset by username when the user was
logged in. This did not work when hide_email_already_taken site setting
was enabled, which disables the lookup-by-username functionality.

This commit also introduces a check to ensure that the parameter is an
email when hide_email_already_taken is enabled as the single allowed
type is email (no usernames are allowed).
2022-01-20 10:04:45 +02:00
Andrei Prigorshnev 16d9b2755c
DEV: rename single_sign_on classes to discourse_connect (#15332) 2022-01-06 16:28:46 +04:00
Sam b6c3e9aa03
FEATURE: hide_email_address_taken forces use of email in forgot password form (#15362)
* FEATURE: hide_email_address_taken forces use of email in forgot password form

This strengthens this site setting which is meant to be used to harden sites
that are experiencing abuse on forgot password routes.

Previously we would only deny letting people know if forgot password worked on not
New change also bans usage of username for forgot password when enabled
2021-12-20 12:54:10 +11:00
Dan Ungureanu fa8cd629f1
DEV: Hash tokens stored from email_tokens (#14493)
This commit adds token_hash and scopes columns to email_tokens table.
token_hash is a replacement for the token column to avoid storing email
tokens in plaintext as it can pose a security risk. The new scope column
ensures that email tokens cannot be used to perform a different action
than the one intended.

To sum up, this commit:

* Adds token_hash and scope to email_tokens

* Reuses code that schedules critical_user_email

* Refactors EmailToken.confirm and EmailToken.atomic_confirm methods

* Periodically cleans old, unconfirmed or expired email tokens
2021-11-25 09:34:39 +02:00
Arpit Jalan 7db3888f17
FIX: log proper error message when SSO nonce verification fails (#14077) 2021-08-18 18:44:12 +05:30
Andrei Prigorshnev 1a8c949900
UX: suspend forever time period messages (#13776)
When the Forever option is selected for suspending a user, the user is suspended for 1000 years. Without customizing the site’s text, this time period is displayed to the user in the suspension email that is sent to the user, and if the user attempts to log back into the site. Telling someone that they have been suspended for 1000 years seems likely to come across as a bad attempt at humour.

This PR special case messages when a user suspended or silenced forever.
2021-07-20 14:42:08 +04:00
Martin Brennan 355d51afde
FEATURE: Allow using invites when DiscourseConnect SSO is enabled (#12419)
This PR allows invitations to be used when the DiscourseConnect SSO is enabled for a site (`enable_discourse_connect`) and local logins are disabled. Previously invites could not be accepted with SSO enabled simply because we did not have the code paths to handle that logic.

The invitation methods that are supported include:

* Inviting people to groups via email address
* Inviting people to topics via email address
* Using invitation links generated by the Invite Users UI in the /my/invited/pending route

The flow works like this:

1. User visits an invite URL
2. The normal invitation validations (redemptions/expiry) happen at that point
3. We store the invite key in a secure session
4. The user clicks "Accept Invitation and Continue" (see below)
5. The user is redirected to /session/sso then to the SSO provider URL then back to /session/sso_login
6. We retrieve the invite based on the invite key in secure session. We revalidate the invitation. We show an error to the user if it is not valid. An additional check here for invites with an email specified is to check the SSO email matches the invite email
7. If the invite is OK we create the user via the normal SSO methods
8. We redeem the invite and activate the user. We clear the invite key in secure session.
9. If the invite had a topic we redirect the user there, otherwise we redirect to /

Note that we decided for SSO-based invites the `must_approve_users` site setting is ignored, because the invite is a form of pre-approval, and because regular non-staff users cannot send out email invites or generally invite to the forum in this case.

Also deletes some group invite checks as per https://github.com/discourse/discourse/pull/12353
2021-03-19 10:20:10 +10:00
David Taylor 13d2a1f82c
SECURITY: Attach DiscourseConnect (SSO) nonce to current session (#12124) 2021-02-18 10:35:10 +00:00
David Taylor 7e6cb1ff2e
FIX: Correct server error for starting SSO login, and add spec (#12010)
Followup to 821bb1e8cb
2021-02-08 10:59:43 +00:00
David Taylor 821bb1e8cb
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978)
The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense.

This commit aims to:
- Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_`
- Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices
- Copy `site_settings` database records to the new names
- Rename relevant translation keys
- Update relevant translations

This commit does **not** aim to:
- Rename any Ruby classes or methods. This might be done in a future commit
- Change any URLs. This would break existing integrations
- Make any changes to the protocol. This would break existing integrations
- Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately

The risks are:
- There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical.
- If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working.

A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 10:04:33 +00:00
Martin Brennan e58f9f7a55
DEV: Move logic for rate limiting user second factor to one place (#11941)
This moves all the rate limiting for user second factor (based on `params[:second_factor_token]` existing) to the one place, which rate limits by IP and also by username if a user is found.
2021-02-04 09:03:30 +10:00
Robin Ward f39ae8a903
SECURITY: Rate limit MFA by login if possible (#11938)
This ensures we rate limit on logins where possible, we also normalize logins for the rate limiters centrally.
2021-02-03 10:26:28 +11:00
David Taylor 36b4712349
FIX: Logout redirect should only be `/login` for login_required sites (#11466)
25563357 moved the logout redirect logic from the client-side to the server-side. Unfortunately the login_required check was lost during the refactoring which meant that non-login-required sites would redirect to `/login` after redirect, and immediately restart the login process. Depending on the SSO implementation, that can make it impossible for users to log out cleanly.

This commit restores the login_required check, and prevents the potential redirect loop.
2020-12-11 09:44:16 +00:00
David Taylor 20c0da8516
FIX: Improve email validation error handling for external logins (#11307)
- Display reason for validation error when logging in via an authenticator
- Fix email validation handling for 'Discourse SSO', and add a spec

Previously, validation errors (e.g. blocked or already-taken emails) would raise a generic error with no useful information.
2020-11-23 11:06:08 +00:00
David Taylor 255633578c
DEV: Move logout redirect logic to server and add plugin hook (#11199)
This will allow authentication plugins to provide single-logout functionality by redirect users to the identity provider after logout.
2020-11-11 15:47:42 +00:00
Krzysztof Kotlarek 5cf411c3ae
FIX: move hp request from /users to /token (#10795)
`hp` is a valid username and we should not prevent users from registering it.
2020-10-02 09:01:40 +10:00
Sam Saffron d8d54a92f1
FEATURE: tighten rate limiting rules for forgot password
1. Total 6 attempts per day per user
2. Total of 5 per unique email/login that is not found per hour
3. If an admin blocks an IP that IP can not request a reset
2020-05-08 13:30:51 +10:00
Justin DiRose 5471c065cd
FIX: Missing timezone guess on email session login (#9404)
Timezone is guessed by moment.js if unset upon a normal login, but was not when
logging in via an email link. This adds logic to update a guessed
timezone upon email login so timezones don't end up blank.
2020-04-10 13:19:39 -05:00
Sam Saffron 0375a5ac0b
DEV: reduce logging when no external id is specified
Previously we were returning an unknown sso error and logging a message
when external id was blank. This noise is not needed.
2020-04-08 12:42:28 +10:00
Blake Erickson 965ac3567b FIX: Handle SSO Provider Parse exception
Prevent unnecessary 500 errors from appearing in the logs and return a
422 response instead.
2020-02-12 16:08:04 -07:00
Matt Marjanović ad2aa7b52c
FEATURE: Add logout functionality to SSO Provider protocol (#8816)
This commit adds support for an optional "logout" parameter in the
payload of the /session/sso_provider endpoint.  If an SSO Consumer
adds a "logout=true" parameter to the encoded/signed "sso" payload,
then Discourse will treat the request as a logout request instead
of an authentication request.  The logout flow works something like
this:

 * User requests logout at SSO-Consumer site (e.g., clicks "Log me out!"
   on web browser).
 * SSO-Consumer site does whatever it does to destroy User's session on
   the SSO-Consumer site.
 * SSO-Consumer then redirects browser to the Discourse sso_provider
   endpoint, with a signed request bearing "logout=true" in addition
   to the usual nonce and the "return_sso_url".
 * Discourse destroys User's discourse session and redirects browser back
   to the "return_sso_url".
 * SSO-Consumer site does whatever it does --- notably, it cannot request
   SSO credentials from Discourse without the User being prompted to login
   again.
2020-02-03 12:53:14 -05:00
Martin Brennan 1014e56e80
DEV: Respond with 403 instead of 500 for disabled local login via email
Previously if local login via email was disabled because of the site setting or because SSO was enabled, we were raising a 500 error. We now raise a 403 error instead; we shouldn't raise 500 errors on purpose, instead keeping that code for unhandled errors. It doesn't make sense in the context of what we are validating either to raise a 500.
2020-01-20 16:11:58 +10:00
Martin Brennan 9c04aa593c
Fix broken admin login fro SSO enabled sites (#8737)
* When we refactored away the admin-login route we introduced a bug where admins could not log into an SSO enabled site, because of a check in the email_login route that disallowed this.
* Allow admin to get around this check.
2020-01-17 11:25:31 +10:00
Martin Brennan 66f2db4ea4 SECURITY: 2FA with U2F / TOTP 2020-01-15 11:27:12 +01:00
Martin Brennan 9e399b42b9 DEV: Remove redundant admin_login route, share with email_login 2020-01-13 12:10:07 +10:00
Martin Brennan cb660ef952 SECURITY: Improve second factor auth logic 2020-01-10 10:45:56 +10:00
Joffrey JAFFEUX aa73df768a
DEV: improves error message when sso param is not passed (#8549)
SingleSignOnProvider is expecting a sso param later in the chain. If sso param is not found it will cause a 500 with the following exception: `NoMethodError (undefined method `unpack1' for nil:NilClass)` as `set_return_sso_url` is attempting to decode it: https://github.com/discourse/discourse/blob/master/lib/single_sign_on_provider.rb#L19
2019-12-16 12:33:24 +01:00
Sam Saffron 0c52537f10 DEV: update rubocop to version 0.77
We like to stay as close as possible to latest with rubocop cause the cops
get better.

This update required some code changes, specifically the default is to avoid
explicit returns where implicit is done

Also this renames a few rules
2019-12-10 11:48:39 +11:00
Joffrey JAFFEUX 0d3d2c43a0
DEV: s/\$redis/Discourse\.redis (#8431)
This commit also adds a rubocop rule to prevent global variables.
2019-12-03 10:05:53 +01:00
Martin Brennan afb5533581
FEATURE: Add timezone to core user_options (#8380)
* Add timezone to user_options table

* Also migrate existing timezone values from UserCustomField,
  which is where the discourse-calendar plugin is storing them

* Allow user to change their core timezone from Profile

* Auto guess & set timezone on login & invite accept & signup

* Serialize user_options.timezone for group members. this is so discourse-group-timezones can access the core user timezone, as it is being removed in discourse-calendar.

* Annotate user_option with timezone

* Validate timezone values
2019-11-25 10:49:27 +10:00
Penar Musaraj 067696df8f DEV: Apply Rubocop redundant return style 2019-11-14 15:10:51 -05:00
Krzysztof Kotlarek 427d54b2b0 DEV: Upgrading Discourse to Zeitwerk (#8098)
Zeitwerk simplifies working with dependencies in dev and makes it easier reloading class chains. 

We no longer need to use Rails "require_dependency" anywhere and instead can just use standard 
Ruby patterns to require files.

This is a far reaching change and we expect some followups here.
2019-10-02 14:01:53 +10:00
Martin Brennan 68d35b14f4 FEATURE: Webauthn authenticator management with 2FA login (Security Keys) (#8099)
Adds 2 factor authentication method via second factor security keys over [web authn](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API).

Allows a user to authenticate a second factor on login, login-via-email, admin-login, and change password routes. Adds registration area within existing user second factor preferences to register multiple security keys. Supports both external (yubikey) and built-in (macOS/android fingerprint readers).
2019-10-01 19:08:41 -07:00
David Taylor 6d3d08daad UX: Hide login/signup header buttons during authentication flows 2019-08-08 13:57:18 +01:00
Osama Sayegh 525920a979
FIX: Better error when SSO fails due to blank secret (#7946)
* FIX: Better error when SSO fails due to blank secret

* Update spec/requests/session_controller_spec.rb

Co-Authored-By: Robin Ward <robin.ward@gmail.com>
2019-07-26 17:37:23 +03:00
Osama Sayegh 997add3af9
DEV: Add extension point to allow modifying SSO URL (#7937)
This allows plugins to, for example, add extra query params to the SSO URL when discourse redirects to to the SSO website.
2019-07-25 00:18:27 +03:00
David Taylor e6e47f2fb2 SECURITY: Add confirmation screen when logging in via user-api OTP 2019-06-17 16:18:44 +01:00
David Taylor 52387be4a4 SECURITY: Add confirmation screen when logging in via email link 2019-06-17 16:18:37 +01:00
David Taylor 5f6f707080 Revert "Merge pull request from GHSA-hv9p-jfm4-gpr9"
This reverts commit b8340c6c8e.
2019-06-17 16:17:10 +01:00
David Taylor b8340c6c8e
Merge pull request from GHSA-hv9p-jfm4-gpr9
* SECURITY: Add confirmation screen when logging in via email link

* SECURITY: Add confirmation screen when logging in via user-api OTP

* FIX: Correct translation key in session controller specs

* FIX: Use .email-login class for page
2019-06-17 15:59:41 +01:00
Sam Saffron e302c0af8b DEV: by default disable anon impersonation in dev environments
The impersonate any user by anonymous feature in dev should require a
deliberate opt-in. This way developers are better aware of the security
implications of this development only feature.
2019-06-03 10:02:27 +10:00
Guo Xiang Tan 64c117519e Fix modifying frozen strings errors take 3. 2019-05-13 16:45:23 +08:00
Sam Saffron 30990006a9 DEV: enable frozen string literal on all files
This reduces chances of errors where consumers of strings mutate inputs
and reduces memory usage of the app.

Test suite passes now, but there may be some stuff left, so we will run
a few sites on a branch prior to merging
2019-05-13 09:31:32 +08:00
Guo Xiang Tan 24347ace10 FIX: Properly associate user_profiles background urls via upload id.
`Upload#url` is more likely and can change from time to time. When it
does changes, we don't want to have to look through multiple tables to
ensure that the URLs are all up to date. Instead, we simply associate
uploads properly to `UserProfile` so that it does not have to replicate
the URLs in the table.
2019-05-02 14:58:24 +08:00
Chris Butler 8673bd832a FEATURE: use failed_to_login for SSO error (#7394)
The error displayed when logging into suspended accounts via SSO never includes
the suspension reason, unlike non-SSO logins. By re-using the failed_to_login
method when generating the error message for SSO we can ensure the message is
consistent between the SSO and non-SSO paths.
2019-04-24 16:38:56 +10:00
Penar Musaraj fdf4145d4b
FEATURE: Delegated authentication via user api keys (#7272) 2019-04-01 13:18:53 -04:00
Sam Saffron 40ac895ef7 SECURITY: properly validate return URL for SSO
Previously carefully crafted URLs could redirect off site
2019-03-25 09:02:42 +11:00
Robin Ward c719658f9f `human?` helper method on a user
This is cleaner than hard coding `id > 0` in ruby code.
2019-02-08 13:34:54 -05:00
Arpit Jalan 1ea0cbece8 FIX: skip adding sso diagnostics if sso object is nil 2018-12-19 20:55:35 +05:30
Maja Komel 2fcbbead45 FIX: move sso provider into its own class so it doesn't interfere with sso client (#6767) 2018-12-19 10:22:10 +01:00