def __init__(self, connection_config, reauth_time, auth_attrib) -> None: ''' Args: connection_config (Dict): Parameters required to connect to the Okta API reauth_time (int): The min time in seconds to cache auth requests auth_attrib (str): The attribute of the user record that will be used to authenticate them. ''' super().__init__(reauth_time, auth_attrib) connection_config['pathname'] = '/api/v1/users' self.usersclient = UsersClient(**connection_config) self.factorsclient = FactorsClient(**connection_config) self.apiclient = ApiClient(**connection_config) # Maintain a per user lookup for poll URL self.poll_url = {}
def _create_factor_client(okta_org, okta_api_key): """ Create Okta FactorsClient :param okta_org: Okta organization name :param okta_api_key: Okta API Key :return: Instance of FactorsClient """ # https://github.com/okta/okta-sdk-python/blob/master/okta/FactorsClient.py factor_client = FactorsClient( base_url=f"https://{okta_org}.okta.com/", api_token=okta_api_key, ) return factor_client
def _get_factor_for_user_id(factor_client: FactorsClient, user_id: str) -> List[Factor]: """ Get factor for user from the Okta server :param factor_client: factor client :param user_id: user to fetch the data from :return: Array of user factor information """ try: factor_results = factor_client.get_lifecycle_factors(user_id) except OktaError as okta_error: logger.debug( f"Unable to get factor for user id {user_id} with " f"error code {okta_error.error_code} with description {okta_error.error_summary}", ) return [] return factor_results
class AuthClient(BaseAuthClient): def __init__(self, connection_config, reauth_time, auth_attrib) -> None: ''' Args: connection_config (Dict): Parameters required to connect to the Okta API reauth_time (int): The min time in seconds to cache auth requests auth_attrib (str): The attribute of the user record that will be used to authenticate them. ''' super().__init__(reauth_time, auth_attrib) connection_config['pathname'] = '/api/v1/users' self.usersclient = UsersClient(**connection_config) self.factorsclient = FactorsClient(**connection_config) self.apiclient = ApiClient(**connection_config) # Maintain a per user lookup for poll URL self.poll_url = {} def _get_okta_userid(self, username): user = self.usersclient.get_users(query=username, limit=1) try: return user[0].id except Exception as error: logging.error('Error getting username {}'.format(error)) return None def _get_factors(self, userid): try: return self.factorsclient.get_lifecycle_factors(userid) except Exception as error: logging.error('Error getting factors {}'.format(error)) return None def can_auth(self, user): # type: () -> bool # Check Okta user for a push factor. # Returns false is not available # Returns factor Id if it is # TODO: Add support for other types of auth (TOTP, etc). username = self._auth_attribute(user) if username is not False: logging.debug('Checking auth capabilities for {}'.format(username)) okta_user_id = self._get_okta_userid(username) factors = self._get_factors(okta_user_id) if factors is not None: for factor in factors: if factor.factorType == 'push': return factor.id return False def auth(self, user, reason=None): # type: (str) -> None logging.debug('Sending Okta Push request for {}'.format( self._auth_attribute(user))) # Okta's SDK is broken! # https://github.com/okta/okta-sdk-python/issues/66 # res = self.factorsclient.verify_factor( # user_id=self.okta_user_id, # user_factor_id=self.okta_push_factor_id # ) # Implement our own call which actually works okta_user_id = self._get_okta_userid(self._auth_attribute(user)) res = self.apiclient.post_path('/{0}/factors/{1}/verify'.format( okta_user_id, user._factor_id)) try: res_obj = json.loads(res.text) except Exception as error: raise AuthException(error) self.poll_url[okta_user_id] = res_obj['_links']['poll']['href'] user._last_auth_state = AuthStates.PENDING def auth_status(self, user): # type: () -> int okta_user_id = self._get_okta_userid(self._auth_attribute(user)) if user._last_auth_state == AuthStates.PENDING: response = self.apiclient.get(self.poll_url[okta_user_id]) response_obj = json.loads(response.text) res = response_obj['factorResult'] if res != 'WAITING': if res == 'SUCCESS': user._last_auth_state = AuthStates.AUTHORIZED user._last_auth_time = datetime.now(tz=pytz.utc) else: user._last_auth_state = AuthStates.DENIED user._last_auth_time = datetime.min elif user._last_auth_state == AuthStates.AUTHORIZED: if not self._recently_authed(user): user._last_auth_state = AuthStates.NONE return user._last_auth_state def reset(self, user): okta_user_id = self._get_okta_userid(self._auth_attribute(user)) self.poll_url.pop(okta_user_id, None) user._last_auth_state = AuthStates.NONE
import time from okta import UsersClient from okta import FactorsClient site = 'Your Site' skey = 'Your Key' usersClient = UsersClient(site, skey) factorClient = FactorsClient(site, skey) currentDate = time.strftime('%Y%m%d') lst = [] users = usersClient.get_paged_users() while True: for user in users.result: if user.status == 'ACTIVE': # Get only active users lst.append(user) if not users.is_last_page(): # Keep on fetching pages of users until the last page users = usersClient.get_paged_users(url=users.next_url) else: break EnrolledUsers = open('C:\\temp\\EnrolledUsers' + currentDate + '.csv', 'w+') EnrolledUsers.write( "Username,FactorType,UserID,DateEnrolled,TimeEnrolled") # Set CSV Headers for user in lst: lifecycle = factorClient.get_lifecycle_factors(user_id=user.id)
def tests_client_initializer_kwargs(self): client = FactorsClient(base_url='https://example.okta.com', api_token='api_key')
def tests_client_initializer_args(self): client = FactorsClient('https://example.okta.com', 'api_key')
from datetime import datetime from okta import UsersClient from okta import FactorsAdminClient from okta import FactorsClient # Get a users ID usersClient = UsersClient("Your Site", "Your Token") usersClient.get_user('Login Name').id # Or this: # usr = usersClient.get_user('Login Name').id # usr.id # Get a users factor, ID and time enrolled userClients = FactorsClient("Your Site", "Your Token") userClients = uclient.get_lifecycle_factors(user_id="User ID") for client in userClients: print(client.factorType, client.id, client.created) # Get the org's list of active factors factorClient = FactorsAdminClient("Your Site", "Your Token") clients = factorClient.get_org_factors() for client in clients: if client.status != 'NOT_SETUP' and client.status != 'INACTIVE': print(client.factorType, client.id, client.status) # Get all users enrollment date for a specific factor site = 'Your Site' skey = 'Your Key'