-
Notifications
You must be signed in to change notification settings - Fork 114
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
[Login] Improve error messaging displaying a new error screen when application password is disabled #15031
base: trunk
Are you sure you want to change the base?
[Login] Improve error messaging displaying a new error screen when application password is disabled #15031
Conversation
…ed application password.
…ledViewModel.swift - Modify navigation logic to pop to the third last view controller or root if fewer than three - Update primary button title to "Retry" for retrying application password authorization - Remove outdated primary button title "Log in with WordPress.com"
…ordDisabledViewModel` using Woo mobile guidelines
…swordViewModelTests`
📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While testing navigation back and forth, I encountered a case where the application password fetch failed with the following log:
Tracked application_password_authorization_url_fetch_failed, properties: [error_domain: Networking.RequestAuthenticatorError, error_description: Alamofire.AFError.requestAdaptationFailed(error: Networking.RequestAuthenticatorError.applicationPasswordNotAvailable), error_code: 1]
In this case, the fetchAuthURL
method failed with error and the logic went through to the catch
block, which showed an alert instead of the application password not available screen:
Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-02-03.at.11.50.29.mp4
We should also check the logic in this catch block to show the new screen if we get the applicationPasswordNotAvailable
error.
// Pop back two view controllers to remove both error and web view | ||
navigationController?.popViewController(animated: false) | ||
navigationController?.popViewController(animated: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is hacky and prone to error. How about looking for the index of ApplicationPasswordTutorialViewController
in the navigation stack, and pop to the index before that?
A better option would be to send the view controller before the application password flow to this view controller via presentApplicationPasswordWebView
in AuthenticationManager
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you and with your second suggestion, so I applied the new changes in this commit: 9b480ba
.../Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift
Outdated
Show resolved
Hide resolved
if viewControllers.count >= 3 { | ||
navigationController.popToViewController(viewControllers[viewControllers.count - 3], animated: true) | ||
} else { | ||
navigationController.popToRootViewController(animated: true) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number 3 seems to be a magic number, it's not clear why we have to do this. Please consider my suggestion above about looking for the index of a specific view controller to pop to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I'm using the previousVC
like in the comment above, please feel free to check changes here: 9b480ba 🙏
…abled-note-take-2
- Modify `ApplicationPasswordAuthorizationWebViewController.swift` to include a reference to the previous view controller for navigation purposes. - Update `AuthenticationManager.swift` to pass the previous view controller to the web view used for application password authorization. - Enhance `ApplicationPasswordDisabledViewModel.swift` to store the previous view controller and use it for navigation. - Adjust `PostSiteCredentialLoginChecker.swift` to capture and utilize the last view controller before the application password flow. - Update tests in `ApplicationPasswordDisabledViewModelTests.swift` to include the previous view controller in the view model initialization.
…abled-note-take-2
@itsmeichigo this is ready for another check 🙌 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, Paolo. I found a few issues with the new changes in the comments below.
Also, it seems that you missed the comment in my previous round about missing the case when fetching the authentication URL fails with Alamofire.AFError.requestAdaptationFailed(error: Networking.RequestAuthenticatorError.applicationPasswordNotAvailable)
.
.../Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift
Outdated
Show resolved
Hide resolved
.../Authentication/Application Password/ApplicationPasswordAuthorizationWebViewController.swift
Outdated
Show resolved
Hide resolved
...erce/Classes/Authentication/Navigation Exceptions/ApplicationPasswordDisabledViewModel.swift
Show resolved
Hide resolved
...erce/Classes/Authentication/Navigation Exceptions/ApplicationPasswordDisabledViewModel.swift
Outdated
Show resolved
Hide resolved
// show application password disabled error, and catch the last view controller that was showing before the Application Password flow. | ||
let previousViewController = navigationController.viewControllers.dropLast().last |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the exact controller that you are navigating to here? Please note that the PostSiteCredentialLoginChecker
can be triggered from two places: (1) after site credential login (if application password is not required), and (2) after application password login.
For (1), I'd suggest sending nil
as the previous view controller to the PostSiteCredentialLoginChecker
, so that the error page would simply pop itself upon navigating back.
For (2), I'd suggest sending the previous view controller from the application password entry point in AuthenticationManager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your suggestions @itsmeichigo, they are gold and I wasn't 100% aware of the flow. Can you check if the changes make sense now, please? 6bdb62d
if let previousViewController = previousViewController { | ||
navigationController.popToViewController(previousViewController, animated: true) | ||
} else { | ||
navigationController.popToRootViewController(animated: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you want to pop to the previous view controller, popToRoot
seems incorrect. Should it be popViewController
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I implemented it, during my testing process (at least in every test I did), the previous view controller immediately before the error screen was the loading screen—the one with just a loader in the middle of the view. If we pop back to it (by calling popViewController
), the user would remain stuck there, so we need to go back further to ensure a better user experience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. From my understanding, you already sent the previousViewController
for the application password flow, so this should not happen. Also, you are sending nil
for the site credential login flow, so tapping "Try Again" should navigate back to the login screen instead of the prologue screen IMO. Is there any other edge case we should be aware of?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, in theory, there are no other edge cases and I didn't find any other specific edge cases so I'm putting popViewController
. 👍
…ationPasswordAuthorizationWebViewController.swift Co-authored-by: Huong Do <[email protected]>
…cationPasswordDisabledViewModel.swift Co-authored-by: Huong Do <[email protected]>
- Update `AuthenticationManager.swift` to include `previousViewController` parameter in `checkSiteCredentialLogin` function - Modify `PostSiteCredentialLoginChecker.swift` to accept `previousViewController` in the initializer and utilize it in error handling
…rTests: update `PostSiteCredentialLoginChecker` instantiation in `PostSiteCredentialLoginCheckerTests.swift` to include `previousViewController: nil` across multiple test cases.
I'm sorry for missing that. How is it possible to generate that specific error? Is this something you simulate by editing the code, or is there a specific case that you can consistently replicate on JN sites? Note that simply disabling application passwords doesn't generate that error for me on my side. |
As stated above, I encountered this by navigating back and forth from the application password disabled error screen. Specifically:
Though this sounds like an edge case, I believe it should be handled given 2 reasons:
|
…abled-note-take-2
…hange navigationController method from `popToRootViewController` to `popViewController`
@itsmeichigo I was able to replicate the issue you mentioned when going back and forth. Do you think the error should be handled with the same error screen, or should we show a different error? I'm not sure if the error is always due to the application password being disabled or something else, because if I enable the application password, replicating that specific error becomes impossible, at least in my tests. If we display an error regarding fetching the URL, it will be generic and not helpful for the user, so I think I can move forward by displaying the same error screen about the application password being disabled. What do you think? |
…abled-note-take-2
@pmusolino I debugged the app and found that the flow now doesn't go through web application password, so we've been testing the wrong thing. Please note: you can only reach the web application password flow if you see the tutorial page before opening the web view. I used Proxyman to check the requests and here are what I'm seeing with a JN site that has https://wordpress.org/plugins/disable-application-passwords/ installed, and this is the flow I see up until the error reported above: So the flow first went through the application password retrieval with nonce (handled by When I navigated back and forth many times to retry, I finally got the 429 error (too many requests) for the nonce-retrieval request ( Now, to actually reach the application password web view screen, we need to block the programmatic site credential login through As can be seen in the screencast below, after entering site credentials, I was redirected to the web application password tutorial page with the error at the top. Then when I proceeded, I immediately got the error alert for disabled application password. This means it's a must to display the disabled error screen upon catching error when fetching application password URL. Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-02-06.at.10.41.07.mp4Regarding your question:
A few suggestions in case it's helpful:
|
…ntroller` and display errorUI instead of error alert
Thank you so much Huong for the explanation. Extra: I believe this happens because the |
…abled-note-take-2
Regarding this, I believe So, this is not an issue with the customization of the login page, but a custom rule of redirect to 404. In this case, I don't think we can do anything, users will need to contact support for help. cc @hichamboushaba in case he has some other suggestions. |
…abled-note-take-2
Yes, I think that it's a very common behavior for this type of plugin. |
Version |
Closes: #14004 (and peaMlT-U4)
Description
This pull request introduces improvements to handling the scenario when application passwords are disabled in user's website. The changes involve updating the error handling UI and navigation logic to provide a better user experience. This is a continuation of the job started by @hafizrahman here.
Testing information
Screenshots
RELEASE-NOTES.txt
if necessary.Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement: