diff --git a/openc3-cosmos-cmd-tlm-api/app/controllers/users_controller.rb b/openc3-cosmos-cmd-tlm-api/app/controllers/users_controller.rb index c544d7dd2f..1074be3153 100644 --- a/openc3-cosmos-cmd-tlm-api/app/controllers/users_controller.rb +++ b/openc3-cosmos-cmd-tlm-api/app/controllers/users_controller.rb @@ -21,7 +21,12 @@ def active() end def logout() - OpenC3::AuthModel.logout + # Require a valid token so logout is not reachable unauthenticated (CWE-306) + return unless authorization('system') + # Terminate only the caller's own session token (from the Authorization + # header), not the entire global sessions store, so one user logging out + # does not log out every other operator. + OpenC3::AuthModel.terminate(request.headers['HTTP_AUTHORIZATION']) head :ok end end diff --git a/openc3-cosmos-cmd-tlm-api/spec/controllers/users_controller_spec.rb b/openc3-cosmos-cmd-tlm-api/spec/controllers/users_controller_spec.rb index 84d615e967..7cc274d3d8 100644 --- a/openc3-cosmos-cmd-tlm-api/spec/controllers/users_controller_spec.rb +++ b/openc3-cosmos-cmd-tlm-api/spec/controllers/users_controller_spec.rb @@ -17,9 +17,10 @@ expect(response).to have_http_status(:ok) end - it "Logout" do - allow(OpenC3::AuthModel).to receive(:logout) - put :logout, params: {user: "user"} + it "Logout terminates only the caller's own session token" do + request.headers['HTTP_AUTHORIZATION'] = 'ses_mytoken' + expect(OpenC3::AuthModel).to receive(:terminate).with('ses_mytoken') + put :logout, params: {user: "user", scope: "DEFAULT"} expect(response).to have_http_status(:ok) end end diff --git a/openc3/lib/openc3/utilities/env_helper.rb b/openc3/lib/openc3/utilities/env_helper.rb index 31b416ef44..fc0e8e0dac 100644 --- a/openc3/lib/openc3/utilities/env_helper.rb +++ b/openc3/lib/openc3/utilities/env_helper.rb @@ -1,4 +1,16 @@ -# For simple boolean flags +# encoding: ascii-8bit + +# Copyright 2026 OpenC3, Inc. +# All Rights Reserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE.md for more details. +# +# This file may also be used under the terms of a commercial license +# if purchased from OpenC3, Inc. + class EnvHelper def self.enabled?(key) ['true', '1', 'yes', 'on'].include?(ENV[key].to_s.downcase)