From 3a29ecc7b3f39c32c5df63da686183fddae5ee97 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Mon, 15 Jul 2024 16:41:50 -0500 Subject: [PATCH 01/14] add poc for sso --- Gemfile | 3 + Gemfile.lock | 2 + .../actions/subscription_controller.rb | 2 +- .../relationships/billings_controller.rb | 2 +- .../relationships/plans_controller.rb | 2 +- app/controllers/api/v1/accounts_controller.rb | 2 +- .../v1/analytics/actions/counts_controller.rb | 2 +- .../api/v1/entitlements_controller.rb | 2 +- .../relationships/tokens_controller.rb | 2 +- .../api/v1/environments_controller.rb | 2 +- .../api/v1/event_logs_controller.rb | 2 +- .../relationships/group_owners_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../relationships/machines_controller.rb | 2 +- .../groups/relationships/users_controller.rb | 2 +- app/controllers/api/v1/groups_controller.rb | 2 +- .../keys/relationships/policies_controller.rb | 2 +- .../keys/relationships/products_controller.rb | 2 +- app/controllers/api/v1/keys_controller.rb | 2 +- .../licenses/actions/checkouts_controller.rb | 2 +- .../v1/licenses/actions/permits_controller.rb | 2 +- .../v1/licenses/actions/uses_controller.rb | 2 +- .../actions/validations_controller.rb | 4 +- .../relationships/entitlements_controller.rb | 2 +- .../relationships/groups_controller.rb | 2 +- .../relationships/machines_controller.rb | 2 +- .../relationships/owners_controller.rb | 2 +- .../relationships/policies_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- .../relationships/tokens_controller.rb | 2 +- .../relationships/users_controller.rb | 2 +- .../relationships/v1x5/users_controller.rb | 2 +- app/controllers/api/v1/licenses_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../relationships/machines_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- .../api/v1/machine_components_controller.rb | 2 +- .../actions/heartbeats_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../relationships/machines_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- .../api/v1/machine_processes_controller.rb | 2 +- .../machines/actions/checkouts_controller.rb | 2 +- .../machines/actions/heartbeats_controller.rb | 2 +- .../actions/v1x0/proofs_controller.rb | 2 +- .../relationships/groups_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../machine_components_controller.rb | 2 +- .../machine_processes_controller.rb | 2 +- .../relationships/owners_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- .../relationships/v1x5/users_controller.rb | 2 +- app/controllers/api/v1/machines_controller.rb | 2 +- .../v1/metrics/actions/counts_controller.rb | 2 +- app/controllers/api/v1/metrics_controller.rb | 2 +- .../relationships/entitlements_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../policies/relationships/pool_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- app/controllers/api/v1/policies_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../relationships/machines_controller.rb | 2 +- .../relationships/policies_controller.rb | 2 +- .../release_arches_controller.rb | 2 +- .../release_artifacts_controller.rb | 2 +- .../release_channels_controller.rb | 2 +- .../release_engines_controller.rb | 2 +- .../release_packages_controller.rb | 2 +- .../release_platforms_controller.rb | 2 +- .../relationships/releases_controller.rb | 2 +- .../relationships/tokens_controller.rb | 2 +- .../relationships/users_controller.rb | 2 +- app/controllers/api/v1/products_controller.rb | 2 +- app/controllers/api/v1/profiles_controller.rb | 2 +- .../api/v1/release_arches_controller.rb | 2 +- .../api/v1/release_artifacts_controller.rb | 4 +- .../api/v1/release_channels_controller.rb | 2 +- .../release_engines/pypi/simple_controller.rb | 2 +- .../tauri/upgrades_controller.rb | 2 +- .../api/v1/release_engines_controller.rb | 2 +- .../api/v1/release_packages_controller.rb | 4 +- .../api/v1/release_platforms_controller.rb | 2 +- .../actions/publishings_controller.rb | 2 +- .../actions/v1x0/upgrades_controller.rb | 2 +- .../relationships/entitlements_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- .../release_artifacts_controller.rb | 4 +- ...ease_entitlement_constraints_controller.rb | 2 +- .../release_packages_controller.rb | 4 +- .../relationships/upgrades_controller.rb | 2 +- .../v1x0/release_artifacts_controller.rb | 4 +- app/controllers/api/v1/releases_controller.rb | 4 +- .../request_logs/actions/counts_controller.rb | 2 +- .../api/v1/request_logs_controller.rb | 2 +- app/controllers/api/v1/searches_controller.rb | 2 +- app/controllers/api/v1/tokens_controller.rb | 7 +- .../api/v1/users/actions/bans_controller.rb | 2 +- .../v1/users/actions/password_controller.rb | 2 +- .../users/relationships/groups_controller.rb | 2 +- .../relationships/licenses_controller.rb | 2 +- .../relationships/machines_controller.rb | 2 +- .../relationships/products_controller.rb | 2 +- .../second_factors_controller.rb | 2 +- .../users/relationships/tokens_controller.rb | 2 +- app/controllers/api/v1/users_controller.rb | 4 +- .../api/v1/webhook_endpoints_controller.rb | 2 +- .../actions/retries_controller.rb | 2 +- .../api/v1/webhook_events_controller.rb | 2 +- app/controllers/application_controller.rb | 9 +- app/controllers/auth/sso_controller.rb | 49 ++++++++++ app/controllers/concerns/authentication.rb | 93 +++++++++++++++---- app/models/account.rb | 2 + app/models/user.rb | 2 + app/services/resolve_account_service.rb | 3 +- config/application.rb | 14 +++ config/initializers/workos.rb | 8 ++ config/initializers/zietwork.rb | 9 +- config/routes.rb | 36 ++++++- ...229_add_sso_organization_id_to_accounts.rb | 8 ++ ...40715164737_add_sso_profile_id_to_users.rb | 8 ++ .../20240715174443_add_sso_idp_id_to_users.rb | 8 ++ ...240715210732_add_session_nonce_to_users.rb | 5 + db/schema.rb | 7 ++ lib/keygen/error.rb | 26 +++++- spec/lib/union_of_spec.rb | 8 +- 125 files changed, 386 insertions(+), 147 deletions(-) create mode 100644 app/controllers/auth/sso_controller.rb create mode 100644 config/initializers/workos.rb create mode 100644 db/migrate/20240712202229_add_sso_organization_id_to_accounts.rb create mode 100644 db/migrate/20240715164737_add_sso_profile_id_to_users.rb create mode 100644 db/migrate/20240715174443_add_sso_idp_id_to_users.rb create mode 100644 db/migrate/20240715210732_add_session_nonce_to_users.rb diff --git a/Gemfile b/Gemfile index 7e64ac5a6a..abe7e80d49 100644 --- a/Gemfile +++ b/Gemfile @@ -45,6 +45,9 @@ gem 'jwt' # 2FA/TOTP gem 'rotp', '~> 6.2' +# SSO +gem 'workos' + # Scopes and pagination gem 'has_scope' gem 'kaminari', '~> 1.2.0' diff --git a/Gemfile.lock b/Gemfile.lock index ebae0cf271..d853b3bb30 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -500,6 +500,7 @@ GEM websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + workos (5.2.1) xpath (3.2.0) nokogiri (~> 1.8) zeitwerk (2.6.15) @@ -579,6 +580,7 @@ DEPENDENCIES typed_params (~> 1.2.5) uri (>= 0.12.2) webmock (~> 3.14.0) + workos RUBY VERSION ruby 3.3.4p94 diff --git a/app/controllers/api/v1/accounts/actions/subscription_controller.rb b/app/controllers/api/v1/accounts/actions/subscription_controller.rb index 6e43674078..b850b5eaca 100644 --- a/app/controllers/api/v1/accounts/actions/subscription_controller.rb +++ b/app/controllers/api/v1/accounts/actions/subscription_controller.rb @@ -3,7 +3,7 @@ module Api::V1::Accounts::Actions class SubscriptionController < Api::V1::BaseController before_action :scope_to_current_account! - before_action :authenticate_with_token! + before_action :authenticate! def manage authorize! with: Accounts::SubscriptionPolicy diff --git a/app/controllers/api/v1/accounts/relationships/billings_controller.rb b/app/controllers/api/v1/accounts/relationships/billings_controller.rb index ac2183d88d..dd96fa8c00 100644 --- a/app/controllers/api/v1/accounts/relationships/billings_controller.rb +++ b/app/controllers/api/v1/accounts/relationships/billings_controller.rb @@ -3,7 +3,7 @@ module Api::V1::Accounts::Relationships class BillingsController < Api::V1::BaseController before_action :scope_to_current_account! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_billing def show diff --git a/app/controllers/api/v1/accounts/relationships/plans_controller.rb b/app/controllers/api/v1/accounts/relationships/plans_controller.rb index 54856a0a50..25e6e17b1e 100644 --- a/app/controllers/api/v1/accounts/relationships/plans_controller.rb +++ b/app/controllers/api/v1/accounts/relationships/plans_controller.rb @@ -3,7 +3,7 @@ module Api::V1::Accounts::Relationships class PlansController < Api::V1::BaseController before_action :scope_to_current_account! - before_action :authenticate_with_token! + before_action :authenticate! def show plan = current_account.plan diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index a9d751572d..5fb12ca254 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -3,7 +3,7 @@ module Api::V1 class AccountsController < Api::V1::BaseController before_action :scope_to_current_account!, only: %i[show update destroy] - before_action :authenticate_with_token!, only: %i[show update destroy] + before_action :authenticate!, only: %i[show update destroy] before_action :set_account, only: %i[show update destroy] def show diff --git a/app/controllers/api/v1/analytics/actions/counts_controller.rb b/app/controllers/api/v1/analytics/actions/counts_controller.rb index 1c5b9413df..4c06c939ec 100644 --- a/app/controllers/api/v1/analytics/actions/counts_controller.rb +++ b/app/controllers/api/v1/analytics/actions/counts_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Analytics::Actions class CountsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! def count authorize! to: :show?, with: Accounts::AnalyticsPolicy diff --git a/app/controllers/api/v1/entitlements_controller.rb b/app/controllers/api/v1/entitlements_controller.rb index f755a7ee9d..1984c0ab5d 100644 --- a/app/controllers/api/v1/entitlements_controller.rb +++ b/app/controllers/api/v1/entitlements_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class EntitlementsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_entitlement, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/environments/relationships/tokens_controller.rb b/app/controllers/api/v1/environments/relationships/tokens_controller.rb index 5b8b51da47..1498bbcfb5 100644 --- a/app/controllers/api/v1/environments/relationships/tokens_controller.rb +++ b/app/controllers/api/v1/environments/relationships/tokens_controller.rb @@ -5,7 +5,7 @@ class TokensController < Api::V1::BaseController before_action :require_ee! before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_environment def index diff --git a/app/controllers/api/v1/environments_controller.rb b/app/controllers/api/v1/environments_controller.rb index f1a0055841..3ed9498959 100644 --- a/app/controllers/api/v1/environments_controller.rb +++ b/app/controllers/api/v1/environments_controller.rb @@ -5,7 +5,7 @@ class EnvironmentsController < Api::V1::BaseController before_action :require_ee! before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_environment, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/event_logs_controller.rb b/app/controllers/api/v1/event_logs_controller.rb index 8726a291e8..3a54bc9a5b 100644 --- a/app/controllers/api/v1/event_logs_controller.rb +++ b/app/controllers/api/v1/event_logs_controller.rb @@ -12,7 +12,7 @@ class EventLogsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! before_action :require_ent_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_event_log, only: %i[show] def index diff --git a/app/controllers/api/v1/groups/relationships/group_owners_controller.rb b/app/controllers/api/v1/groups/relationships/group_owners_controller.rb index 0a1bfc642f..845fc78433 100644 --- a/app/controllers/api/v1/groups/relationships/group_owners_controller.rb +++ b/app/controllers/api/v1/groups/relationships/group_owners_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Groups::Relationships class GroupOwnersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_group authorize :group diff --git a/app/controllers/api/v1/groups/relationships/licenses_controller.rb b/app/controllers/api/v1/groups/relationships/licenses_controller.rb index caa67d7493..76c2c902b8 100644 --- a/app/controllers/api/v1/groups/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/groups/relationships/licenses_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Groups::Relationships class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_group authorize :group diff --git a/app/controllers/api/v1/groups/relationships/machines_controller.rb b/app/controllers/api/v1/groups/relationships/machines_controller.rb index 9d2d11adbd..1151b8c691 100644 --- a/app/controllers/api/v1/groups/relationships/machines_controller.rb +++ b/app/controllers/api/v1/groups/relationships/machines_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Groups::Relationships class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_group authorize :group diff --git a/app/controllers/api/v1/groups/relationships/users_controller.rb b/app/controllers/api/v1/groups/relationships/users_controller.rb index b82121afe7..232f33ae9e 100644 --- a/app/controllers/api/v1/groups/relationships/users_controller.rb +++ b/app/controllers/api/v1/groups/relationships/users_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Groups::Relationships class UsersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_group authorize :group diff --git a/app/controllers/api/v1/groups_controller.rb b/app/controllers/api/v1/groups_controller.rb index 14d57557c6..5d805fc763 100644 --- a/app/controllers/api/v1/groups_controller.rb +++ b/app/controllers/api/v1/groups_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class GroupsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_group, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/keys/relationships/policies_controller.rb b/app/controllers/api/v1/keys/relationships/policies_controller.rb index 04cd9f16ac..18ded4693f 100644 --- a/app/controllers/api/v1/keys/relationships/policies_controller.rb +++ b/app/controllers/api/v1/keys/relationships/policies_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Keys::Relationships class PoliciesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_key authorize :key diff --git a/app/controllers/api/v1/keys/relationships/products_controller.rb b/app/controllers/api/v1/keys/relationships/products_controller.rb index b58f6a8d5d..daf14a1667 100644 --- a/app/controllers/api/v1/keys/relationships/products_controller.rb +++ b/app/controllers/api/v1/keys/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Keys::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_key authorize :key diff --git a/app/controllers/api/v1/keys_controller.rb b/app/controllers/api/v1/keys_controller.rb index 0e91c061c7..636311fb95 100644 --- a/app/controllers/api/v1/keys_controller.rb +++ b/app/controllers/api/v1/keys_controller.rb @@ -7,7 +7,7 @@ class KeysController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_key, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/licenses/actions/checkouts_controller.rb b/app/controllers/api/v1/licenses/actions/checkouts_controller.rb index 90ccaa4e6e..2fcc50b86f 100644 --- a/app/controllers/api/v1/licenses/actions/checkouts_controller.rb +++ b/app/controllers/api/v1/licenses/actions/checkouts_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Actions class CheckoutsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/actions/permits_controller.rb b/app/controllers/api/v1/licenses/actions/permits_controller.rb index 4062dcb9a5..ca15628318 100644 --- a/app/controllers/api/v1/licenses/actions/permits_controller.rb +++ b/app/controllers/api/v1/licenses/actions/permits_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Actions class PermitsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license def check_in diff --git a/app/controllers/api/v1/licenses/actions/uses_controller.rb b/app/controllers/api/v1/licenses/actions/uses_controller.rb index 4eb7a468c5..17b64ac1e7 100644 --- a/app/controllers/api/v1/licenses/actions/uses_controller.rb +++ b/app/controllers/api/v1/licenses/actions/uses_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Actions class UsesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/actions/validations_controller.rb b/app/controllers/api/v1/licenses/actions/validations_controller.rb index f65ae973a6..f92219526a 100644 --- a/app/controllers/api/v1/licenses/actions/validations_controller.rb +++ b/app/controllers/api/v1/licenses/actions/validations_controller.rb @@ -4,8 +4,8 @@ module Api::V1::Licenses::Actions class ValidationsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[validate_by_key] - before_action :authenticate_with_token, only: %i[validate_by_key] + before_action :authenticate!, except: %i[validate_by_key] + before_action :authenticate, only: %i[validate_by_key] before_action :set_license, only: %i[quick_validate_by_id validate_by_id] def quick_validate_by_id diff --git a/app/controllers/api/v1/licenses/relationships/entitlements_controller.rb b/app/controllers/api/v1/licenses/relationships/entitlements_controller.rb index 8f2294369a..9e55771fcd 100644 --- a/app/controllers/api/v1/licenses/relationships/entitlements_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/entitlements_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class EntitlementsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/groups_controller.rb b/app/controllers/api/v1/licenses/relationships/groups_controller.rb index f499926730..5b644771ac 100644 --- a/app/controllers/api/v1/licenses/relationships/groups_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/groups_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class GroupsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/machines_controller.rb b/app/controllers/api/v1/licenses/relationships/machines_controller.rb index 99d7dc0125..6ebb45e799 100644 --- a/app/controllers/api/v1/licenses/relationships/machines_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/machines_controller.rb @@ -8,7 +8,7 @@ class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/owners_controller.rb b/app/controllers/api/v1/licenses/relationships/owners_controller.rb index 763f0c12b0..e32d519960 100644 --- a/app/controllers/api/v1/licenses/relationships/owners_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/owners_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class OwnersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/policies_controller.rb b/app/controllers/api/v1/licenses/relationships/policies_controller.rb index 88c3c9e5af..4b98cb0b5b 100644 --- a/app/controllers/api/v1/licenses/relationships/policies_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/policies_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class PoliciesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/products_controller.rb b/app/controllers/api/v1/licenses/relationships/products_controller.rb index 5c2719caf1..cb2ee0c76b 100644 --- a/app/controllers/api/v1/licenses/relationships/products_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/tokens_controller.rb b/app/controllers/api/v1/licenses/relationships/tokens_controller.rb index 9ce82fb78f..78297c45a2 100644 --- a/app/controllers/api/v1/licenses/relationships/tokens_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/tokens_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class TokensController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/users_controller.rb b/app/controllers/api/v1/licenses/relationships/users_controller.rb index 15bb0b8214..70cf9bdade 100644 --- a/app/controllers/api/v1/licenses/relationships/users_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/users_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships class UsersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses/relationships/v1x5/users_controller.rb b/app/controllers/api/v1/licenses/relationships/v1x5/users_controller.rb index 906bd973ca..09538929de 100644 --- a/app/controllers/api/v1/licenses/relationships/v1x5/users_controller.rb +++ b/app/controllers/api/v1/licenses/relationships/v1x5/users_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Licenses::Relationships::V1x5 class UsersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license authorize :license diff --git a/app/controllers/api/v1/licenses_controller.rb b/app/controllers/api/v1/licenses_controller.rb index 9a525865bf..1a698932c4 100644 --- a/app/controllers/api/v1/licenses_controller.rb +++ b/app/controllers/api/v1/licenses_controller.rb @@ -25,7 +25,7 @@ class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_license, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/machine_components/relationships/licenses_controller.rb b/app/controllers/api/v1/machine_components/relationships/licenses_controller.rb index 9eccc4945e..3271817c6f 100644 --- a/app/controllers/api/v1/machine_components/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/machine_components/relationships/licenses_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineComponents::Relationships class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_component authorize :machine_component diff --git a/app/controllers/api/v1/machine_components/relationships/machines_controller.rb b/app/controllers/api/v1/machine_components/relationships/machines_controller.rb index 255e960965..9565473cb3 100644 --- a/app/controllers/api/v1/machine_components/relationships/machines_controller.rb +++ b/app/controllers/api/v1/machine_components/relationships/machines_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineComponents::Relationships class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_component authorize :machine_component diff --git a/app/controllers/api/v1/machine_components/relationships/products_controller.rb b/app/controllers/api/v1/machine_components/relationships/products_controller.rb index 9cffa96b39..12442bc8a1 100644 --- a/app/controllers/api/v1/machine_components/relationships/products_controller.rb +++ b/app/controllers/api/v1/machine_components/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineComponents::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_component authorize :machine_component diff --git a/app/controllers/api/v1/machine_components_controller.rb b/app/controllers/api/v1/machine_components_controller.rb index 1ab2516c65..5b0bbc6f5b 100644 --- a/app/controllers/api/v1/machine_components_controller.rb +++ b/app/controllers/api/v1/machine_components_controller.rb @@ -10,7 +10,7 @@ class MachineComponentsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_component, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/machine_processes/actions/heartbeats_controller.rb b/app/controllers/api/v1/machine_processes/actions/heartbeats_controller.rb index 0cc376d33e..41f1d141de 100644 --- a/app/controllers/api/v1/machine_processes/actions/heartbeats_controller.rb +++ b/app/controllers/api/v1/machine_processes/actions/heartbeats_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineProcesses::Actions class HeartbeatsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_process authorize :machine_process diff --git a/app/controllers/api/v1/machine_processes/relationships/licenses_controller.rb b/app/controllers/api/v1/machine_processes/relationships/licenses_controller.rb index 7bfecd25d5..1134d88bb0 100644 --- a/app/controllers/api/v1/machine_processes/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/machine_processes/relationships/licenses_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineProcesses::Relationships class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_process authorize :machine_process diff --git a/app/controllers/api/v1/machine_processes/relationships/machines_controller.rb b/app/controllers/api/v1/machine_processes/relationships/machines_controller.rb index 6433a3ae92..7b3910debe 100644 --- a/app/controllers/api/v1/machine_processes/relationships/machines_controller.rb +++ b/app/controllers/api/v1/machine_processes/relationships/machines_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineProcesses::Relationships class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_process authorize :machine_process diff --git a/app/controllers/api/v1/machine_processes/relationships/products_controller.rb b/app/controllers/api/v1/machine_processes/relationships/products_controller.rb index c73c4bfd1c..3fa4757a20 100644 --- a/app/controllers/api/v1/machine_processes/relationships/products_controller.rb +++ b/app/controllers/api/v1/machine_processes/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::MachineProcesses::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_process authorize :machine_process diff --git a/app/controllers/api/v1/machine_processes_controller.rb b/app/controllers/api/v1/machine_processes_controller.rb index c5aa7934c8..0a7e1057fc 100644 --- a/app/controllers/api/v1/machine_processes_controller.rb +++ b/app/controllers/api/v1/machine_processes_controller.rb @@ -11,7 +11,7 @@ class MachineProcessesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine_process, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/machines/actions/checkouts_controller.rb b/app/controllers/api/v1/machines/actions/checkouts_controller.rb index 461ea32f22..bc32e520e9 100644 --- a/app/controllers/api/v1/machines/actions/checkouts_controller.rb +++ b/app/controllers/api/v1/machines/actions/checkouts_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Actions class CheckoutsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/actions/heartbeats_controller.rb b/app/controllers/api/v1/machines/actions/heartbeats_controller.rb index 0c6fe53425..bc7be2d0d0 100644 --- a/app/controllers/api/v1/machines/actions/heartbeats_controller.rb +++ b/app/controllers/api/v1/machines/actions/heartbeats_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Actions class HeartbeatsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/actions/v1x0/proofs_controller.rb b/app/controllers/api/v1/machines/actions/v1x0/proofs_controller.rb index 2fcb807cc5..7e0ab632b1 100644 --- a/app/controllers/api/v1/machines/actions/v1x0/proofs_controller.rb +++ b/app/controllers/api/v1/machines/actions/v1x0/proofs_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Actions::V1x0 class ProofsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/groups_controller.rb b/app/controllers/api/v1/machines/relationships/groups_controller.rb index 499e97243f..4dfe10c2b9 100644 --- a/app/controllers/api/v1/machines/relationships/groups_controller.rb +++ b/app/controllers/api/v1/machines/relationships/groups_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Relationships class GroupsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/licenses_controller.rb b/app/controllers/api/v1/machines/relationships/licenses_controller.rb index 9a2b7a0c7d..8f04046755 100644 --- a/app/controllers/api/v1/machines/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/machines/relationships/licenses_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Relationships class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/machine_components_controller.rb b/app/controllers/api/v1/machines/relationships/machine_components_controller.rb index f5e94f646a..fc49eb7ea3 100644 --- a/app/controllers/api/v1/machines/relationships/machine_components_controller.rb +++ b/app/controllers/api/v1/machines/relationships/machine_components_controller.rb @@ -6,7 +6,7 @@ class MachineComponentsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/machine_processes_controller.rb b/app/controllers/api/v1/machines/relationships/machine_processes_controller.rb index d8ec053045..3106a5017e 100644 --- a/app/controllers/api/v1/machines/relationships/machine_processes_controller.rb +++ b/app/controllers/api/v1/machines/relationships/machine_processes_controller.rb @@ -6,7 +6,7 @@ class MachineProcessesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/owners_controller.rb b/app/controllers/api/v1/machines/relationships/owners_controller.rb index 39f5e28364..c3a8eaf783 100644 --- a/app/controllers/api/v1/machines/relationships/owners_controller.rb +++ b/app/controllers/api/v1/machines/relationships/owners_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Relationships class OwnersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/products_controller.rb b/app/controllers/api/v1/machines/relationships/products_controller.rb index 18cc688e3c..f00cd7a44d 100644 --- a/app/controllers/api/v1/machines/relationships/products_controller.rb +++ b/app/controllers/api/v1/machines/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines/relationships/v1x5/users_controller.rb b/app/controllers/api/v1/machines/relationships/v1x5/users_controller.rb index 66bbeab709..0691de9e3d 100644 --- a/app/controllers/api/v1/machines/relationships/v1x5/users_controller.rb +++ b/app/controllers/api/v1/machines/relationships/v1x5/users_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Machines::Relationships::V1x5 class UsersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine authorize :machine diff --git a/app/controllers/api/v1/machines_controller.rb b/app/controllers/api/v1/machines_controller.rb index 836481f2de..a926178625 100644 --- a/app/controllers/api/v1/machines_controller.rb +++ b/app/controllers/api/v1/machines_controller.rb @@ -17,7 +17,7 @@ class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_machine, only: [:show, :update, :destroy] def index diff --git a/app/controllers/api/v1/metrics/actions/counts_controller.rb b/app/controllers/api/v1/metrics/actions/counts_controller.rb index 0742058ca1..022d08d88a 100644 --- a/app/controllers/api/v1/metrics/actions/counts_controller.rb +++ b/app/controllers/api/v1/metrics/actions/counts_controller.rb @@ -6,7 +6,7 @@ class CountsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! def count authorize! with: MetricPolicy diff --git a/app/controllers/api/v1/metrics_controller.rb b/app/controllers/api/v1/metrics_controller.rb index 76464061af..bf25bad7f1 100644 --- a/app/controllers/api/v1/metrics_controller.rb +++ b/app/controllers/api/v1/metrics_controller.rb @@ -8,7 +8,7 @@ class MetricsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_metric, only: %i[show] def index diff --git a/app/controllers/api/v1/policies/relationships/entitlements_controller.rb b/app/controllers/api/v1/policies/relationships/entitlements_controller.rb index 9336c3980a..ebcb5bf1e5 100644 --- a/app/controllers/api/v1/policies/relationships/entitlements_controller.rb +++ b/app/controllers/api/v1/policies/relationships/entitlements_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Policies::Relationships class EntitlementsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_policy authorize :policy diff --git a/app/controllers/api/v1/policies/relationships/licenses_controller.rb b/app/controllers/api/v1/policies/relationships/licenses_controller.rb index bceccf4567..9e2105add5 100644 --- a/app/controllers/api/v1/policies/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/policies/relationships/licenses_controller.rb @@ -8,7 +8,7 @@ class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_policy authorize :policy diff --git a/app/controllers/api/v1/policies/relationships/pool_controller.rb b/app/controllers/api/v1/policies/relationships/pool_controller.rb index 999356d20e..694fb0b82e 100644 --- a/app/controllers/api/v1/policies/relationships/pool_controller.rb +++ b/app/controllers/api/v1/policies/relationships/pool_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Policies::Relationships class PoolController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_policy, only: %i[index show pop] authorize :policy diff --git a/app/controllers/api/v1/policies/relationships/products_controller.rb b/app/controllers/api/v1/policies/relationships/products_controller.rb index b0c8b92095..63fd815bb1 100644 --- a/app/controllers/api/v1/policies/relationships/products_controller.rb +++ b/app/controllers/api/v1/policies/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Policies::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_policy authorize :policy diff --git a/app/controllers/api/v1/policies_controller.rb b/app/controllers/api/v1/policies_controller.rb index ad53db1ff9..aef8fbabe5 100644 --- a/app/controllers/api/v1/policies_controller.rb +++ b/app/controllers/api/v1/policies_controller.rb @@ -6,7 +6,7 @@ class PoliciesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_policy, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/products/relationships/licenses_controller.rb b/app/controllers/api/v1/products/relationships/licenses_controller.rb index 4d45d20417..95b6766c55 100644 --- a/app/controllers/api/v1/products/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/products/relationships/licenses_controller.rb @@ -8,7 +8,7 @@ class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/machines_controller.rb b/app/controllers/api/v1/products/relationships/machines_controller.rb index 2fe37c2364..dcbff9fe9d 100644 --- a/app/controllers/api/v1/products/relationships/machines_controller.rb +++ b/app/controllers/api/v1/products/relationships/machines_controller.rb @@ -8,7 +8,7 @@ class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/policies_controller.rb b/app/controllers/api/v1/products/relationships/policies_controller.rb index 1f47fa735e..3df1bd20f5 100644 --- a/app/controllers/api/v1/products/relationships/policies_controller.rb +++ b/app/controllers/api/v1/products/relationships/policies_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Products::Relationships class PoliciesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/release_arches_controller.rb b/app/controllers/api/v1/products/relationships/release_arches_controller.rb index 050e98f652..054fe6ec74 100644 --- a/app/controllers/api/v1/products/relationships/release_arches_controller.rb +++ b/app/controllers/api/v1/products/relationships/release_arches_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Products::Relationships class ReleaseArchesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/release_artifacts_controller.rb b/app/controllers/api/v1/products/relationships/release_artifacts_controller.rb index 108bd58761..54671b7991 100644 --- a/app/controllers/api/v1/products/relationships/release_artifacts_controller.rb +++ b/app/controllers/api/v1/products/relationships/release_artifacts_controller.rb @@ -12,7 +12,7 @@ class ReleaseArtifactsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product, only: %i[index show] before_action :set_artifact, only: %i[show] diff --git a/app/controllers/api/v1/products/relationships/release_channels_controller.rb b/app/controllers/api/v1/products/relationships/release_channels_controller.rb index 40c0accae7..c3a6aba38c 100644 --- a/app/controllers/api/v1/products/relationships/release_channels_controller.rb +++ b/app/controllers/api/v1/products/relationships/release_channels_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Products::Relationships class ReleaseChannelsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/release_engines_controller.rb b/app/controllers/api/v1/products/relationships/release_engines_controller.rb index 7eacfabe8a..f64aea1d0c 100644 --- a/app/controllers/api/v1/products/relationships/release_engines_controller.rb +++ b/app/controllers/api/v1/products/relationships/release_engines_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Products::Relationships class ReleaseEnginesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/release_packages_controller.rb b/app/controllers/api/v1/products/relationships/release_packages_controller.rb index 66015b4b2f..0a531784e1 100644 --- a/app/controllers/api/v1/products/relationships/release_packages_controller.rb +++ b/app/controllers/api/v1/products/relationships/release_packages_controller.rb @@ -6,7 +6,7 @@ class ReleasePackagesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/release_platforms_controller.rb b/app/controllers/api/v1/products/relationships/release_platforms_controller.rb index 833dcd47c5..411f821397 100644 --- a/app/controllers/api/v1/products/relationships/release_platforms_controller.rb +++ b/app/controllers/api/v1/products/relationships/release_platforms_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Products::Relationships class ReleasePlatformsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/releases_controller.rb b/app/controllers/api/v1/products/relationships/releases_controller.rb index 75762996b9..3ccb310c5c 100644 --- a/app/controllers/api/v1/products/relationships/releases_controller.rb +++ b/app/controllers/api/v1/products/relationships/releases_controller.rb @@ -16,7 +16,7 @@ class ReleasesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/tokens_controller.rb b/app/controllers/api/v1/products/relationships/tokens_controller.rb index 272b268a34..c987b678bd 100644 --- a/app/controllers/api/v1/products/relationships/tokens_controller.rb +++ b/app/controllers/api/v1/products/relationships/tokens_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Products::Relationships class TokensController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products/relationships/users_controller.rb b/app/controllers/api/v1/products/relationships/users_controller.rb index ed3c3b00cf..5d74b3544a 100644 --- a/app/controllers/api/v1/products/relationships/users_controller.rb +++ b/app/controllers/api/v1/products/relationships/users_controller.rb @@ -6,7 +6,7 @@ class UsersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product authorize :product diff --git a/app/controllers/api/v1/products_controller.rb b/app/controllers/api/v1/products_controller.rb index 9382eea5f6..e0f29bbf06 100644 --- a/app/controllers/api/v1/products_controller.rb +++ b/app/controllers/api/v1/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_product, only: [:show, :update, :destroy] def index diff --git a/app/controllers/api/v1/profiles_controller.rb b/app/controllers/api/v1/profiles_controller.rb index 53d8f7c654..26e8f4da4f 100644 --- a/app/controllers/api/v1/profiles_controller.rb +++ b/app/controllers/api/v1/profiles_controller.rb @@ -3,7 +3,7 @@ module Api::V1 class ProfilesController < Api::V1::BaseController before_action :scope_to_current_account! - before_action :authenticate_with_token! + before_action :authenticate! def show authorize! current_bearer diff --git a/app/controllers/api/v1/release_arches_controller.rb b/app/controllers/api/v1/release_arches_controller.rb index daff8b1fce..f438ba89f4 100644 --- a/app/controllers/api/v1/release_arches_controller.rb +++ b/app/controllers/api/v1/release_arches_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class ReleaseArchesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_arch, only: %i[show] def index diff --git a/app/controllers/api/v1/release_artifacts_controller.rb b/app/controllers/api/v1/release_artifacts_controller.rb index 97d8f4ea8c..54e3e2a777 100644 --- a/app/controllers/api/v1/release_artifacts_controller.rb +++ b/app/controllers/api/v1/release_artifacts_controller.rb @@ -14,8 +14,8 @@ class ReleaseArtifactsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[index show] - before_action :authenticate_with_token, only: %i[index show] + before_action :authenticate!, except: %i[index show] + before_action :authenticate, only: %i[index show] before_action :set_artifact, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/release_channels_controller.rb b/app/controllers/api/v1/release_channels_controller.rb index ad9b1fc637..cf147ee93f 100644 --- a/app/controllers/api/v1/release_channels_controller.rb +++ b/app/controllers/api/v1/release_channels_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class ReleaseChannelsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_channel, only: %i[show] def index diff --git a/app/controllers/api/v1/release_engines/pypi/simple_controller.rb b/app/controllers/api/v1/release_engines/pypi/simple_controller.rb index 9fb34399de..524acfc482 100644 --- a/app/controllers/api/v1/release_engines/pypi/simple_controller.rb +++ b/app/controllers/api/v1/release_engines/pypi/simple_controller.rb @@ -6,7 +6,7 @@ class Pypi::SimpleController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_package, only: %i[show] def index diff --git a/app/controllers/api/v1/release_engines/tauri/upgrades_controller.rb b/app/controllers/api/v1/release_engines/tauri/upgrades_controller.rb index bf0c77c653..e30a818d57 100644 --- a/app/controllers/api/v1/release_engines/tauri/upgrades_controller.rb +++ b/app/controllers/api/v1/release_engines/tauri/upgrades_controller.rb @@ -4,7 +4,7 @@ module Api::V1::ReleaseEngines class Tauri::UpgradesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_package, only: %i[show] typed_query { diff --git a/app/controllers/api/v1/release_engines_controller.rb b/app/controllers/api/v1/release_engines_controller.rb index 3f4960aaf2..c6127a5e0a 100644 --- a/app/controllers/api/v1/release_engines_controller.rb +++ b/app/controllers/api/v1/release_engines_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class ReleaseEnginesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_engine, only: %i[show] def index diff --git a/app/controllers/api/v1/release_packages_controller.rb b/app/controllers/api/v1/release_packages_controller.rb index c7ab49af28..1abe62ee48 100644 --- a/app/controllers/api/v1/release_packages_controller.rb +++ b/app/controllers/api/v1/release_packages_controller.rb @@ -7,8 +7,8 @@ class ReleasePackagesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[index show] - before_action :authenticate_with_token, only: %i[index show] + before_action :authenticate!, except: %i[index show] + before_action :authenticate, only: %i[index show] before_action :set_package, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/release_platforms_controller.rb b/app/controllers/api/v1/release_platforms_controller.rb index 4ab020ff55..f89d192640 100644 --- a/app/controllers/api/v1/release_platforms_controller.rb +++ b/app/controllers/api/v1/release_platforms_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class ReleasePlatformsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_platform, only: %i[show] def index diff --git a/app/controllers/api/v1/releases/actions/publishings_controller.rb b/app/controllers/api/v1/releases/actions/publishings_controller.rb index c2935137b1..1483ea40eb 100644 --- a/app/controllers/api/v1/releases/actions/publishings_controller.rb +++ b/app/controllers/api/v1/releases/actions/publishings_controller.rb @@ -2,7 +2,7 @@ module Api::V1::Releases::Actions class PublishingsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_release def publish diff --git a/app/controllers/api/v1/releases/actions/v1x0/upgrades_controller.rb b/app/controllers/api/v1/releases/actions/v1x0/upgrades_controller.rb index 7a461e8b1a..f6f095f217 100644 --- a/app/controllers/api/v1/releases/actions/v1x0/upgrades_controller.rb +++ b/app/controllers/api/v1/releases/actions/v1x0/upgrades_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Releases::Actions::V1x0 class UpgradesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_release, only: %i[check_for_upgrade_by_id] skip_verify_authorized only: %i[ diff --git a/app/controllers/api/v1/releases/relationships/entitlements_controller.rb b/app/controllers/api/v1/releases/relationships/entitlements_controller.rb index 4322b6d1a1..494f25f03b 100644 --- a/app/controllers/api/v1/releases/relationships/entitlements_controller.rb +++ b/app/controllers/api/v1/releases/relationships/entitlements_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Releases::Relationships class EntitlementsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_release authorize :release diff --git a/app/controllers/api/v1/releases/relationships/products_controller.rb b/app/controllers/api/v1/releases/relationships/products_controller.rb index 7f6c638045..4ed6cd9ca1 100644 --- a/app/controllers/api/v1/releases/relationships/products_controller.rb +++ b/app/controllers/api/v1/releases/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Releases::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_release authorize :release diff --git a/app/controllers/api/v1/releases/relationships/release_artifacts_controller.rb b/app/controllers/api/v1/releases/relationships/release_artifacts_controller.rb index 72cd9be810..4c54f7ace0 100644 --- a/app/controllers/api/v1/releases/relationships/release_artifacts_controller.rb +++ b/app/controllers/api/v1/releases/relationships/release_artifacts_controller.rb @@ -9,8 +9,8 @@ class ReleaseArtifactsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[index show] - before_action :authenticate_with_token, only: %i[index show] + before_action :authenticate!, except: %i[index show] + before_action :authenticate, only: %i[index show] before_action :set_release, only: %i[index show] before_action :set_artifact, only: %i[show] diff --git a/app/controllers/api/v1/releases/relationships/release_entitlement_constraints_controller.rb b/app/controllers/api/v1/releases/relationships/release_entitlement_constraints_controller.rb index 6edea9f982..0a2f45ae42 100644 --- a/app/controllers/api/v1/releases/relationships/release_entitlement_constraints_controller.rb +++ b/app/controllers/api/v1/releases/relationships/release_entitlement_constraints_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Releases::Relationships class ReleaseEntitlementConstraintsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_release authorize :release diff --git a/app/controllers/api/v1/releases/relationships/release_packages_controller.rb b/app/controllers/api/v1/releases/relationships/release_packages_controller.rb index 4a1a2caf70..00d7d81d2a 100644 --- a/app/controllers/api/v1/releases/relationships/release_packages_controller.rb +++ b/app/controllers/api/v1/releases/relationships/release_packages_controller.rb @@ -4,8 +4,8 @@ module Api::V1::Releases::Relationships class ReleasePackagesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[show] - before_action :authenticate_with_token, only: %i[show] + before_action :authenticate!, except: %i[show] + before_action :authenticate, only: %i[show] before_action :set_release authorize :release diff --git a/app/controllers/api/v1/releases/relationships/upgrades_controller.rb b/app/controllers/api/v1/releases/relationships/upgrades_controller.rb index c94ea14ac7..be11043698 100644 --- a/app/controllers/api/v1/releases/relationships/upgrades_controller.rb +++ b/app/controllers/api/v1/releases/relationships/upgrades_controller.rb @@ -7,7 +7,7 @@ class UpgradesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token + before_action :authenticate before_action :set_release typed_query { diff --git a/app/controllers/api/v1/releases/relationships/v1x0/release_artifacts_controller.rb b/app/controllers/api/v1/releases/relationships/v1x0/release_artifacts_controller.rb index 3981ebd748..68d5c7c630 100644 --- a/app/controllers/api/v1/releases/relationships/v1x0/release_artifacts_controller.rb +++ b/app/controllers/api/v1/releases/relationships/v1x0/release_artifacts_controller.rb @@ -4,8 +4,8 @@ module Api::V1::Releases::Relationships::V1x0 class ReleaseArtifactsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[show] - before_action :authenticate_with_token, only: %i[show] + before_action :authenticate!, except: %i[show] + before_action :authenticate, only: %i[show] before_action :set_release typed_query { diff --git a/app/controllers/api/v1/releases_controller.rb b/app/controllers/api/v1/releases_controller.rb index d7eea26d79..b3c2894486 100644 --- a/app/controllers/api/v1/releases_controller.rb +++ b/app/controllers/api/v1/releases_controller.rb @@ -20,8 +20,8 @@ class ReleasesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token!, except: %i[index show] - before_action :authenticate_with_token, only: %i[index show] + before_action :authenticate!, except: %i[index show] + before_action :authenticate, only: %i[index show] before_action :set_release, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/request_logs/actions/counts_controller.rb b/app/controllers/api/v1/request_logs/actions/counts_controller.rb index 6154bf4c4a..387edf210d 100644 --- a/app/controllers/api/v1/request_logs/actions/counts_controller.rb +++ b/app/controllers/api/v1/request_logs/actions/counts_controller.rb @@ -4,7 +4,7 @@ module Api::V1::RequestLogs::Actions class CountsController < Api::V1::BaseController before_action :require_ee! before_action :scope_to_current_account! - before_action :authenticate_with_token! + before_action :authenticate! def count authorize! with: RequestLogPolicy diff --git a/app/controllers/api/v1/request_logs_controller.rb b/app/controllers/api/v1/request_logs_controller.rb index c9438d3471..5d78364720 100644 --- a/app/controllers/api/v1/request_logs_controller.rb +++ b/app/controllers/api/v1/request_logs_controller.rb @@ -15,7 +15,7 @@ class RequestLogsController < Api::V1::BaseController before_action :require_ee! before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_request_log, only: [:show] def index diff --git a/app/controllers/api/v1/searches_controller.rb b/app/controllers/api/v1/searches_controller.rb index 9fbde72f83..f411c116d3 100644 --- a/app/controllers/api/v1/searches_controller.rb +++ b/app/controllers/api/v1/searches_controller.rb @@ -21,7 +21,7 @@ class EmptyQueryError < StandardError; end before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! typed_params { format :jsonapi diff --git a/app/controllers/api/v1/tokens_controller.rb b/app/controllers/api/v1/tokens_controller.rb index fa599191c7..e6db7d0681 100644 --- a/app/controllers/api/v1/tokens_controller.rb +++ b/app/controllers/api/v1/tokens_controller.rb @@ -10,7 +10,7 @@ class TokensController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription!, only: %i[index regenerate regenerate_current] before_action :authenticate_with_password_or_token!, only: %i[generate] - before_action :authenticate_with_token!, except: %i[generate] + before_action :authenticate!, except: %i[generate] before_action :set_token, only: %i[show regenerate revoke] def index @@ -64,7 +64,8 @@ def show end end param :meta, type: :hash, optional: true do - param :otp, type: :string + param :provider, type: :string, optional: true, inclusion: { in: %w[AppleOAuth GitHubOAuth GoogleOAUth MicrosoftOAuth] } + param :otp, type: :string, optional: true end } def generate @@ -93,8 +94,6 @@ def generate else render_unprocessable_resource token end - rescue ArgumentError # Catch null bytes (Postgres throws an argument error) - render_bad_request end # FIXME(ezekg) Deprecate this route. diff --git a/app/controllers/api/v1/users/actions/bans_controller.rb b/app/controllers/api/v1/users/actions/bans_controller.rb index f60eacef7c..8303a84e36 100644 --- a/app/controllers/api/v1/users/actions/bans_controller.rb +++ b/app/controllers/api/v1/users/actions/bans_controller.rb @@ -3,7 +3,7 @@ module Api::V1::Users::Actions class BansController < Api::V1::BaseController before_action :scope_to_current_account! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user def ban diff --git a/app/controllers/api/v1/users/actions/password_controller.rb b/app/controllers/api/v1/users/actions/password_controller.rb index 2ee21b3c4c..ae1a1b205e 100644 --- a/app/controllers/api/v1/users/actions/password_controller.rb +++ b/app/controllers/api/v1/users/actions/password_controller.rb @@ -3,7 +3,7 @@ module Api::V1::Users::Actions class PasswordController < Api::V1::BaseController before_action :scope_to_current_account! - before_action :authenticate_with_token!, only: %i[update] + before_action :authenticate!, only: %i[update] before_action :set_user, only: %i[update reset] authorize :user diff --git a/app/controllers/api/v1/users/relationships/groups_controller.rb b/app/controllers/api/v1/users/relationships/groups_controller.rb index 61acad3614..cd2e998c18 100644 --- a/app/controllers/api/v1/users/relationships/groups_controller.rb +++ b/app/controllers/api/v1/users/relationships/groups_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Users::Relationships class GroupsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user authorize :user diff --git a/app/controllers/api/v1/users/relationships/licenses_controller.rb b/app/controllers/api/v1/users/relationships/licenses_controller.rb index e225c6d2e1..09ccfb27d9 100644 --- a/app/controllers/api/v1/users/relationships/licenses_controller.rb +++ b/app/controllers/api/v1/users/relationships/licenses_controller.rb @@ -8,7 +8,7 @@ class LicensesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user authorize :user diff --git a/app/controllers/api/v1/users/relationships/machines_controller.rb b/app/controllers/api/v1/users/relationships/machines_controller.rb index 09f17a41e6..65ad0dcddb 100644 --- a/app/controllers/api/v1/users/relationships/machines_controller.rb +++ b/app/controllers/api/v1/users/relationships/machines_controller.rb @@ -8,7 +8,7 @@ class MachinesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user authorize :user diff --git a/app/controllers/api/v1/users/relationships/products_controller.rb b/app/controllers/api/v1/users/relationships/products_controller.rb index 94a30ac417..10ace290d9 100644 --- a/app/controllers/api/v1/users/relationships/products_controller.rb +++ b/app/controllers/api/v1/users/relationships/products_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Users::Relationships class ProductsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user authorize :user diff --git a/app/controllers/api/v1/users/relationships/second_factors_controller.rb b/app/controllers/api/v1/users/relationships/second_factors_controller.rb index 6776a7d6c0..90f5f362ca 100644 --- a/app/controllers/api/v1/users/relationships/second_factors_controller.rb +++ b/app/controllers/api/v1/users/relationships/second_factors_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Users::Relationships class SecondFactorsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user authorize :user diff --git a/app/controllers/api/v1/users/relationships/tokens_controller.rb b/app/controllers/api/v1/users/relationships/tokens_controller.rb index 2f25b2d962..61e448e792 100644 --- a/app/controllers/api/v1/users/relationships/tokens_controller.rb +++ b/app/controllers/api/v1/users/relationships/tokens_controller.rb @@ -4,7 +4,7 @@ module Api::V1::Users::Relationships class TokensController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_user authorize :user diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb index 390d9daf81..0171c40959 100644 --- a/app/controllers/api/v1/users_controller.rb +++ b/app/controllers/api/v1/users_controller.rb @@ -15,8 +15,8 @@ class UsersController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription!, only: %i[index create destroy] - before_action :authenticate_with_token!, only: %i[index show update destroy] - before_action :authenticate_with_token, only: %i[create] + before_action :authenticate!, only: %i[index show update destroy] + before_action :authenticate, only: %i[create] before_action :set_user, only: %i[show update destroy] def index diff --git a/app/controllers/api/v1/webhook_endpoints_controller.rb b/app/controllers/api/v1/webhook_endpoints_controller.rb index 3ba8e6de23..c285b1b06e 100644 --- a/app/controllers/api/v1/webhook_endpoints_controller.rb +++ b/app/controllers/api/v1/webhook_endpoints_controller.rb @@ -4,7 +4,7 @@ module Api::V1 class WebhookEndpointsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_endpoint, only: [:show, :update, :destroy] def index diff --git a/app/controllers/api/v1/webhook_events/actions/retries_controller.rb b/app/controllers/api/v1/webhook_events/actions/retries_controller.rb index d933ed349f..73b9c1d95e 100644 --- a/app/controllers/api/v1/webhook_events/actions/retries_controller.rb +++ b/app/controllers/api/v1/webhook_events/actions/retries_controller.rb @@ -4,7 +4,7 @@ module Api::V1::WebhookEvents::Actions class RetriesController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_event def retry diff --git a/app/controllers/api/v1/webhook_events_controller.rb b/app/controllers/api/v1/webhook_events_controller.rb index f60777d105..b9896beca8 100644 --- a/app/controllers/api/v1/webhook_events_controller.rb +++ b/app/controllers/api/v1/webhook_events_controller.rb @@ -6,7 +6,7 @@ class WebhookEventsController < Api::V1::BaseController before_action :scope_to_current_account! before_action :require_active_subscription! - before_action :authenticate_with_token! + before_action :authenticate! before_action :set_event, only: [:show, :destroy] def index diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5ad1d099f8..1b620cd171 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -394,16 +394,19 @@ def rescue_from_exceptions kwargs[:source] = e.source if e.source.present? + kwargs[:links] = e.links if + e.links.present? + # Add additional properties based on code case e.code when 'LICENSE_NOT_ALLOWED', 'LICENSE_INVALID' - kwargs[:links] = { about: 'https://keygen.sh/docs/api/authentication/#license-authentication' } + kwargs.deep_merge(links: { about: docs_url('/docs/api/authentication/#license-authentication') }) when 'TOKEN_NOT_ALLOWED', 'TOKEN_INVALID' - kwargs[:links] = { about: 'https://keygen.sh/docs/api/authentication/#token-authentication' } + kwargs.deep_merge(links: { about: docs_url('/docs/api/authentication/#token-authentication') }) when 'TOKEN_MISSING' - kwargs[:links] = { about: 'https://keygen.sh/docs/api/authentication/' } + kwargs.deep_merge(links: { about: docs_url('/docs/api/authentication/') }) end render_unauthorized(**kwargs) diff --git a/app/controllers/auth/sso_controller.rb b/app/controllers/auth/sso_controller.rb new file mode 100644 index 0000000000..94d8c9251e --- /dev/null +++ b/app/controllers/auth/sso_controller.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Auth + KEYGEN_PORTAL_HOST = ENV.fetch('KEYGEN_PORTAL_HOST') { 'portal.keygen.sh' } + + class SsoController < Api::V1::BaseController + include ActionController::Cookies + + skip_verify_authorized + + typed_query { + param :state, type: :string, optional: true, allow_blank: true + param :code, type: :string + } + def callback + code, state = sso_query.values_at(:code, :state) + profile = WorkOS::SSO.profile_and_token(client_id: WORKOS_CLIENT_ID, code:) + .profile + + # TODO(ezekg) error handling e.g. code is invalid, error callback, + # failure to find/create user, etc. + + account = Account.find_by!(sso_organization_id: profile.organization_id) + user = account.users.find_or_create_by!(email: profile.email) do |u| + u.sso_profile_id = profile.id + u.sso_idp_id = profile.idp_id + u.first_name = profile.first_name + u.last_name = profile.last_name + + # TODO(ezekg) eventually implement workos groups? + u.grant_role! :admin + end + + # Generate a nonce to assert that only 1 SSO-based session can be + # active for a user at any given time. + user.update!(session_nonce: SecureRandom.random_number(2**32)) + + # We use encrypted session cookies for SSO authentication because we + # don't want to expose a token in the redirect URL, and we don't + # want the token used for an API integration. + session[:nonce] = user.session_nonce + session[:account_id] = account.id + session[:user_id] = user.id + + redirect_to portal_url(account), status: :temporary_redirect, + allow_other_host: true + end + end +end diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 5fc6d96d95..62573b86ec 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -6,6 +6,28 @@ module Authentication include ActionController::HttpAuthentication::Token::ControllerMethods include ActionController::HttpAuthentication::Basic::ControllerMethods + def authenticate! + case + when has_password_credentials? + authenticate_with_password! + when has_session_credentials? + authenticate_with_session! + else + authenticate_with_token! + end + end + + def authenticate + case + when has_password_credentials? + authenticate_with_password + when has_session_credentials? + authenticate_with_session + else + authenticate_with_token + end + end + def authenticate_with_token! case when has_bearer_credentials? @@ -56,8 +78,24 @@ def authenticate_with_password_or_token end end + def authenticate_with_session! + authenticate_or_request_with_http_session(&method(:http_session_authenticator)) + end + + def authenticate_with_session + authenticate_with_http_session(&method(:http_session_authenticator)) + end + private + def authenticate_or_request_with_http_session(&auth_procedure) + authenticate_with_http_session(&auth_procedure) || request_http_token_authentication + end + + def authenticate_with_http_session(&auth_procedure) + auth_procedure.call(session) + end + def authenticate_or_request_with_query_token(&auth_procedure) authenticate_with_query_token(&auth_procedure) || request_http_token_authentication end @@ -79,6 +117,23 @@ def authenticate_with_http_license(&auth_procedure) auth_procedure.call(license_key) end + def http_session_authenticator(session) + return nil if + current_account.nil? || session.nil? + + user = current_account.users.for_environment(current_environment, strict: current_environment.nil?) + .find_by(id: session[:user_id]) + + unless user.present? && user.account_id == session[:account_id] && + user.session_nonce == session[:nonce] + session.destroy # clear cookie + + raise Keygen::Error::InvalidSessionError.new + end + + @current_bearer = user + end + def query_token_authenticator(query_token) return nil if current_account.nil? || query_token.blank? @@ -101,38 +156,34 @@ def http_password_authenticator(username = nil, password = nil) .find_by(email: "#{username}".downcase) unless user.present? - raise Keygen::Error::UnauthorizedError.new( - detail: 'email and password must be valid', - code: 'CREDENTIALS_INVALID', - header: 'Authorization', + raise Keygen::Error::InvalidCredentialsError.new(header: 'Authorization') + end + + if user.single_sign_on_enabled? + provider = params.dig(:meta, :provider) + redirect = WorkOS::SSO.authorization_url( + redirect_uri: sso_callback_url, + client_id: WORKOS_CLIENT_ID, + organization: current_account.sso_organization_id, + provider:, ) + + raise Keygen::Error::SingleSignOnRequiredError.new(links: { redirect: }) end if user.second_factor_enabled? otp = params.dig(:meta, :otp) if otp.nil? - raise Keygen::Error::UnauthorizedError.new( - detail: 'second factor is required', - code: 'OTP_REQUIRED', - pointer: '/meta/otp', - ) + raise Keygen::Error::SecondFactorRequiredError.new(pointer: '/meta/otp') end unless user.verify_second_factor(otp) - raise Keygen::Error::UnauthorizedError.new( - detail: 'second factor must be valid', - code: 'OTP_INVALID', - pointer: '/meta/otp', - ) + raise Keygen::Error::InvalidSecondFactorError.new(pointer: '/meta/otp') end end unless user.password? && user.authenticate(password) - raise Keygen::Error::UnauthorizedError.new( - detail: 'email and password must be valid', - code: 'CREDENTIALS_INVALID', - header: 'Authorization', - ) + raise Keygen::Error::InvalidCredentialsError.new(header: 'Authorization') end @current_bearer = user @@ -283,6 +334,10 @@ def has_license_credentials? authentication_scheme == 'license' end + def has_session_credentials? + session.key?(:user_id) + end + def has_password_credentials? return false unless has_basic_credentials? diff --git a/app/models/account.rb b/app/models/account.rb index f1f90f73a2..df6ac8dfd9 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -289,6 +289,8 @@ def protected? protected end + def sso? = sso_organization_id? + def status billing&.state&.upcase end diff --git a/app/models/user.rb b/app/models/user.rb index 9c5255674f..8516a4508a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -470,6 +470,8 @@ def status end end + def single_sign_on_enabled? = account.sso? + def second_factor_enabled? second_factors.enabled.exists? end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index cb1446dba3..cb975a732a 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -12,6 +12,7 @@ def call! case when Keygen.singleplayer? account_id = request.params[:account_id] || + request.session[:account_id] || ENV['KEYGEN_ACCOUNT_ID'] raise Keygen::Error::InvalidAccountIdError, 'account is required' unless account_id.present? @@ -22,7 +23,7 @@ def call! account when Keygen.multiplayer? - account_id = request.params[:account_id] + account_id = request.params[:account_id] || request.session[:account_id] account_host = request.host account = find_by_account_cname(account_host) || diff --git a/config/application.rb b/config/application.rb index e603143cd3..9b71fd7bdd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -34,6 +34,17 @@ class Application < Rails::Application # Skip views, helpers and assets when generating a new resource. config.api_only = true + # Use cookies for sessions + config.session_store :cookie_store, key: '_keygen_session', + domain: ENV.fetch('KEYGEN_PORTAL_HOST') { 'portal.keygen.sh' }, + expire_after: 1.day, + httponly: true, + secure: true + + # Re-add session middleware since we're an API-only app + config.middleware.use ActionDispatch::Cookies + config.middleware.use config.session_store, config.session_options + # Remove unneeded Rack middleware config.middleware.delete Rack::ConditionalGet config.middleware.delete Rack::ETag @@ -93,6 +104,9 @@ class Application < Rails::Application # FIXME(ezekg) Use 7.0 cache format until we can roll over to 7.1. config.active_support.cache_format_version 7.0 + # Use SHA256 for signed cookies + config.action_dispatch.signed_cookie_digest = 'SHA256' + # We don't need this: https://guides.rubyonrails.org/security.html#unsafe-query-generation config.action_dispatch.perform_deep_munge = false diff --git a/config/initializers/workos.rb b/config/initializers/workos.rb new file mode 100644 index 0000000000..8c519e57e3 --- /dev/null +++ b/config/initializers/workos.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +WORKOS_CLIENT_ID = ENV['WORKOS_CLIENT_ID'] +WORKOS_API_KEY = ENV['WORKOS_API_KEY'] + +WorkOS.configure do |config| + config.key = WORKOS_API_KEY +end diff --git a/config/initializers/zietwork.rb b/config/initializers/zietwork.rb index d1db06934a..6afc5529a0 100644 --- a/config/initializers/zietwork.rb +++ b/config/initializers/zietwork.rb @@ -3,8 +3,11 @@ Rails.autoloaders.each do |autoloader| # FIXME(ezekg) Should we rename these to follow conventions? autoloader.inflector.inflect( - "digest_io" => "DigestIO", - "jsonapi" => "JSONAPI", - "ee" => "EE", + 'digest_io' => 'DigestIO', + 'jsonapi' => 'JSONAPI', + 'ee' => 'EE', + 'ldap' => 'LDAP', + 'saml' => 'SAML', + 'sso' => 'SSO', ) end diff --git a/config/routes.rb b/config/routes.rb index cb30a6cc3e..1f871fb42a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -54,10 +54,14 @@ concern :tauri do scope module: :tauri, constraints: MimeTypeConstraint.new(:binary, :json, raise_on_no_match: true), defaults: { format: :json } do - get ':package', to: 'upgrades#show' + get ':package', to: 'upgrades#show', as: :tauri_upgrade_package end end + concern :sso do + get :sso, to: 'sso#callback', as: :sso_callback + end + concern :v1 do get :ping, to: 'health#general_ping' @@ -477,6 +481,14 @@ end end + # Subdomains for authentication (i.e. SSO) + scope constraints: { subdomain: 'auth' }, **domain_constraints do + # SSO + scope module: :auth do + concerns :sso + end + end + scope module: :api do namespace :v1 do # Health checks @@ -538,6 +550,28 @@ end end + # Route helper for redirecting to Portal + direct :portal do |segment| + case segment + in Account => account + "https://portal.keygen.sh/#{account.slug}" + in String => path + "https://portal.keygen.sh/#{path}" + else + "https://portal.keygen.sh" + end + end + + # Route helpers for redirecting to docs + direct :docs do |segment| + case segment + in String => path + "https://keygen.sh/#{path}" + else + "https://keygen.sh" + end + end + %w[500 503].each do |code| match code, to: 'errors#show', code: code.to_i, via: :all end diff --git a/db/migrate/20240712202229_add_sso_organization_id_to_accounts.rb b/db/migrate/20240712202229_add_sso_organization_id_to_accounts.rb new file mode 100644 index 0000000000..024577961e --- /dev/null +++ b/db/migrate/20240712202229_add_sso_organization_id_to_accounts.rb @@ -0,0 +1,8 @@ +class AddSsoOrganizationIdToAccounts < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_column :accounts, :sso_organization_id, :string, null: true + add_index :accounts, :sso_organization_id, unique: true, algorithm: :concurrently + end +end diff --git a/db/migrate/20240715164737_add_sso_profile_id_to_users.rb b/db/migrate/20240715164737_add_sso_profile_id_to_users.rb new file mode 100644 index 0000000000..269807b630 --- /dev/null +++ b/db/migrate/20240715164737_add_sso_profile_id_to_users.rb @@ -0,0 +1,8 @@ +class AddSsoProfileIdToUsers < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_column :users, :sso_profile_id, :string, null: true + add_index :users, %i[account_id sso_profile_id], unique: true, algorithm: :concurrently + end +end diff --git a/db/migrate/20240715174443_add_sso_idp_id_to_users.rb b/db/migrate/20240715174443_add_sso_idp_id_to_users.rb new file mode 100644 index 0000000000..040368ff08 --- /dev/null +++ b/db/migrate/20240715174443_add_sso_idp_id_to_users.rb @@ -0,0 +1,8 @@ +class AddSsoIdpIdToUsers < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_column :users, :sso_idp_id, :string, null: true + add_index :users, %i[account_id sso_idp_id], unique: true, algorithm: :concurrently + end +end diff --git a/db/migrate/20240715210732_add_session_nonce_to_users.rb b/db/migrate/20240715210732_add_session_nonce_to_users.rb new file mode 100644 index 0000000000..716b335697 --- /dev/null +++ b/db/migrate/20240715210732_add_session_nonce_to_users.rb @@ -0,0 +1,5 @@ +class AddSessionNonceToUsers < ActiveRecord::Migration[7.1] + def change + add_column :users, :session_nonce, :integer, limit: 8 + end +end diff --git a/db/schema.rb b/db/schema.rb index c375d1c850..e49b5e51d2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -39,6 +39,7 @@ t.string "api_version" t.string "cname" t.string "backend" + t.string "sso_organization_id" t.index ["cname"], name: "index_accounts_on_cname", unique: true t.index ["created_at"], name: "index_accounts_on_created_at", order: :desc t.index ["domain"], name: "index_accounts_on_domain", unique: true @@ -46,6 +47,7 @@ t.index ["plan_id", "created_at"], name: "index_accounts_on_plan_id_and_created_at" t.index ["slug", "created_at"], name: "index_accounts_on_slug_and_created_at", unique: true t.index ["slug"], name: "index_accounts_on_slug", unique: true + t.index ["sso_organization_id"], name: "index_accounts_on_sso_organization_id", unique: true t.index ["subdomain"], name: "index_accounts_on_subdomain", unique: true end @@ -794,11 +796,16 @@ t.datetime "banned_at", precision: nil t.uuid "group_id" t.uuid "environment_id" + t.string "sso_profile_id" + t.string "sso_idp_id" + t.bigint "session_nonce" t.index "to_tsvector('simple'::regconfig, COALESCE((first_name)::text, ''::text))", name: "users_tsv_first_name_idx", using: :gist t.index "to_tsvector('simple'::regconfig, COALESCE((id)::text, ''::text))", name: "users_tsv_id_idx", using: :gist t.index "to_tsvector('simple'::regconfig, COALESCE((last_name)::text, ''::text))", name: "users_tsv_last_name_idx", using: :gist t.index "to_tsvector('simple'::regconfig, COALESCE((metadata)::text, ''::text))", name: "users_tsv_metadata_idx", using: :gist t.index ["account_id", "created_at"], name: "index_users_on_account_id_and_created_at" + t.index ["account_id", "sso_idp_id"], name: "index_users_on_account_id_and_sso_idp_id", unique: true + t.index ["account_id", "sso_profile_id"], name: "index_users_on_account_id_and_sso_profile_id", unique: true t.index ["banned_at"], name: "index_users_on_banned_at" t.index ["created_at"], name: "index_users_on_created_at", order: :desc t.index ["email", "account_id"], name: "index_users_on_email_and_account_id", unique: true diff --git a/lib/keygen/error.rb b/lib/keygen/error.rb index 0c0cef02ea..e2be737b0a 100644 --- a/lib/keygen/error.rb +++ b/lib/keygen/error.rb @@ -5,12 +5,14 @@ module Error class JSONAPIError < StandardError attr_reader :code, :detail, - :source + :source, + :links - def initialize(message, code: nil, detail: nil, parameter: nil, pointer: nil, header: nil) + def initialize(message, code: nil, detail: nil, parameter: nil, pointer: nil, header: nil, links: nil) @code = code @detail = detail @source = { parameter:, pointer:, header: }.compact + @links = links super(message) end @@ -20,6 +22,26 @@ class UnauthorizedError < JSONAPIError def initialize(message = 'is unauthorized', code:, **) = super(message, code:, **) end + class InvalidCredentialsError < UnauthorizedError + def initialize(*, **) = super(detail: 'email and password must be valid', code: 'CREDENTIALS_INVALID', **) + end + + class SingleSignOnRequiredError < UnauthorizedError + def initialize(*, **) = super(detail: 'single sign on is required', code: 'SSO_REQUIRED', **) + end + + class SecondFactorRequiredError < UnauthorizedError + def initialize(*, **) = super(detail: 'second factor is required', code: 'OTP_REQUIRED', **) + end + + class InvalidSecondFactorError < UnauthorizedError + def initialize(*, **) = super(detail: 'second factor must be valid', code: 'OTP_INVALID', **) + end + + class InvalidSessionError < UnauthorizedError + def initialize(*, **) = super(detail: 'session is invalid', code: 'SESSION_INVALID', **) + end + class ForbiddenError < JSONAPIError def initialize(message = 'is forbidden', code:, **) = super(message, code:, **) end diff --git a/spec/lib/union_of_spec.rb b/spec/lib/union_of_spec.rb index 0760734827..49cb320d1c 100644 --- a/spec/lib/union_of_spec.rb +++ b/spec/lib/union_of_spec.rb @@ -935,7 +935,10 @@ "users"."stdout_last_sent_at" AS t1_r12, "users"."banned_at" AS t1_r13, "users"."group_id" AS t1_r14, - "users"."environment_id" AS t1_r15 + "users"."environment_id" AS t1_r15, + "users"."sso_profile_id" AS t1_r16, + "users"."sso_idp_id" AS t1_r17, + "users"."session_nonce" AS t1_r18 FROM "licenses" LEFT OUTER JOIN "license_users" ON "license_users"."license_id" = "licenses"."id" @@ -979,6 +982,9 @@ "users"."banned_at" AS t0_r13, "users"."group_id" AS t0_r14, "users"."environment_id" AS t0_r15, + "users"."sso_profile_id" AS t0_r16, + "users"."sso_idp_id" AS t0_r17, + "users"."session_nonce" AS t0_r18, "machines"."id" AS t1_r0, "machines"."fingerprint" AS t1_r1, "machines"."ip" AS t1_r2, From 3d47fdb750cb88db9cd80536ffb02782e69bb974 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 10:49:14 -0500 Subject: [PATCH 02/14] update jit-user-provisioning --- app/controllers/auth/sso_controller.rb | 45 ++++++++++++++----- config/initializers/zietwork.rb | 2 + ...16153309_add_sso_connection_id_to_users.rb | 7 +++ db/schema.rb | 1 + lib/keygen/error.rb | 4 ++ spec/lib/union_of_spec.rb | 4 +- 6 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20240716153309_add_sso_connection_id_to_users.rb diff --git a/app/controllers/auth/sso_controller.rb b/app/controllers/auth/sso_controller.rb index 94d8c9251e..3c9bdce27c 100644 --- a/app/controllers/auth/sso_controller.rb +++ b/app/controllers/auth/sso_controller.rb @@ -20,20 +20,41 @@ def callback # TODO(ezekg) error handling e.g. code is invalid, error callback, # failure to find/create user, etc. - account = Account.find_by!(sso_organization_id: profile.organization_id) - user = account.users.find_or_create_by!(email: profile.email) do |u| - u.sso_profile_id = profile.id - u.sso_idp_id = profile.idp_id - u.first_name = profile.first_name - u.last_name = profile.last_name - - # TODO(ezekg) eventually implement workos groups? - u.grant_role! :admin + account = Account.where.not(sso_organization_id: nil) # sanity-check + .find_by!( + sso_organization_id: profile.organization_id, + ) + + # WorkOS recommends JIT-user-provisioning: https://workos.com/docs/sso/jit-provisioning + # + # 1. First, we attempt to find the user by their profile ID. + # 2. Next, we attempt to find the user by their email. + # 3. Otherwise, create a new user. + # + # Afterwards, we keep the user's profile up-to-date. + user = account.users.then do |users| + users.find_by(sso_profile_id: profile.id) || users.find_or_initialize_by(email: profile.email) do |u| + u.sso_profile_id = profile.id + u.sso_connection_id = profile.connection_id + u.sso_idp_id = profile.idp_id + u.first_name = profile.first_name + u.last_name = profile.last_name + u.email = profile.email + + # TODO(ezekg) eventually implement workos groups? + u.grant_role! :admin + end end - # Generate a nonce to assert that only 1 SSO-based session can be - # active for a user at any given time. - user.update!(session_nonce: SecureRandom.random_number(2**32)) + user.update!( + # Generate a nonce to assert that only 1 SSO-based session can be + # active for a user at any given time. + session_nonce: SecureRandom.random_number(2**32), + # Keep the user's profile up-to-date with the IdP. + first_name: profile.first_name, + last_name: profile.last_name, + email: profile.email, + ) # We use encrypted session cookies for SSO authentication because we # don't want to expose a token in the redirect URL, and we don't diff --git a/config/initializers/zietwork.rb b/config/initializers/zietwork.rb index 6afc5529a0..8a152e37d4 100644 --- a/config/initializers/zietwork.rb +++ b/config/initializers/zietwork.rb @@ -9,5 +9,7 @@ 'ldap' => 'LDAP', 'saml' => 'SAML', 'sso' => 'SSO', + 'idp' => 'IdP', + 'sp' => 'SP', ) end diff --git a/db/migrate/20240716153309_add_sso_connection_id_to_users.rb b/db/migrate/20240716153309_add_sso_connection_id_to_users.rb new file mode 100644 index 0000000000..150acdae1b --- /dev/null +++ b/db/migrate/20240716153309_add_sso_connection_id_to_users.rb @@ -0,0 +1,7 @@ +class AddSsoConnectionIdToUsers < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_column :users, :sso_connection_id, :string, null: true + end +end diff --git a/db/schema.rb b/db/schema.rb index e49b5e51d2..e28b3e2778 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -799,6 +799,7 @@ t.string "sso_profile_id" t.string "sso_idp_id" t.bigint "session_nonce" + t.string "sso_connection_id" t.index "to_tsvector('simple'::regconfig, COALESCE((first_name)::text, ''::text))", name: "users_tsv_first_name_idx", using: :gist t.index "to_tsvector('simple'::regconfig, COALESCE((id)::text, ''::text))", name: "users_tsv_id_idx", using: :gist t.index "to_tsvector('simple'::regconfig, COALESCE((last_name)::text, ''::text))", name: "users_tsv_last_name_idx", using: :gist diff --git a/lib/keygen/error.rb b/lib/keygen/error.rb index e2be737b0a..7b966d1a80 100644 --- a/lib/keygen/error.rb +++ b/lib/keygen/error.rb @@ -30,6 +30,10 @@ class SingleSignOnRequiredError < UnauthorizedError def initialize(*, **) = super(detail: 'single sign on is required', code: 'SSO_REQUIRED', **) end + class InvalidSingleSignOnError < UnauthorizedError + def initialize(*, **) = super(detail: 'single sign on is invalid', code: 'SSO_INVALID', **) + end + class SecondFactorRequiredError < UnauthorizedError def initialize(*, **) = super(detail: 'second factor is required', code: 'OTP_REQUIRED', **) end diff --git a/spec/lib/union_of_spec.rb b/spec/lib/union_of_spec.rb index 49cb320d1c..38c27d45ca 100644 --- a/spec/lib/union_of_spec.rb +++ b/spec/lib/union_of_spec.rb @@ -938,7 +938,8 @@ "users"."environment_id" AS t1_r15, "users"."sso_profile_id" AS t1_r16, "users"."sso_idp_id" AS t1_r17, - "users"."session_nonce" AS t1_r18 + "users"."session_nonce" AS t1_r18, + "users"."sso_connection_id" AS t1_r19 FROM "licenses" LEFT OUTER JOIN "license_users" ON "license_users"."license_id" = "licenses"."id" @@ -985,6 +986,7 @@ "users"."sso_profile_id" AS t0_r16, "users"."sso_idp_id" AS t0_r17, "users"."session_nonce" AS t0_r18, + "users"."sso_connection_id" AS t0_r19, "machines"."id" AS t1_r0, "machines"."fingerprint" AS t1_r1, "machines"."ip" AS t1_r2, From c60c46e075e9c3c095be239bd627608012e7fc4f Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 12:27:52 -0500 Subject: [PATCH 03/14] refactor direct urls --- app/controllers/application_controller.rb | 6 ++-- config/initializers/zietwork.rb | 2 ++ config/routes.rb | 20 +++--------- lib/keygen.rb | 1 + lib/keygen/url.rb | 38 +++++++++++++++++++++++ 5 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 lib/keygen/url.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1b620cd171..c0a0547980 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -401,12 +401,12 @@ def rescue_from_exceptions case e.code when 'LICENSE_NOT_ALLOWED', 'LICENSE_INVALID' - kwargs.deep_merge(links: { about: docs_url('/docs/api/authentication/#license-authentication') }) + kwargs.deep_merge(links: { about: docs_url(:authentication, anchor: 'license-authentication') }) when 'TOKEN_NOT_ALLOWED', 'TOKEN_INVALID' - kwargs.deep_merge(links: { about: docs_url('/docs/api/authentication/#token-authentication') }) + kwargs.deep_merge(links: { about: docs_url(:authentication, anchor: 'token-authentication') }) when 'TOKEN_MISSING' - kwargs.deep_merge(links: { about: docs_url('/docs/api/authentication/') }) + kwargs.deep_merge(links: { about: docs_url(:authentication) }) end render_unauthorized(**kwargs) diff --git a/config/initializers/zietwork.rb b/config/initializers/zietwork.rb index 8a152e37d4..296d42cbf3 100644 --- a/config/initializers/zietwork.rb +++ b/config/initializers/zietwork.rb @@ -11,5 +11,7 @@ 'sso' => 'SSO', 'idp' => 'IdP', 'sp' => 'SP', + 'uri' => 'URI', + 'url' => 'URL', ) end diff --git a/config/routes.rb b/config/routes.rb index 1f871fb42a..c5bf80dd1d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -551,25 +551,13 @@ end # Route helper for redirecting to Portal - direct :portal do |segment| - case segment - in Account => account - "https://portal.keygen.sh/#{account.slug}" - in String => path - "https://portal.keygen.sh/#{path}" - else - "https://portal.keygen.sh" - end + direct :portal do |segment, options| + Keygen::URL.portal_url(segment, **options) end # Route helpers for redirecting to docs - direct :docs do |segment| - case segment - in String => path - "https://keygen.sh/#{path}" - else - "https://keygen.sh" - end + direct :docs do |segment, options| + Keygen::URL.docs_url(segment, **options) end %w[500 503].each do |code| diff --git a/lib/keygen.rb b/lib/keygen.rb index 638ee4babd..6bbad4d47d 100644 --- a/lib/keygen.rb +++ b/lib/keygen.rb @@ -10,6 +10,7 @@ require_relative 'keygen/portable_class' require_relative 'keygen/exporter' require_relative 'keygen/importer' +require_relative 'keygen/url' module Keygen PUBLIC_KEY = %(\xB8\xF3\xEBL\xD2`\x13_g\xA5\tn\x8D\xC1\xC9\xB9\xDC\xB8\x1E\xE9\xFEP\xD1,\xDC\xD9A\xF6`z\x901).freeze diff --git a/lib/keygen/url.rb b/lib/keygen/url.rb new file mode 100644 index 0000000000..7680ef72b3 --- /dev/null +++ b/lib/keygen/url.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Keygen + module URL + PORTAL_BASE_URL = 'https://portal.keygen.sh'.freeze + DOCS_BASE_URL = 'https://keygen.sh/docs/api'.freeze + + class << self + def portal_url(record_or_path = nil, **) = case record_or_path + in Account => account + url_for(PORTAL_BASE_URL, path: account.slug, **) + in String | Symbol => path + url_for(PORTAL_BASE_URL, path:, **) + else + url_for(PORTAL_BASE_URL, **) + end + + def docs_url(topic = nil, **) = url_for(DOCS_BASE_URL, trailing_slash: true, path: topic.presence, **) + + private + + def url_for(base_url, path: nil, query: nil, anchor: nil, trailing_slash: false) + url = URI.parse(base_url) + + unless path.nil? + url.path += '/' unless path.to_s.starts_with?('/') + url.path += path.to_s + url.path += '/' if trailing_slash + end + + url.query = query.to_query unless query.nil? + url.fragment = anchor.to_s unless anchor.nil? + + url.to_s + end + end + end +end From 67244677030595624d238c27b0833647b640aefe Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 12:38:04 -0500 Subject: [PATCH 04/14] fix issue where non-admins required sso --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 8516a4508a..df62e20fe2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -470,7 +470,7 @@ def status end end - def single_sign_on_enabled? = account.sso? + def single_sign_on_enabled? = !role.user? && account.sso? def second_factor_enabled? second_factors.enabled.exists? From 413d4e8bbc38bb454729e8c6ec8767495f365bdc Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 12:45:16 -0500 Subject: [PATCH 05/14] add error handling to sso callback --- app/controllers/application_controller.rb | 5 +++++ app/controllers/auth/sso_controller.rb | 24 +++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c0a0547980..3871d75c0a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -385,6 +385,11 @@ def rescue_from_exceptions e.code.present? render_bad_request(**kwargs) + rescue Keygen::Error::InvalidSingleSignOnError => e + Keygen.logger.warn { "[sso] code=#{e.code.inspect} message=#{e.message.inspect}" } + + # we want to redirect to Portal to display the SSO error message in a helpful way + redirect_to portal_url('/sso/error', query: { error: e.message, code: e.code }) rescue Keygen::Error::UnauthorizedError => e kwargs = { code: e.code } diff --git a/app/controllers/auth/sso_controller.rb b/app/controllers/auth/sso_controller.rb index 3c9bdce27c..063f136260 100644 --- a/app/controllers/auth/sso_controller.rb +++ b/app/controllers/auth/sso_controller.rb @@ -9,22 +9,33 @@ class SsoController < Api::V1::BaseController skip_verify_authorized typed_query { + param :error_description, type: :string, optional: true, allow_blank: true + param :error, type: :string, optional: true, allow_blank: true param :state, type: :string, optional: true, allow_blank: true param :code, type: :string } def callback + if (error_code = sso_query[:error]).present? + error_message = sso_query[:error_description] + + raise Keygen::Error::InvalidSingleSignOnError.new( + code: error_code.then { "SSO_#{_1.upcase}" unless _1.nil? }, + detail: error_message, + ) + end + code, state = sso_query.values_at(:code, :state) profile = WorkOS::SSO.profile_and_token(client_id: WORKOS_CLIENT_ID, code:) .profile - # TODO(ezekg) error handling e.g. code is invalid, error callback, - # failure to find/create user, etc. - account = Account.where.not(sso_organization_id: nil) # sanity-check - .find_by!( + .find_by( sso_organization_id: profile.organization_id, ) + raise Keygen::Error::InvalidSingleSignOnError.new('account is invalid') if + account.nil? + # WorkOS recommends JIT-user-provisioning: https://workos.com/docs/sso/jit-provisioning # # 1. First, we attempt to find the user by their profile ID. @@ -65,6 +76,11 @@ def callback redirect_to portal_url(account), status: :temporary_redirect, allow_other_host: true + rescue WorkOS::APIError => e + raise Keygen::Error::InvalidSingleSignOnError.new( + code: e.code.then { "SSO_#{_1.upcase}" unless _1.nil? }, + detail: e.message, + ) end end end From 84b92534ec1fd50ec2435058b3ba440e2004c82d Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 15:19:17 -0500 Subject: [PATCH 06/14] fix jit-user-provisioning for org emails --- app/controllers/concerns/authentication.rb | 6 ++++++ ...0240716174322_add_sso_organization_domain_to_accounts.rb | 5 +++++ db/schema.rb | 1 + 3 files changed, 12 insertions(+) create mode 100644 db/migrate/20240716174322_add_sso_organization_domain_to_accounts.rb diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 62573b86ec..370f946a1d 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -152,6 +152,12 @@ def query_token_authenticator(query_token) end def http_password_authenticator(username = nil, password = nil) + if current_account.sso? && current_account.sso_organization_domains.any? { username.ends_with?(_1) } # for JIT-user-provisioning + redirect = Keygen::SSO.authorization_url(account: current_account, email: username) + + raise Keygen::Error::SingleSignOnRequiredError.new(links: { redirect: }) + end + user = current_account.users.for_environment(current_environment, strict: current_environment.nil?) .find_by(email: "#{username}".downcase) diff --git a/db/migrate/20240716174322_add_sso_organization_domain_to_accounts.rb b/db/migrate/20240716174322_add_sso_organization_domain_to_accounts.rb new file mode 100644 index 0000000000..ace43ecc65 --- /dev/null +++ b/db/migrate/20240716174322_add_sso_organization_domain_to_accounts.rb @@ -0,0 +1,5 @@ +class AddSsoOrganizationDomainToAccounts < ActiveRecord::Migration[7.1] + def change + add_column :accounts, :sso_organization_domains, :string, array: true, default: [] + end +end diff --git a/db/schema.rb b/db/schema.rb index e28b3e2778..2b0b9c3eb6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -40,6 +40,7 @@ t.string "cname" t.string "backend" t.string "sso_organization_id" + t.string "sso_organization_domains", default: [], array: true t.index ["cname"], name: "index_accounts_on_cname", unique: true t.index ["created_at"], name: "index_accounts_on_created_at", order: :desc t.index ["domain"], name: "index_accounts_on_domain", unique: true From 992a8c9b7f12a3485af1459cec331d9831a1e98f Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 15:19:48 -0500 Subject: [PATCH 07/14] refactor sso logic into module --- app/controllers/application_controller.rb | 4 +- app/controllers/auth/sso_controller.rb | 70 +++-------- app/controllers/concerns/authentication.rb | 8 +- lib/keygen.rb | 1 + lib/keygen/error.rb | 12 +- lib/keygen/sso.rb | 129 +++++++++++++++++++++ 6 files changed, 153 insertions(+), 71 deletions(-) create mode 100644 lib/keygen/sso.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3871d75c0a..ecf6ba4873 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -386,10 +386,10 @@ def rescue_from_exceptions render_bad_request(**kwargs) rescue Keygen::Error::InvalidSingleSignOnError => e - Keygen.logger.warn { "[sso] code=#{e.code.inspect} message=#{e.message.inspect}" } + Keygen.logger.warn { "[sso] error=#{e.class.inspect} code=#{e.code.inspect} message=#{e.message.inspect}" } # we want to redirect to Portal to display the SSO error message in a helpful way - redirect_to portal_url('/sso/error', query: { error: e.message, code: e.code }) + redirect_to portal_url('/sso/error', query: { code: e.code }), status: :see_other, allow_other_host: true rescue Keygen::Error::UnauthorizedError => e kwargs = { code: e.code } diff --git a/app/controllers/auth/sso_controller.rb b/app/controllers/auth/sso_controller.rb index 063f136260..5227fdfc4c 100644 --- a/app/controllers/auth/sso_controller.rb +++ b/app/controllers/auth/sso_controller.rb @@ -8,63 +8,27 @@ class SsoController < Api::V1::BaseController skip_verify_authorized - typed_query { - param :error_description, type: :string, optional: true, allow_blank: true - param :error, type: :string, optional: true, allow_blank: true - param :state, type: :string, optional: true, allow_blank: true - param :code, type: :string - } def callback - if (error_code = sso_query[:error]).present? - error_message = sso_query[:error_description] + Keygen::SSO.raise_on_request_error!(request) # handle errors - raise Keygen::Error::InvalidSingleSignOnError.new( - code: error_code.then { "SSO_#{_1.upcase}" unless _1.nil? }, - detail: error_message, - ) - end - - code, state = sso_query.values_at(:code, :state) - profile = WorkOS::SSO.profile_and_token(client_id: WORKOS_CLIENT_ID, code:) - .profile - - account = Account.where.not(sso_organization_id: nil) # sanity-check - .find_by( - sso_organization_id: profile.organization_id, - ) - - raise Keygen::Error::InvalidSingleSignOnError.new('account is invalid') if - account.nil? - - # WorkOS recommends JIT-user-provisioning: https://workos.com/docs/sso/jit-provisioning - # - # 1. First, we attempt to find the user by their profile ID. - # 2. Next, we attempt to find the user by their email. - # 3. Otherwise, create a new user. - # - # Afterwards, we keep the user's profile up-to-date. - user = account.users.then do |users| - users.find_by(sso_profile_id: profile.id) || users.find_or_initialize_by(email: profile.email) do |u| - u.sso_profile_id = profile.id - u.sso_connection_id = profile.connection_id - u.sso_idp_id = profile.idp_id - u.first_name = profile.first_name - u.last_name = profile.last_name - u.email = profile.email + code, state = request.query_parameters.values_at(:code, :state) + profile = Keygen::SSO.redeem_code(code:) + account = Keygen::SSO.lookup_account( + profile:, + ) - # TODO(ezekg) eventually implement workos groups? - u.grant_role! :admin - end - end + # assert the authn state matches what we expect e.g. the original email + # equals actual authenticated email + Keygen::SSO.raise_on_state_error!(state, + profile:, + account:, + ) + user = Keygen::SSO.lookup_or_provision_user(profile:, account:) user.update!( # Generate a nonce to assert that only 1 SSO-based session can be # active for a user at any given time. session_nonce: SecureRandom.random_number(2**32), - # Keep the user's profile up-to-date with the IdP. - first_name: profile.first_name, - last_name: profile.last_name, - email: profile.email, ) # We use encrypted session cookies for SSO authentication because we @@ -74,13 +38,7 @@ def callback session[:account_id] = account.id session[:user_id] = user.id - redirect_to portal_url(account), status: :temporary_redirect, - allow_other_host: true - rescue WorkOS::APIError => e - raise Keygen::Error::InvalidSingleSignOnError.new( - code: e.code.then { "SSO_#{_1.upcase}" unless _1.nil? }, - detail: e.message, - ) + redirect_to portal_url(account), status: :see_other, allow_other_host: true end end end diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 370f946a1d..47ff5926fc 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -166,13 +166,7 @@ def http_password_authenticator(username = nil, password = nil) end if user.single_sign_on_enabled? - provider = params.dig(:meta, :provider) - redirect = WorkOS::SSO.authorization_url( - redirect_uri: sso_callback_url, - client_id: WORKOS_CLIENT_ID, - organization: current_account.sso_organization_id, - provider:, - ) + redirect = Keygen::SSO.authorization_url(account: current_account, email: user.email) raise Keygen::Error::SingleSignOnRequiredError.new(links: { redirect: }) end diff --git a/lib/keygen.rb b/lib/keygen.rb index 6bbad4d47d..7dbfb808da 100644 --- a/lib/keygen.rb +++ b/lib/keygen.rb @@ -10,6 +10,7 @@ require_relative 'keygen/portable_class' require_relative 'keygen/exporter' require_relative 'keygen/importer' +require_relative 'keygen/sso' require_relative 'keygen/url' module Keygen diff --git a/lib/keygen/error.rb b/lib/keygen/error.rb index 7b966d1a80..1653a0c574 100644 --- a/lib/keygen/error.rb +++ b/lib/keygen/error.rb @@ -23,27 +23,27 @@ def initialize(message = 'is unauthorized', code:, **) = super(message, code:, * end class InvalidCredentialsError < UnauthorizedError - def initialize(*, **) = super(detail: 'email and password must be valid', code: 'CREDENTIALS_INVALID', **) + def initialize(*, **) = super(*, detail: 'email and password must be valid', code: 'CREDENTIALS_INVALID', **) end class SingleSignOnRequiredError < UnauthorizedError - def initialize(*, **) = super(detail: 'single sign on is required', code: 'SSO_REQUIRED', **) + def initialize(*, **) = super(*, detail: 'single sign on is required', code: 'SSO_REQUIRED', **) end class InvalidSingleSignOnError < UnauthorizedError - def initialize(*, **) = super(detail: 'single sign on is invalid', code: 'SSO_INVALID', **) + def initialize(*, **) = super(*, detail: 'single sign on is invalid', code: 'SSO_INVALID', **) end class SecondFactorRequiredError < UnauthorizedError - def initialize(*, **) = super(detail: 'second factor is required', code: 'OTP_REQUIRED', **) + def initialize(*, **) = super(*, detail: 'second factor is required', code: 'OTP_REQUIRED', **) end class InvalidSecondFactorError < UnauthorizedError - def initialize(*, **) = super(detail: 'second factor must be valid', code: 'OTP_INVALID', **) + def initialize(*, **) = super(*, detail: 'second factor must be valid', code: 'OTP_INVALID', **) end class InvalidSessionError < UnauthorizedError - def initialize(*, **) = super(detail: 'session is invalid', code: 'SESSION_INVALID', **) + def initialize(*, **) = super(*, detail: 'session is invalid', code: 'SESSION_INVALID', **) end class ForbiddenError < JSONAPIError diff --git a/lib/keygen/sso.rb b/lib/keygen/sso.rb new file mode 100644 index 0000000000..e28c3133aa --- /dev/null +++ b/lib/keygen/sso.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +module Keygen + module SSO + class << self + def authorization_url(account:, email:, provider: nil) + state = { email: } # used to assert redeemer matches requestor + + WorkOS::SSO.authorization_url( + client_id: WORKOS_CLIENT_ID, + organization: account.sso_organization_id, + state: encrypt(state, secret_key: account.secret_key), + redirect_uri:, + provider:, + ) + end + + # Redeem an authentication code for a user profile. + def redeem_code(code:) + WorkOS::SSO.profile_and_token(client_id: WORKOS_CLIENT_ID, code:) + .profile + rescue WorkOS::APIError => e + raise Keygen::Error::InvalidSingleSignOnError.new(e.message) + end + + # Lookup the account for a user profile. + def lookup_account(profile:) + Account.where.not(sso_organization_id: nil) # sanity-check + .find_by!( + sso_organization_id: profile.organization_id, + ) + rescue ActiveRecord::RecordNotFound + raise Keygen::Error::InvalidSingleSignOnError.new('account is invalid') + end + + # WorkOS recommends JIT-user-provisioning: https://workos.com/docs/sso/jit-provisioning + # + # 1. First, we attempt to lookup the user by their profile ID. + # 2. Next, we attempt to lookup the user by their email. + # 3. Otherwise, initialize a new user. + # + # Lastly, we keep the user's attributes up-to-date. + def lookup_or_provision_user(profile:, account:, save: false, validate: false) + user = account.users.then do |users| + users.find_by(sso_profile_id: profile.id) || users.find_or_initialize_by(email: profile.email) do |u| + u.sso_profile_id = profile.id + u.sso_connection_id = profile.connection_id + u.sso_idp_id = profile.idp_id + u.first_name = profile.first_name + u.last_name = profile.last_name + u.email = profile.email + + # TODO(ezekg) eventually implement workos groups? + u.grant_role! :admin + end + end + + # keep the user's attributes up-to-date with the IdP + user.assign_attributes( + sso_profile_id: profile.id, + sso_connection_id: profile.connection_id, + sso_idp_id: profile.idp_id, + first_name: profile.first_name, + last_name: profile.last_name, + email: profile.email, + ) + + user.save!(validate:) if save + + user + end + + def raise_on_request_error!(request) + if (code, message = request.query_parameters.values_at(:error, :error_description)).any? + raise Keygen::Error::InvalidSingleSignOnError.new(message, code: "SSO_#{code.upcase}") + end + end + + def raise_on_state_error!(state, account:, profile:) + unless state.blank? + value = decrypt(state, secret_key: account.secret_key).with_indifferent_access + + # assert the profile's email matches the email that initiated the authn + unless profile.email == value[:email] + raise Keygen::Error::InvalidSingleSignOnError.new('email is invalid') + end + end + end + + private + + def redirect_uri = Rails.application.routes.url_helpers.sso_callback_url + + def encrypt(plaintext, secret_key:) + crypt = ActiveSupport::MessageEncryptor.new(derive_key(secret_key), serializer: JSON) + enc = crypt.encrypt_and_sign(plaintext) + .split('--') + .map { |s| Base64.urlsafe_encode64(Base64.strict_decode64(s), padding: false) } + .join('.') + + enc + rescue => e + Keygen.logger.error { "[sso.encrypt] Encrypt failed: err=#{e.message}" } + + nil + end + + def decrypt(ciphertext, secret_key:) + crypt = ActiveSupport::MessageEncryptor.new(derive_key(secret_key), serializer: JSON) + enc = ciphertext.split('.') + .map { |s| Base64.strict_encode64(Base64.urlsafe_decode64(s)) } + .join('--') + + crypt.decrypt_and_verify(enc) + rescue => e + Keygen.logger.warn { "[sso.decrypt] Decrypt failed: err=#{e.message}" } + + nil + end + + def derive_key(secret_key) + keygen = ActiveSupport::KeyGenerator.new(secret_key) + salt = 'sso'.freeze + + keygen.generate_key(salt, 32) + end + end + end +end From 28c685dfb0a41d0aab4eac886dfb86dd15774267 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 15:38:53 -0500 Subject: [PATCH 08/14] fix ignored sso provider --- app/controllers/concerns/authentication.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 47ff5926fc..aaa07a7110 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -153,7 +153,7 @@ def query_token_authenticator(query_token) def http_password_authenticator(username = nil, password = nil) if current_account.sso? && current_account.sso_organization_domains.any? { username.ends_with?(_1) } # for JIT-user-provisioning - redirect = Keygen::SSO.authorization_url(account: current_account, email: username) + redirect = sso_authorization_url_for(username) raise Keygen::Error::SingleSignOnRequiredError.new(links: { redirect: }) end @@ -166,7 +166,7 @@ def http_password_authenticator(username = nil, password = nil) end if user.single_sign_on_enabled? - redirect = Keygen::SSO.authorization_url(account: current_account, email: user.email) + redirect = sso_authorization_url_for(user) raise Keygen::Error::SingleSignOnRequiredError.new(links: { redirect: }) end @@ -370,4 +370,15 @@ def authentication_value auth_value end + + def sso_authorization_url(email) = Keygen::SSO.authorization_url(account: current_account, provider: sso_provider, email:) + def sso_provider = request.filtered_parameters.dig(:meta, :provider) + def sso_authorization_url_for(user_or_email) + case user_or_email + in User => user + sso_authorization_url(user.email) + in String => email + sso_authorization_url(email) + end + end end From 55514076beadfc067def9105eadcf65d3549003f Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Tue, 16 Jul 2024 15:57:40 -0500 Subject: [PATCH 09/14] refactor org domain matching --- app/controllers/concerns/authentication.rb | 11 +++++++---- app/models/account.rb | 8 ++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index aaa07a7110..26604faea8 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -151,15 +151,18 @@ def query_token_authenticator(query_token) end end - def http_password_authenticator(username = nil, password = nil) - if current_account.sso? && current_account.sso_organization_domains.any? { username.ends_with?(_1) } # for JIT-user-provisioning - redirect = sso_authorization_url_for(username) + def http_password_authenticator(email = nil, password = nil) + raise Keygen::Error::InvalidCredentialsError.new(header: 'Authorization') if + email.blank? + + if current_account.sso? && current_account.sso_for?(email) # for JIT-user-provisioning + redirect = sso_authorization_url_for(email) raise Keygen::Error::SingleSignOnRequiredError.new(links: { redirect: }) end user = current_account.users.for_environment(current_environment, strict: current_environment.nil?) - .find_by(email: "#{username}".downcase) + .find_by(email: "#{email}".downcase) unless user.present? raise Keygen::Error::InvalidCredentialsError.new(header: 'Authorization') diff --git a/app/models/account.rb b/app/models/account.rb index df6ac8dfd9..185441943c 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -290,6 +290,14 @@ def protected? end def sso? = sso_organization_id? + def sso_for?(email) + return false if email.blank? + + _, domain = email.downcase.match(/([^@]+)@(.+)/) + .captures + + domain.in?(sso_organization_domains) + end def status billing&.state&.upcase From 368020b97e12db76aba0102a5a0c1026234b4400 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Thu, 18 Jul 2024 22:08:57 -0500 Subject: [PATCH 10/14] update ee features --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 546a65df96..0c0de365e4 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,8 @@ Keygen Enterprise Edition: - **Environments**: manage separate environments within a Keygen account, from test environments, to a sandbox, to QA, to production. - **Permissions**: enterprise-grade roles and permissions. -- **SSO/SAML**: support for SSO/SAML coming soon. +- **Import/export**: migrate from Keygen Cloud to Keygen EE. +- **SSO/SAML**: support for SSO/SAML/OAuth. Keygen uses Keygen EE in production to run Keygen Cloud, which is used to license Keygen EE. It's ~~turtles~~ Keygens all the way down (we love From ccaf9dbf7146177865fede3e6a52426e9c39b487 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Thu, 18 Jul 2024 22:18:39 -0500 Subject: [PATCH 11/14] add comment on session nonce --- app/controllers/concerns/authentication.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 26604faea8..bce3a24ec9 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -124,6 +124,8 @@ def http_session_authenticator(session) user = current_account.users.for_environment(current_environment, strict: current_environment.nil?) .find_by(id: session[:user_id]) + # Currently we only allow 1 session per-user, meaning if the session + # nonce doesn't match then the current session is outdated. unless user.present? && user.account_id == session[:account_id] && user.session_nonce == session[:nonce] session.destroy # clear cookie From 2948973b77a2a0fc4157db268c2a309b3ddac11f Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Thu, 18 Jul 2024 22:43:29 -0500 Subject: [PATCH 12/14] add current vars --- app/controllers/concerns/authentication.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index bce3a24ec9..985c77c9e5 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -121,6 +121,10 @@ def http_session_authenticator(session) return nil if current_account.nil? || session.nil? + @current_http_scheme = :session + @current_http_token = nil + @current_token = nil + user = current_account.users.for_environment(current_environment, strict: current_environment.nil?) .find_by(id: session[:user_id]) From d9099708970bf01a7c3320655761c88c0e479e22 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Fri, 19 Jul 2024 20:52:28 -0500 Subject: [PATCH 13/14] remove rescues --- lib/keygen/sso.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/keygen/sso.rb b/lib/keygen/sso.rb index e28c3133aa..412827a0ef 100644 --- a/lib/keygen/sso.rb +++ b/lib/keygen/sso.rb @@ -99,10 +99,6 @@ def encrypt(plaintext, secret_key:) .join('.') enc - rescue => e - Keygen.logger.error { "[sso.encrypt] Encrypt failed: err=#{e.message}" } - - nil end def decrypt(ciphertext, secret_key:) @@ -112,10 +108,6 @@ def decrypt(ciphertext, secret_key:) .join('--') crypt.decrypt_and_verify(enc) - rescue => e - Keygen.logger.warn { "[sso.decrypt] Decrypt failed: err=#{e.message}" } - - nil end def derive_key(secret_key) From 2a208bf4bb5bfce8012d94cbee1f98f775345544 Mon Sep 17 00:00:00 2001 From: Zeke Gabrielse Date: Fri, 19 Jul 2024 21:52:52 -0500 Subject: [PATCH 14/14] refactor url concern --- app/controllers/auth/sso_controller.rb | 2 -- config/application.rb | 2 +- config/initializers/zietwork.rb | 12 +++--------- config/routes.rb | 4 ++-- lib/keygen.rb | 4 +++- lib/keygen/{url.rb => url_for.rb} | 9 ++++++--- 6 files changed, 15 insertions(+), 18 deletions(-) rename lib/keygen/{url.rb => url_for.rb} (85%) diff --git a/app/controllers/auth/sso_controller.rb b/app/controllers/auth/sso_controller.rb index 5227fdfc4c..cbc120d3a7 100644 --- a/app/controllers/auth/sso_controller.rb +++ b/app/controllers/auth/sso_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true module Auth - KEYGEN_PORTAL_HOST = ENV.fetch('KEYGEN_PORTAL_HOST') { 'portal.keygen.sh' } - class SsoController < Api::V1::BaseController include ActionController::Cookies diff --git a/config/application.rb b/config/application.rb index 9b71fd7bdd..c53cadfcb7 100644 --- a/config/application.rb +++ b/config/application.rb @@ -36,7 +36,7 @@ class Application < Rails::Application # Use cookies for sessions config.session_store :cookie_store, key: '_keygen_session', - domain: ENV.fetch('KEYGEN_PORTAL_HOST') { 'portal.keygen.sh' }, + domain: Keygen::PORTAL_HOST, expire_after: 1.day, httponly: true, secure: true diff --git a/config/initializers/zietwork.rb b/config/initializers/zietwork.rb index 296d42cbf3..29f4438261 100644 --- a/config/initializers/zietwork.rb +++ b/config/initializers/zietwork.rb @@ -4,14 +4,8 @@ # FIXME(ezekg) Should we rename these to follow conventions? autoloader.inflector.inflect( 'digest_io' => 'DigestIO', - 'jsonapi' => 'JSONAPI', - 'ee' => 'EE', - 'ldap' => 'LDAP', - 'saml' => 'SAML', - 'sso' => 'SSO', - 'idp' => 'IdP', - 'sp' => 'SP', - 'uri' => 'URI', - 'url' => 'URL', + 'jsonapi' => 'JSONAPI', + 'ee' => 'EE', + 'sso' => 'SSO', ) end diff --git a/config/routes.rb b/config/routes.rb index c5bf80dd1d..48f8a6d472 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -552,12 +552,12 @@ # Route helper for redirecting to Portal direct :portal do |segment, options| - Keygen::URL.portal_url(segment, **options) + Keygen.portal_url(segment, **options) end # Route helpers for redirecting to docs direct :docs do |segment, options| - Keygen::URL.docs_url(segment, **options) + Keygen.docs_url(segment, **options) end %w[500 503].each do |code| diff --git a/lib/keygen.rb b/lib/keygen.rb index 7dbfb808da..7bc4255db1 100644 --- a/lib/keygen.rb +++ b/lib/keygen.rb @@ -11,9 +11,11 @@ require_relative 'keygen/exporter' require_relative 'keygen/importer' require_relative 'keygen/sso' -require_relative 'keygen/url' +require_relative 'keygen/url_for' module Keygen + include UrlFor + PUBLIC_KEY = %(\xB8\xF3\xEBL\xD2`\x13_g\xA5\tn\x8D\xC1\xC9\xB9\xDC\xB8\x1E\xE9\xFEP\xD1,\xDC\xD9A\xF6`z\x901).freeze class << self diff --git a/lib/keygen/url.rb b/lib/keygen/url_for.rb similarity index 85% rename from lib/keygen/url.rb rename to lib/keygen/url_for.rb index 7680ef72b3..9d99183db2 100644 --- a/lib/keygen/url.rb +++ b/lib/keygen/url_for.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true module Keygen - module URL - PORTAL_BASE_URL = 'https://portal.keygen.sh'.freeze + module UrlFor + extend ActiveSupport::Concern + + PORTAL_HOST = ENV.fetch('KEYGEN_PORTAL_HOST') { 'portal.keygen.sh' }.freeze + PORTAL_BASE_URL = "https://#{PORTAL_HOST}".freeze DOCS_BASE_URL = 'https://keygen.sh/docs/api'.freeze - class << self + class_methods do def portal_url(record_or_path = nil, **) = case record_or_path in Account => account url_for(PORTAL_BASE_URL, path: account.slug, **)