Commit Graph

61 Commits

Author SHA1 Message Date
Stanko K.R. 52d57c4681 Tidy up session_token 2025-12-19 19:21:57 +01:00
Stanko K.R. e0270c6c49 Clean up interfaces
I talked to the mobile team, and to keep things simple we agreed to send
the token via a cookie.
2025-12-19 19:21:57 +01:00
Stanko K.R. 1a1f4a077b Simplify auth logic 2025-12-19 19:21:57 +01:00
Fernando Olivares 877f82c0cc Pass a server token when creating a magic link via API 2025-12-19 19:21:57 +01:00
Stanko K.R. b92982b244 Cleanup & simplify sign in 2025-12-19 19:21:57 +01:00
Jeremy Daer 82626f020d Tailscale serve support (#2126)
Ensure we can serve the app from multiple hosts without breaking links.
* Switch unnecessary full URLs to paths
* Drop default host/port URL options for controllers

Shell 1
```bash
bin/dev
```

Shell 2
```bash
tailscale serve http://fizzy.localhost:3006
```
2025-12-13 09:29:50 -08:00
Stanko Krtalić 23425cb67b Merge pull request #2086 from basecamp/harden-magic-links
Pin sign in attempts to the current session
2025-12-12 07:23:19 +01:00
Stanko K.R. abaed12124 Prohibit access to magic links unless an email address 2025-12-11 19:17:39 +01:00
Stanko K.R. b6edb93c47 Pin sign in attempts to the current session
This makes it way more difficult to brute-force a magic link.

Original implementation by udiudi. Ref: https://github.com/udiudi/fizzy/pull/1/files

Discussion: https://github.com/basecamp/fizzy/discussions/1981

Co-Authored-By: Udi <udi@udi.codes>
2025-12-11 19:05:54 +01:00
Mike Dalessio 3d523b84fc Explicitly use main_app for URL helpers
in controller concerns that are mixed into other engines' controllers. This prevents errors like:

> NoMethodError: undefined method 'session_menu_url' for an instance of ActiveStorage::DirectUploadsController

See also 912bb8a8 and 5ee10800
2025-12-11 12:55:32 -05:00
Stanko K.R. 259707bf70 Fix identity tests 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 0159f369f4 Only authenticate with bearer token if the header is present 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 79fc57a82a Use built-in authenticate_or_request_with_http_token
Hat tip to @adrienpoly
2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 0ce3a85778 Only allow writing when the access token has permission 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson caa4cd491e Smooth out the finder API 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 7d2c284726 Clarify 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 467843fe22 Inline now anemic helper methods 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 3329008dd8 Handle everything in the same method 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 660fcff558 Authenticate api requests without needing a session 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson db29562c4c Tie access token directly to session
We need to present them differently in the session list and prevent them
from being deleted
2025-12-10 09:23:52 +01:00
David Heinemeier Hansson a81c681a8d Add access token authentication via HTTP AUTHORIZATION bearer header 2025-12-10 09:23:52 +01:00
Mike Dalessio 0160f215f2 Validate email before creating identity during sign-up and sign-in
Avoid Sentry exceptions when attackers try to stuff invalid emails. The
browser performs form field validation that should normally prevent this
from occurring, so we just return 422 without validation error messages.

Also:

- extract redirect_to_session_magic_link helper
- some controller refactoring and cleanup
2025-12-06 16:52:16 -05:00
Jorge Manrubia c9ebb79dbd Add some protections around sharing the magic link in development 2025-12-02 10:51:14 +01:00
Jorge Manrubia e30709f6a7 Remove structured logging moved to the engine 2025-11-28 15:53:58 +01:00
Jorge Manrubia c1334f7ffe Don't choke if no structured logging
Temporary workaround, we need a better solution here.
2025-11-28 15:53:58 +01:00
Mike Dalessio 5a7f08067a Move setting Current.account into the middleware
so that code called from the Rails controllers can use Current.account
2025-11-17 09:12:40 -05:00
Stanko K.R. 5c6b91ef77 Fix incorrect var setting 2025-11-17 09:12:36 -05:00
Stanko K.R. 71a332bb08 Remove dead code 2025-11-17 09:12:17 -05:00
Mike Dalessio 89d1299ec0 Fix authentication on "untenanted" controllers
trying out the name "disallow_account_scope" for this, but I don't
think it's quite right yet.
2025-11-17 09:11:47 -05:00
Mike Dalessio 086a9ceada Revert some auth pieces of "Account.sole → Current.account" 2025-11-17 09:11:45 -05:00
Mike Dalessio ec54014832 Add account slug middleware
and set Current.account
2025-11-17 09:11:42 -05:00
Mike Dalessio d41d50d52b Account.sole → Current.account
and some other de-tenant changes, including removing the controller
tenanting concerns
2025-11-17 09:11:40 -05:00
Jorge Manrubia 2bb90eab13 Use the sole collection as the root for a better onboarding experience for new accounts 2025-11-04 17:09:35 +01:00
Stanko K.R. 87d9c3cd01 Make unauthenticated access permit unauthorized access 2025-11-04 09:02:36 +01:00
David Heinemeier Hansson 393e5fd3d4 Don't want to ship with this wart
cc @monorkin
2025-11-03 15:30:44 +01:00
David Heinemeier Hansson 42ebdf9ac1 More natural conditional 2025-11-03 15:29:20 +01:00
Stanko K.R. 49d865ffd1 Delete scoped session tokens when encountered 2025-10-31 19:00:37 +01:00
Stanko Krtalić 98755844a1 Remove the internal API
* Bind sessions to identities
* Remove references to the identity token
* Move email changes to identity
* Move account menu into a turbo-frame
* Create tenants from a tenanted route
2025-10-31 16:26:08 +01:00
Stanko K.R. 201c3e27d3 Update tests for the Internal API 2025-10-31 16:26:08 +01:00
Stanko K.R. 79b012f319 Add Join Codes 2025-10-31 16:24:30 +01:00
Stanko K.R. c8843360fe Clean up and simplify magic links 2025-10-31 16:23:38 +01:00
Stanko K.R. 5cef4ffeb0 Add sign in flow using magic links 2025-10-31 16:22:12 +01:00
Mike Dalessio 1277cc065b Introduce untenanted Identity and Membership models
The new integration test shows the desired user-facing behavior, which
is to make it easy to login without a tenanted URL and to jump between
tenants.

Note that we track two things in the identity_token cookie: a signed
id, and the updated_at for the underlying Identity object. This allows
us to effectively cache on the Identity without having to hit the
database, by using an Identity::Mock object that is compatible with
etag and cache methods.
2025-10-31 16:22:12 +01:00
Mike Dalessio 04be825609 Fix identities for existing sessions 2025-10-10 10:58:30 -04:00
Mike Dalessio 3399e45130 Introduce an "Identity" model to ease login
- New untenanted Identity and Membership models
- New `identity_token` cookie with path "/" holds state across tenants

We're not sure whether the untenanted database will be sqlite or
MySQL, and so I've been careful to minimize

- database reads, placing them behind etags and caching
- database writes, only writing when a new Session is created (login)

Note that we track two things in the identity_token cookie: a signed
id, and the updated_at for the underlying Identity object. This allows
us to effectively cache on the Identity without having to hit the
database, by using an Identity::Mock object that is compatible with
etag and cache methods.

The new integration test shows the desired user-facing behavior, which
is to make it easy to login without a tenanted URL and to jump between
tenants.

- the untenanted "login_help" page shows all linked memberships
- the jump menu shows all linked memberships (except the current)

Also introduced a utility script to populate existing employee
Identities, grouping accounts by email address.
2025-10-10 10:12:25 -04:00
Mike Dalessio 2d327e6294 Render a helpful menu of tenants temporarily 2025-10-02 16:33:25 -04:00
Jorge Manrubia 2e4138b585 Tie etag to sessions
So that we don't get CSRF token issues if sharing sessions in the same browser
2025-09-15 16:31:01 +02:00
Mike Dalessio 5540b0fd1b Make sure session cookie has the correct path for the tenant
ref: https://fizzy.37signals.com/5986089/collections/7/cards/1234
2025-08-10 18:53:52 -04:00
Mike Dalessio 57269b1b9c Allow local authentication with LOCAL_AUTHENTICATION=1
You can touch `tmp/local-auth.txt` to persist this setting.
2025-08-06 17:05:35 -04:00
Mike Dalessio 8e13ce5b78 Drop Current.account and just use Account.sole
I had reintroduced this in dacb53b8 after David removed it in
6bbf68a4, but now I agree we don't need it.

Also, fix a CORS error when trying to redirect a user to an untenanted
path after login (see
https://fizzy.37signals.com/5986089/collections/2/cards/1032).
2025-07-20 13:00:09 -04:00