ui5-community / wdi5

official UI5 end-to-end test framework for UI5 web-apps. wdi5 = Webdriver.IO + UI5 Test API
https://ui5-community.github.io/wdi5/
Apache License 2.0
102 stars 43 forks source link

wdi5 authentication different behavior between localhost and real domain #589

Closed Archer57 closed 5 months ago

Archer57 commented 8 months ago

Describe the bug

When configuring authentication against a custom IdP and a base url against a locally running ui5 app that requires a valid session, wdi5 access the custom IdP, checks for the specified fields, authenticates with the configured credentials, sets a session cookie and accesses the local app. Result: wdi5 can access the local app and the tests run.

When configuring authentication against a custom IdP and a base url against a ui5 app that is deployed in a Cloud Foundry space, wdi5 doesn't access the custom IdP, goes to the deployed app with an unauthorized session and fails.

To Reproduce

  1. Create a custom Identity Provider on SAP BTP.
  2. Create an Cloud Foundry app that requires authentication against your custom IdP.
  3. Add the authentication part for BTP custom IdP in your wdio conf:
    "wdi5:authentication": { 
    provider: "BTP", 
    usernameSelector: "#j_username", 
    passwordSelector: "#j_password", 
    submitSelector: "#logOnFormSubmit", 
    idpDomain: "<your_custom_IdP>"
    }
  4. Set the environment variables wdi5_username and wdi5_password with valid credentials.
  5. Configure wdi5 to use your Cloud Foundry app in the baseUrl.
  6. Set the logLevel to debug.
  7. Run wdi5.

Expected behavior wdi5 can access the deployed app and the tests run.

Actual behavior wdi5 doesn't access the IdP and therefore is unable to access the deployed app.

Logs/Console Output Placeholders:

[0-0] 2024-02-15T08:16:48.452Z INFO webdriver: COMMAND navigateTo("<my_deployed_app_url>")
[0-0] 2024-02-15T08:16:48.452Z INFO webdriver: [POST] http://0.0.0.0:33197/session/b091ac3bb505986203ecd4932349e33f/url
[0-0] 2024-02-15T08:16:48.452Z INFO webdriver: DATA { url: '<my_deployed_app_url>' }
[0-0] 2024-02-15T08:16:48.669Z INFO webdriver: RESULT null
[0-0] 2024-02-15T08:16:48.671Z INFO webdriver: COMMAND getAllCookies()
[0-0] 2024-02-15T08:16:48.672Z INFO webdriver: [GET] http://0.0.0.0:33197/session/b091ac3bb505986203ecd4932349e33f/cookie
[0-0] 2024-02-15T08:16:48.682Z INFO webdriver: RESULT [
[0-0]   {
[0-0]     domain: '.<my_custom_domain>',
[0-0]     expiry: 1707986808,
[0-0]     httpOnly: true,
[0-0]     name: '__cf_bm',
[0-0]     path: '/',
[0-0]     sameSite: 'None',
[0-0]     secure: true,
[0-0]     value: '<some_cryptic_value>'
[0-0]   }
[0-0] ]
[0-0] 2024-02-15T08:16:48.685Z INFO webdriver: COMMAND findElement("css selector", "#j_username")
[0-0] 2024-02-15T08:16:48.685Z INFO webdriver: [POST] http://0.0.0.0:33197/session/b091ac3bb505986203ecd4932349e33f/element
[0-0] 2024-02-15T08:16:48.685Z INFO webdriver: DATA { using: 'css selector', value: '#j_username' }
[0-0] 2024-02-15T08:16:48.760Z INFO webdriver: RESULT {
[0-0]   error: 'no such element',
[0-0]   message: 'no such element: Unable to locate element: {"method":"css selector","selector":"#j_username"}\n' +
[0-0]     '  (Session info: headless chrome=118.0.5993.70)',
[0-0]   stacktrace: '#0 0x55a44aa19fb3 <unknown>\n' +
[0-0]     '#1 0x55a44a6ed4a7 <unknown>\n' +
[0-0]     '#2 0x55a44a734dd6 <unknown>\n' +
[0-0]     '#3 0x55a44a734ec1 <unknown>\n' +
[0-0]     '#4 0x55a44a772354 <unknown>\n' +
[0-0]     '#5 0x55a44a75696d <unknown>\n' +
[0-0]     '#6 0x55a44a76fc02 <unknown>\n' +
[0-0]     '#7 0x55a44a756713 <unknown>\n' +
[0-0]     '#8 0x55a44a72918b <unknown>\n' +
[0-0]     '#9 0x55a44a729f7e <unknown>\n' +
[0-0]     '#10 0x55a44a9df8d8 <unknown>\n' +
[0-0]     '#11 0x55a44a9e3800 <unknown>\n' +
[0-0]     '#12 0x55a44a9edcfc <unknown>\n' +
[0-0]     '#13 0x55a44a9e4418 <unknown>\n' +
[0-0]     '#14 0x55a44a9b142f <unknown>\n' +
[0-0]     '#15 0x55a44aa084e8 <unknown>\n' +
[0-0]     '#16 0x55a44aa086b4 <unknown>\n' +
[0-0]     '#17 0x55a44aa19143 <unknown>\n' +
[0-0]     '#18 0x7faae5458609 start_thread\n'
[0-0] }

Screenshots

Runtime Env (please complete the following information):

Additional context Add any other context about the problem here, e.g. any options the target browser is started with like --headless or if the tests run in a CI environment

Archer57 commented 8 months ago

In addition: I tested the "custom" provider in my configuration as well as BTP. The custom provider doesn't accept a "idpDomain" parameter, so I removed it. The result was the same: With localhost, my custom IdP get's accessed and wdi5 authenticates itself before accessing the app. When changing the base-url to a deployed version, wdi5 instead accesses the domain of the app configured in the base-url and tries to authenticate there, which fails.

vobu commented 7 months ago

what happens when you call up the deployed app by hand, in a browser? Does the authentication then work as expected?

Archer57 commented 7 months ago

what happens when you call up the deployed app by hand, in a browser? Does the authentication then work as expected?

Yes, the authentication works when accessing the deployed app manually.

vobu commented 7 months ago

when accessing the app manually, is the redirect app ā†’ IdP UI for credentials happening automatically, e.g. w/o manually choosing one of multiple available IdPs?

Archer57 commented 7 months ago

Because we have two IdPs in use, the redirect doesn't happen automatically. That's why I sepcified the "idpDomain" in the wdio conf.

vobu commented 7 months ago

then this is the root cause of it all ā„¢: wdi5 currently doesn't support > 1 IdPs with its authentication configuration. Providing idpDomain is only valid in an IAS-scenario and has no effect with a "custom IdP" config. ā†’ there'd be additional functionality necessary in https://github.com/ui5-community/wdi5/blob/main/src/lib/authentication/CustomAuthenticator.ts for making > 1 IdP configurable in wdi5 Want to give it a shot @Archer57 (hint hint nudge nudge)? šŸ˜ø

Archer57 commented 7 months ago

Thanks for the reply @vobu! This helps me for the most part and I may have a more detailed look into the code after my holidays. One question remaining: One of the two IdPs is a IAS-scenario where I intend to use the BTP authenticator. Shouldn't that work even if the app doesn't redirect to the IdP by default as long as I specify the "idpDomain"?

vobu commented 7 months ago

unfortunately not - in the IAS case, no automatic redirect is triggered via the idpDomain option. Instead, wdi5 uses the domain in idpDomain to set the appropriate cookie to prevent biometric auth requirements.

github-actions[bot] commented 6 months ago

hey šŸ‘‹ - silence for 30 days šŸ¤ ... anybody? šŸ˜€

Archer57 commented 6 months ago

Hi, quick update from my side:

I solved the problem by configuring a manual authentication in the before hook of the actual test run. First, I switched the setting skipInjectUI5OnStart to true so the Test doesn't crash when accessing the non-ui5 page of our uaa service. Then I perform the authentication steps using wdio and calling .injectUI5() at the end. Lastly, I moved my manual authentication to a seperate module so it can be imported & reused easily in every test case.

Thanks for the input here! Maybe this brings up an idea on how to handle uaa services with multiple IdPs, but regarding my case, the problem is solved.

github-actions[bot] commented 5 months ago

hey šŸ‘‹ - silence for 30 days šŸ¤ ... anybody? šŸ˜€