Skip to content

Commit e956fe3

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents fd1817b + 1cf1789 commit e956fe3

File tree

1 file changed

+57
-14
lines changed

1 file changed

+57
-14
lines changed

src/sasctl/core.py

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,13 @@ class Session(requests.Session):
260260
to true. Ignored for HTTP connections.
261261
token : str, optional
262262
OAuth token to use for authorization.
263+
client_id : str, optional
264+
Client ID requesting access. Use if connection to Viya should be
265+
made using `client_credentials` method.
266+
client_secret : str, optional
267+
Client secret for client requesting access. Required if `client_id`
268+
is provided.
269+
263270
264271
Attributes
265272
----------
@@ -285,6 +292,8 @@ def __init__(
285292
port=None,
286293
verify_ssl=None,
287294
token=None,
295+
client_id=None,
296+
client_secret=None
288297
):
289298
super(Session, self).__init__()
290299

@@ -373,7 +382,7 @@ def is_ipaddress(hst):
373382
"password": password,
374383
}
375384

376-
if self._settings["password"] is None:
385+
if self._settings["password"] is None and client_secret is None:
377386
# Try to get credentials from .authinfo or .netrc files.
378387
# If no file path was specified, the default locations will
379388
# be checked.
@@ -408,7 +417,8 @@ def is_ipaddress(hst):
408417

409418
# Find a suitable authentication mechanism and build an auth header
410419
self.auth = self.get_auth(
411-
self._settings["username"], self._settings["password"], token
420+
self._settings["username"], self._settings["password"], token,
421+
client_id=client_id, client_secret=client_secret
412422
)
413423

414424
# Used for context manager
@@ -686,20 +696,39 @@ def head(self, url, **kwargs):
686696
def delete(self, url, **kwargs):
687697
return self.request("DELETE", url, **kwargs)
688698

689-
def get_auth(self, username=None, password=None, token=None):
699+
def get_auth(
700+
self,
701+
username=None,
702+
password=None,
703+
token=None,
704+
client_id=None,
705+
client_secret=None
706+
):
690707
"""Attempt to authenticate with the Viya environment.
691708
692-
If `username` and `password` or `token` are provided, they will be used exclusively. If neither of these
693-
is specified, Kerberos authorization will be attempted. If this fails, authorization using an
694-
OAuth2 authorization code will be attempted. Be aware that this requires prompting the user for input and
709+
If `username` and `password` or `token` are provided, they will be used
710+
exclusively. Alternatively `client_id` and `client_secret` can be
711+
provided without `username` and `password` which will result in
712+
authentication using `client_credentials` flow. If neither of these is
713+
specified, Kerberos authorization will be attempted. If this fails,
714+
authorization using an OAuth2 authorization code will be attempted.
715+
Be aware that this requires prompting the user for input and
695716
should NOT be used in a non-interactive session.
696717
697718
Parameters
698719
----------
699720
username : str, optional
700721
Username to use for authentication.
701722
password : str, optional
702-
Password to use for authentication. Required if `username` is provided.
723+
Password to use for authentication. Required if `username` is
724+
provided.
725+
client_id : str, optional
726+
Client ID requesting access. Use if connection to Viya should be
727+
made using a `client_credentials` method.
728+
client_secret : str, optional
729+
Client secret for client requesting access. Required if `client_id`
730+
is provided.
731+
703732
token : str, optional
704733
An existing OAuth2 access token to use.
705734
@@ -711,8 +740,15 @@ def get_auth(self, username=None, password=None, token=None):
711740
"""
712741

713742
# If explicit username & password were provided, use them.
714-
if username is not None and password is not None:
715-
return self.get_oauth_token(username, password)
743+
if username and password:
744+
return self.get_oauth_token(
745+
username, password
746+
)
747+
if client_id is not None and client_secret is not None:
748+
return self.get_oauth_token(
749+
client_id=client_id,
750+
client_secret=client_secret
751+
)
716752

717753
# If an existing access token was provided, use it
718754
if token is not None:
@@ -745,22 +781,27 @@ def get_oauth_token(
745781
client_id=None,
746782
client_secret=None,
747783
):
748-
"""Request an OAuth2 access token using either a username & password or an auth token.
784+
"""Request an OAuth2 access token using either a username & password,
785+
client_id and client_secret, or an auth token.
749786
750787
Parameters
751788
----------
752789
username : str, optional
753790
Username to use for authentication.
754791
password : str, optional
755-
Password to use for authentication. Required if `username` is provided.
792+
Password to use for authentication. Required if `username` is
793+
provided.
756794
auth_code : str, optional
757795
Authorization code to use.
758796
refresh_token : str, optinoal
759797
Valid refresh token to use.
760798
client_id : str, optional
761-
Client ID requesting access. Use if connection to Viya should be made using a non-default client id.
799+
Client ID requesting access. Use if connection to Viya should be
800+
made using a non-default client id or using `client_credentials`
801+
method.
762802
client_secret : str, optional
763-
Client secret for client requesting access. Required if `client_id` is provided
803+
Client secret for client requesting access. Required if `client_id`
804+
is provided.
764805
765806
Returns
766807
-------
@@ -778,6 +819,8 @@ def get_oauth_token(
778819
"username": username,
779820
"password": password,
780821
}
822+
elif username is None and client_secret is not None:
823+
data = {"grant_type": "client_credentials"}
781824
elif auth_code is not None:
782825
data = {"grant_type": "authorization_code", "code": auth_code}
783826
elif refresh_token is not None:
@@ -830,7 +873,7 @@ def get_oauth_token(
830873

831874
# No reason to cache token if username & password were provided - they'd just be re-provided on future
832875
# connections. Cache for auth code & refresh token to prevent frequent interruptions for the user.
833-
if username is None:
876+
if username is None and client_secret is None:
834877
self.cache_token(token, self.PROFILE_PATH)
835878

836879
return token

0 commit comments

Comments
 (0)