@@ -212,11 +212,14 @@ def _gen_sql(payload):
212
212
return sql + where
213
213
214
214
215
- #
216
- # Authentication session information for connecting to an OIDC instance. Assumes an OIDC system like Keycloak
217
- # with a preconfigured client called "oidc".
218
- #
219
215
class AlmaAuth (BaseQuery ):
216
+ """Authentication session information for passing credentials to an OIDC instance
217
+
218
+ Assumes an OIDC system like Keycloak with a preconfigured client app called "oidc" to validate against.
219
+ This does not use Tokens in the traditional OIDC sense, but rather uses the Keycloak specific endpoint
220
+ to validate a username and password. Passwords are then kept in a Python keyring.
221
+ """
222
+
220
223
_CLIENT_ID = 'oidc'
221
224
_GRANT_TYPE = 'password'
222
225
_INVALID_PASSWORD_MESSAGE = 'Invalid user credentials'
@@ -229,7 +232,12 @@ def __init__(self):
229
232
self ._auth_hosts = auth_urls
230
233
self ._auth_host = None
231
234
232
- def set_auth_hosts (self , auth_hosts ):
235
+ @property
236
+ def auth_hosts (self ):
237
+ return self ._auth_hosts
238
+
239
+ @auth_hosts .setter
240
+ def auth_hosts (self , auth_hosts ):
233
241
"""
234
242
Set the available hosts to check for login endpoints.
235
243
@@ -239,10 +247,12 @@ def set_auth_hosts(self, auth_hosts):
239
247
Available hosts name. Checking each one until one returns a 200 for
240
248
the well-known endpoint.
241
249
"""
242
- self ._auth_hosts = auth_hosts
250
+ if auth_hosts is None :
251
+ raise LoginError ('Valid authentication hosts cannot be None' )
252
+ else :
253
+ self ._auth_hosts = auth_hosts
243
254
244
- @property
245
- def host (self ):
255
+ def get_valid_host (self ):
246
256
if self ._auth_host is None :
247
257
for auth_url in self ._auth_hosts :
248
258
# set session cookies (they do not get set otherwise)
@@ -277,7 +287,7 @@ def login(self, username, password):
277
287
'client_id' : self ._CLIENT_ID
278
288
}
279
289
280
- login_url = f'https://{ self .host } { self ._LOGIN_ENDPOINT } '
290
+ login_url = f'https://{ self .get_valid_host () } { self ._LOGIN_ENDPOINT } '
281
291
log .info (f'Authenticating { username } on { login_url } .' )
282
292
login_response = self ._request ('POST' , login_url , data = data , cache = False )
283
293
json_auth = login_response .json ()
@@ -287,12 +297,12 @@ def login(self, username, password):
287
297
error_message = json_auth ['error_description' ]
288
298
if self ._INVALID_PASSWORD_MESSAGE not in error_message :
289
299
raise LoginError ("Could not log in to ALMA authorization portal: "
290
- f"{ self .host } Message from server: { error_message } " )
300
+ f"{ self .get_valid_host () } Message from server: { error_message } " )
291
301
else :
292
- log . error (error_message )
302
+ raise LoginError (error_message )
293
303
elif 'access_token' not in json_auth :
294
304
raise LoginError ("Could not log in to any of the known ALMA authorization portals: \n "
295
- f"No error from server, but missing access token from host: { self .host } " )
305
+ f"No error from server, but missing access token from host: { self .get_valid_host () } " )
296
306
else :
297
307
log .info (f'Successfully logged in to { self ._auth_host } ' )
298
308
@@ -965,7 +975,7 @@ def _get_auth_info(self, username, *, store_password=False,
965
975
else :
966
976
username = self .USERNAME
967
977
968
- auth_url = self .auth .host
978
+ auth_url = self .auth .get_valid_host ()
969
979
970
980
# Get password from keyring or prompt
971
981
password , password_from_keyring = self ._get_password (
@@ -995,7 +1005,7 @@ def _login(self, username=None, store_password=False,
995
1005
on the keyring. Default is False.
996
1006
"""
997
1007
998
- self .auth .set_auth_hosts ( auth_urls )
1008
+ self .auth .auth_hosts = auth_urls
999
1009
1000
1010
username , password = self ._get_auth_info (username = username ,
1001
1011
store_password = store_password ,
0 commit comments