Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle ibkey promo #69

Merged
merged 5 commits into from
Mar 15, 2022
Merged

Conversation

JackD111
Copy link
Contributor

This fixes #68 by handling the promo item visibility as a successful auth

Copy link

@blaney83 blaney83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with local docker build and changes work as expected.

@JackD111
Copy link
Contributor Author

JackD111 commented Mar 11, 2022

I noticed, that not clicking the continue button of the ibkey promo caused the gateway to not always be authenticated. The continue button is now clicked

@blaney83
Copy link

@JackD111 thanks. I commented after seeing the application progress further, but also ended up adding some click handling as well. Unfortunately, still running into a raft of issues, but as for the promo, click handling is essential.

@Voyz
Copy link
Owner

Voyz commented Mar 11, 2022

Fantastic contribution @JackD111 thank you for putting this together 👍 Also thumbs up to @DanielHTpg who suggested the workaround with treating the promo as a success state.

I'd be happy to merge that right in - the code is immaculate 👏 - however I wonder, is this the right place we'd want to be calling it? @JackD111 in #68 you mention:

It seems, IB added a new advertisement for accounts without 2FA, which advertises the IB Key app

But I notice in #62 (comment) that it also happens when completing a 2FA request.

I can see that your addition happens before handling 2FA. Shouldn't it happen after 2FA attempt, if one happens?

In such case I think the ibkey_promo_skip_displayed - apart from being added to the first wait statement like you did - should also be added to the wait statement in the 2FA handling block:

trigger = WebDriverWait(driver, var.OAUTH_TIMEOUT).until(any_of(success_present, error_displayed))

And the if trigger_class == var.IBKEY_PROMO_EL_CLASS: segment should happen just before this if statement:

if trigger_id == var.ERROR_EL_ID:

Please let me know if this makes sense and feel free to disagree 👍 Also thanks for reviewing and testing this PR @blaney83 👏

Thanks a lot guys! Voy

@Voyz Voyz self-requested a review March 11, 2022 12:54
@Voyz Voyz self-assigned this Mar 11, 2022
@Voyz Voyz added the enhancement New feature or request label Mar 11, 2022
@JackD111
Copy link
Contributor Author

JackD111 commented Mar 11, 2022

@Voyz Oh, I didn't think that they would display the promo login even for accounts that use 2FA. I implemented it in that order because I assumed, we wouldn't need to handle promo with 2FA enabled accounts.

Doing it like this should handle non 2FA accounts as well as 2FA enabled accounts (untested):

....
            # observe results - either success or 2FA request
            success_present = text_to_be_present_in_element([(By.TAG_NAME, 'pre'), (By.TAG_NAME, 'body')],
                                                            var.SUCCESS_EL_TEXT)
            two_factor_input_present = EC.visibility_of_element_located((By.ID, var.TWO_FA_EL_ID))
            error_displayed = EC.visibility_of_element_located((By.ID, var.ERROR_EL_ID))
            ibkey_promo_skip_displayed = EC.visibility_of_element_located((By.CSS_SELECTOR, var.IBKEY_PROMO_EL_SELECTOR))

            trigger = WebDriverWait(driver, var.OAUTH_TIMEOUT).until(
                any_of(success_present, two_factor_input_present, error_displayed, ibkey_promo_skip_displayed))

            trigger_id = trigger.get_attribute('id')

            # handle 2FA
            if trigger_id == var.TWO_FA_EL_ID:
                _LOGGER.info(f'Credentials correct, but Gateway requires two-factor authentication.')
                if two_fa_handler is None:
                    _LOGGER.critical(
                        f'######## ATTENTION! ######## No 2FA handler found. You may define your own 2FA handler or use built-in handlers. See documentation for more: https://github.com/Voyz/ibeam/wiki/Two-Factor-Authentication')
                    return False, True

                two_fa_code = handle_two_fa(two_fa_handler)

                if two_fa_code is None:
                    _LOGGER.warning(f'No 2FA code returned. Aborting authentication.')
                else:
                    two_fa_el = driver.find_elements_by_id(var.TWO_FA_INPUT_EL_ID)
                    WebDriverWait(driver, var.OAUTH_TIMEOUT).until(
                        EC.element_to_be_clickable((By.ID, var.TWO_FA_INPUT_EL_ID)))
                    two_fa_el[0].send_keys(two_fa_code)

                    _LOGGER.debug('Submitting the 2FA form')
                    submit_form_el = driver.find_element_by_id(var.SUBMIT_EL_ID)
                    WebDriverWait(driver, var.OAUTH_TIMEOUT).until(
                        EC.element_to_be_clickable((By.ID, var.SUBMIT_EL_ID)))
                    submit_form_el.click()

                    trigger = WebDriverWait(driver, var.OAUTH_TIMEOUT).until(
	                any_of(success_present, ibkey_promo_skip_displayed, error_displayed))
                    trigger_id = trigger.get_attribute('id')

	    trigger_class = trigger.get_attribute('class')

            if trigger_class == var.IBKEY_PROMO_EL_CLASS:
                _LOGGER.debug('Handling IB-Key promo display...')
                ibkey_promo_el = WebDriverWait(driver, 10).until(
                    EC.element_to_be_clickable((By.CSS_SELECTOR, var.IBKEY_PROMO_EL_SELECTOR)))
                ibkey_promo_el.click()
                WebDriverWait(driver, 10).until(success_present)

            if trigger_id == var.ERROR_EL_ID:
                _LOGGER.error(f'Error displayed by the login webpage: {trigger.text}')
.....

I don't have an account that has non IB Key 2FA so I can't test the 2FA part but the order of the handling should cover both scenarios.

@JackD111
Copy link
Contributor Author

@Voyz The latest commit should now handle the case of the promo apprearing after 2FA

Copy link
Owner

@Voyz Voyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for introducing the changes @JackD111 👏

Just pulled your repo and tested the code - things seem to be in order. Just left a small comment in code after which I'll be happy to merge this in 👍

Went ahead and published voyz/ibeam:0.4.0-rc9 with this change in case anyone would like to test it as an image already

ibeam/src/var.py Outdated
@@ -105,6 +105,12 @@
MAX_IMMEDIATE_ATTEMPTS = int(os.environ.get('IBEAM_MAX_IMMEDIATE_ATTEMPTS', 10))
"""Maximum number of immediate retries upon detecting an error message."""

IBKEY_PROMO_EL_SELECTOR = os.environ.get('IBEAM_IBKEY_PROMO_EL_SELECTOR', 'a.ibkey-promo-skip')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @JackD111 just wondering - why a separate EL_CLASS and EL_SELECTOR variables? Couldn't

ibkey_promo_skip_clickable = EC.element_to_be_clickable((By.CSS_SELECTOR, var.IBKEY_PROMO_EL_SELECTOR))

use var.IBKEY_PROMO_EL_CLASS instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had another look into the documentation and found a By.CLASS_NAME which I didn't notice before when writing the code. I updated the code to use that instead and made the IBKEY_PROMO_EL_SELECTOR var obsolete.

Copy link
Owner

@Voyz Voyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job @JackD111 thanks for putting this PR together and addressing my comments. Happy to merge it in 👍

@Voyz Voyz merged commit 99ca472 into Voyz:reauthentication-v2 Mar 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants