This site is currently read-only as we are migrating to Oracle Forums for an improved community experience. You will not be able to initiate activity until January 30th, when you will be able to use this site as normal.

    Forum Stats

  • 3,889,961 Users
  • 2,269,775 Discussions
  • 7,916,823 Comments

Discussions

Throttle message displayed on Login page but the seconds value does not count down remaining seconds

Nazbit
Nazbit Member Posts: 34 Bronze Badge

Hi,

I wonder if anyone might be able to help with this?

I am having a problem with my login page when incorrect credentials are entered the throttling message "Invalid Login Credentials Please wait 5 seconds to login again." Is being displayed as expected BUT the numeric seconds value in the warning message does not count down the remaining seconds until the user can login again.

E.G: It says 5 seconds as rendered and stays at that value forever when it should say 5…4, 3, 2, 1.

I found a couple of similar threads where it was identified that the relevant JS has not been rendered on the page but no solution was discussed:

So to give some more detail of the problem and what I have found, I have an app which uses two step login process which I have split across two public pages.

  • P9999 - Login Step 1 - Collect some credentials, verify against an external webservice and branch to Step 2
  • P9998 - Login Step 2 - Collect more credentials and then Calls apex_authentication.login like any other apex login page

The login page setting under App Builder > Application Properties is set to P9998 Login Step 1 as this is to be the initial landing page for new / expired / logged out sessions.

The actual login functionality is all working fine.

Just when we have cause to display the throttling message it is displayed with static values and does not count down. It appears that the javascript to do the throttle count down is missing from the page (see above URLS) but I don't know enough about JS to re add it to the page manually.

So I tried to dig more in to the underlying cause of the missing JS.

It seems like the reason for the missing JS in the page rendering is coming from the PAGE_FUNCTION on the view APEX_APPLICATION_PAGES:

PAGE_NO           PAGE_FUNCTION

9999         Login

9998         Dynamic HTML

That view is sourcing this data from PAGE_COMPONENT_MAP on WWV_FLOW_STEPS:

ID          FLOW_ID            COMPONENT_MAP

9999     200                      12

9998     200                      10

(10 = Dynamic HTML, 12 = LOGIN)

I think to be able to solve my problem and get the JS rendered on the login page to count down seconds as expected, I need to have both login pages (9999 and 9998) set to WWV_FLOW_STEPS.COMPONENT_MAP = 12 and by extension APEX_APPLICATION_PAGES.PAGE_FUNCTION = 'Login'.

Does that seem right?

I can’t get much further than this to see what is setting the Component Map and what criteria it is based on because the package bodies are wrapped and so do not show up in the source tables. Unwrapping them will be very time consuming and possibly a license violation too.

I think I can solve this problem in two ways:

  • Hopefully someone might know how to get the component map set to 12 for both of my login pages rather than just step 1?
  • Or does anyone know how to add the necessary JS to my Step 2 page manually to allow the throttle message to count down the remaining seconds?

Thanks for reading and I hope I've explained the problem clearly enough.

Oracle Apex Version 20.1.0.00.13

Oracle Database 18.0.0.0.0

Oracle REST Data Services 19.2.0.r1991647

Tomcat 9.0.37

Best Answers

  • Nazbit
    Nazbit Member Posts: 34 Bronze Badge
    edited Dec 13, 2021 8:15PM Answer ✓

    I don't have apex infront of me right now to give the exact wording so apologies if I'm mistaken, but from memory...

    App builder > Edit Application Properties > User Interface Tab

    One of the sections asks for:

    * URL of the app login page

    * URL of the app "home page" to be shown after login

    I left the homepage path as was but changed the login path to redirect new sessions to step 1 after they were automatically pointing at step 2.

    But doing this causes step 1 to become the main login page again.


    (Edited for clarity)

  • fac586
    fac586 Senior Technical Architect EdinburghMember Posts: 21,579 Red Diamond
    Answer ✓

    I left the homepage path as was but changed the login path to redirect new sessions to step 1 after they were automatically pointing at step 2.

    But doing this causes step 1 to become the main login page again.

    Leave this pointing at step 2.

    Replace this process on step 2:

    • Pre Load process - sanity check - if user did not complete step 1 redirect there now.

    with a branch to step 1 at the Before Header execution point using the "sanity check" logic as a Server-side Condition.

    This should result in step 2 being the official "login" page and any attempt to access it without completing step 1 redirecting to the first page.

    Nazbit

Answers

  • fac586
    fac586 Senior Technical Architect EdinburghMember Posts: 21,579 Red Diamond

    So to give some more detail of the problem and what I have found, I have an app which uses two step login process which I have split across two public pages.

    P9999 - Login Step 1 - Collect some credentials, verify against an external webservice and branch to Step 2

    P9998 - Login Step 2 - Collect more credentials and then Calls apex_authentication.login like any other apex login page

    Why use two pages here? Explain in detail what is happening.

  • Nazbit
    Nazbit Member Posts: 34 Bronze Badge

    OK Sure. So its to do with Multi Factor Authentication. I initially tried to use one page for the whole process with conditional processing and dynamic actions to hide and show renders but I found it all got a bit messy and found it neater to split in to two pages.

    P9999 - Login Step 1:

    • Default pre render process on username cookie retrieval
    • Contains the default login form region to accept username, password, checkbox for remember username cookie
    • Run validation on username, reject if format is incorrect or user not found in users table or user locked / disabled etc
    • Runs validation that password is not null
    • Call PL/SQL package to call third party rest api to validate username and password and get a json response collection of acceptable MFA factors for that user
    • If response ok branch to Step 2
    • Else response invalid stay here with suitable error message

    P9998 - Login Step 2:

    • Pre Load process - sanity check - if user did not complete step 1 redirect there now.
    • Page renders a list of the MFA factors enrolled for that user from the previous web service response on step 1
    • Radio group allows choice of factor (if more than one exist) and accepts value input from the user
    • Calls PL/SQL package which calls a third party rest api to validate the MFA value supplied
    • If response from web service is good then login to the apex session
      • apex_authentication.login (p_username is username, p_password is a one time password / security token from MFA web service response)
      • Set username cookie if checked on previous page
      • Clear cache for both pages
    • Else If response from web service is bad then show error

    The custom authentication function in the custom authentication scheme then does this:

    • Recheck that username exists in users table and is valid for logon
    • Check that relevant tokens have been placed in the database by step 1 for this username and oracle session id
    • Check that relevant tokens have been placed in the database by step 2 for this username and oracle session id
    • Check that one time password is valid and within valid time window


    Hope that helps.

    It might be possible in one page but seemed cleaner to do it across two pages.

    I found that even with conditions added to the page processing, dynamic actions and validations they were all starting to trip over each others. Plus submit on enter pressed had to be disabled because there were different types of submit request in use. It also became a bit difficult to tell the difference between a new oracle session and one that had previously failed the authentication process.


    All of this is working as I'd hoped. It's just that the having "two login pages" is meaning that apex only identifies step 1 as the true login and doesn't render the login java script on step 2 (even though this is the one performing the login) which is required to decrement the count down seconds timer on the throttle warning.


    Thanks

  • fac586
    fac586 Senior Technical Architect EdinburghMember Posts: 21,579 Red Diamond
    edited Dec 13, 2021 6:45PM

    Thanks for the detailed information.

    It might be possible in one page but seemed cleaner to do it across two pages.

    Indeed it does, but then you hit this problem where APEX thinks you only need one login page.

    I found that even with conditions added to the page processing, dynamic actions and validations they were all starting to trip over each others.

    It's definitely more complicated than having two pages, but it shouldn't get completely out of hand. What condition(s) were you using? My approach would be the simple one of setting a REQUEST value when branching back for the second phase and then making all conditional rendering decisions based on that REQUEST value.

    Plus submit on enter pressed had to be disabled because there were different types of submit request in use.

    Why is that a problem? Submit On Enter sets the REQUEST value to the name of the entered item, so it's only a matter of extending any REQUEST-based conditions to include multiple values.

    All of this is working as I'd hoped. It's just that the having "two login pages" is meaning that apex only identifies step 1 as the true login and doesn't render the login java script on step 2 (even though this is the one performing the login) which is required to decrement the count down seconds timer on the throttle warning.

    I don't know what that JavaScript is yet, but if it's not obvious/documented then I'd be looking for a supported solution in the first instance.

    However, if the throttle message is only required on the second of these pages, then make that the one that APEX thinks is the official "Login" page? Create a copy of the application, delete pages 9999 and 9998 from the original and copy them back in reverse order (not tested!).

    Nazbit
  • Nazbit
    Nazbit Member Posts: 34 Bronze Badge

    Thanks for replying again.

    I agree with you that conditional processing using the request value should work in theory but I was having numerous problems with it. Perhaps now that I have the end to end process working and all of the underlying packages etc built I may be able to go back to one page and bring any specific issues I encounter back here for discussion.

    Perhaps I gave up on the single page too easily but also while the design of the related components and the overall process flow was still evolving. It may be easier to consolidate on to one page now that the process is demonstrated and working across two pages.

    However, if the throttle message is only required on the second of these pages, then make that the one that APEX thinks is the official "Login" page? Create a copy of the application, delete pages 9999 and 9998 from the original and copy them back in reverse order (not tested!).

    I tried this and confirmed that the new Step 2 page was identified as the login in both the application builder and also the tables described above.

    But that then had the side effect that all new sessions are diverted immediately to step 2 as it changes the Default Login URL in the Application User Interface settings.

    Changing the path manually to point at Step 1 then resets the whole process and makes apex see the Step 1 as the main (and therefore only) login page instead of Step 2.

    So that doesn't appear to work.

    Submit On Enter sets the REQUEST value to the name of the entered item, so it's only a matter of extending any REQUEST-based conditions to include multiple values.

    Thankyou. This was new information to me. I understand the request value when working with buttons and dynamic actions but I was not aware of this. I think this will solve some of the problems that I was having in keeping this on a single page.

    There is an example of the javascript in one of the two links at the top of the page although it dates back to someone who identified it in apex 4.

  • fac586
    fac586 Senior Technical Architect EdinburghMember Posts: 21,579 Red Diamond

    Changing the path manually to point at Step 1

    How was that done?

  • Nazbit
    Nazbit Member Posts: 34 Bronze Badge
    edited Dec 13, 2021 8:15PM Answer ✓

    I don't have apex infront of me right now to give the exact wording so apologies if I'm mistaken, but from memory...

    App builder > Edit Application Properties > User Interface Tab

    One of the sections asks for:

    * URL of the app login page

    * URL of the app "home page" to be shown after login

    I left the homepage path as was but changed the login path to redirect new sessions to step 1 after they were automatically pointing at step 2.

    But doing this causes step 1 to become the main login page again.


    (Edited for clarity)

  • fac586
    fac586 Senior Technical Architect EdinburghMember Posts: 21,579 Red Diamond
    Answer ✓

    I left the homepage path as was but changed the login path to redirect new sessions to step 1 after they were automatically pointing at step 2.

    But doing this causes step 1 to become the main login page again.

    Leave this pointing at step 2.

    Replace this process on step 2:

    • Pre Load process - sanity check - if user did not complete step 1 redirect there now.

    with a branch to step 1 at the Before Header execution point using the "sanity check" logic as a Server-side Condition.

    This should result in step 2 being the official "login" page and any attempt to access it without completing step 1 redirecting to the first page.

    Nazbit
  • Nazbit
    Nazbit Member Posts: 34 Bronze Badge


    Replace this process on step 2:

    Pre Load process - sanity check - if user did not complete step 1 redirect there now.

    with a branch to step 1 at the Before Header execution point using the "sanity check" logic as a Server-side Condition.

    Yes you are right.

    I had it in a dynamic action fired on page load which works for my original purpose but not for the redirect we are attempting now.

    But moving that logic as per your suggestion to a pre rendering branch does indeed work nicely.

    So step 2 is now recognised by apex as my main login page (which it is because its the one that calls the apex login procedure) but users are redirected to complete step 1 first.

    Thanks