1414# GNU Affero General Public License for more details.
1515
1616# Modified by OpenC3, Inc.
17- # All changes Copyright 2023 , OpenC3, Inc.
17+ # All changes Copyright 2026 , OpenC3, Inc.
1818# All Rights Reserved
1919#
2020# This file may also be used under the terms of a commercial license
@@ -37,12 +37,74 @@ def initialize()
3737 if @token . nil?
3838 raise OpenC3AuthenticationError , "Authentication requires environment variable OPENC3_API_PASSWORD"
3939 end
40+ @service = password == ENV [ 'OPENC3_SERVICE_PASSWORD' ]
41+ retry_faraday_request do
42+ response = _make_auth_request ( password )
43+ @token = response . body
44+ end
45+ if @token . nil? or @token . empty?
46+ raise OpenC3AuthenticationError , "Authentication failed. Please check the password in the environment variable OPENC3_API_PASSWORD"
47+ end
4048 end
4149
4250 # Load the token from the environment
4351 def token ( include_bearer : true )
4452 @token
4553 end
54+
55+ def get_otp ( scope : 'DEFAULT' )
56+ if @token . nil? or @token . empty?
57+ raise OpenC3AuthenticationError , "Uninitialized authentication: unable to get OTP"
58+ end
59+ retry_faraday_request do
60+ response = _make_otp_request ( scope : scope )
61+ return response . body
62+ end
63+ end
64+
65+ def _make_auth_request ( password )
66+ Faraday . new . post ( _generate_auth_url , '{"password": "' + password + '"}' , { 'Content-Type' => 'application/json' } )
67+ end
68+
69+ def _make_otp_request ( scope : 'DEFAULT' )
70+ params = {
71+ 'scope' => scope
72+ }
73+ headers = {
74+ 'Authorization' => token ,
75+ }
76+ Faraday . new . get ( _generate_auth_url ( '/auth/otp' ) , params , headers )
77+ end
78+
79+ def _generate_auth_url ( endpoint = nil )
80+ schema = ENV [ 'OPENC3_API_SCHEMA' ] || 'http'
81+ hostname = ENV [ 'OPENC3_API_HOSTNAME' ] || ( ENV [ 'OPENC3_DEVEL' ] ? '127.0.0.1' : 'openc3-cosmos-cmd-tlm-api' )
82+ port = ENV [ 'OPENC3_API_PORT' ] || '2901'
83+ port = port . to_i
84+ unless endpoint
85+ endpoint = if @service
86+ "auth/verify_service"
87+ else
88+ "auth/verify"
89+ end
90+ end
91+ return "#{ schema } ://#{ hostname } :#{ port } /openc3-api/#{ endpoint } "
92+ end
93+
94+ def retry_faraday_request ( max_retries : 3 )
95+ retries = 0
96+ begin
97+ yield
98+ rescue Faraday ::ConnectionFailed , Faraday ::TimeoutError => e
99+ retries += 1
100+ if retries <= max_retries
101+ STDOUT . puts "Authentication request failed (attempt #{ retries } /3): #{ e . message } . Retrying in #{ retries } s..."
102+ sleep ( retries )
103+ retry
104+ end
105+ raise
106+ end
107+ end
46108 end
47109
48110 # OpenC3 enterprise Keycloak authentication code
0 commit comments