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

Detect cancellation of login #26

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

erkenberg
Copy link

@erkenberg erkenberg commented May 9, 2022

We had an issue similar to #20, where we needed to detect when the oAuth progress was cancelled by the user (thus the login overlay closes without getting a redirect from the identity providers endpoint, as the user never interacted with it).
Currently the plugins sends no message at all if this happens, therefore we couldn't detect this case.

We solved it by adding a special message that the plugin sends when this happens: oauth:{"error":"cancelled"}.

The only edge case that came up while testing is, that while closing the overlay via the close buttons included in the overlay itself returns the new message (instead of nothing), canceling via the actual dialog will still return the regular response from the identity provider (as before).

While this makes sense implementation wise, it might be a bit confusing when using it.

What do you think?

Tested without issues on Android 12 and iOS 15. Note that while I'm sufficiently familiar with Android, I don't know much about Swift, and the implementation for iOS was more based on testing and following the documentation for ASWebAuthenticationSession than actually understanding what exactly I'm doing (but seems to run just fine).

@erkenberg erkenberg changed the title Feature/detect o auth login cancellation Detect cancellation of login May 9, 2022
@dpogue
Copy link
Member

dpogue commented May 10, 2022

Thanks for the pull request! 🙇🏼‍♂️

At a glance, the code looks good. I'd like to do a more thorough review and run it to see some of the edge cases you mentioned, but I probably won't have a chance to do that until the weekend.

@erkenberg
Copy link
Author

Thanks for the quick feedback, let me know when you need any more information, looking forward to your review.

Have a nice week!

Copy link
Member

@dpogue dpogue left a comment

Choose a reason for hiding this comment

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

👍 I like this approach

I still need to test it on actual devices to see the dialog closing issue you mentioned, and see if there's anything we can do for older iOS versions (although I also realize those aren't supported by Cordova iOS anymore).

@@ -37,6 +37,8 @@ class ASWebAuthenticationSessionOAuthSessionProvider : OAuthSessionProvider {
self.aswas = ASWebAuthenticationSession(url: endpoint, callbackURLScheme: callbackURLScheme, completionHandler: { (callBack:URL?, error:Error?) in
if let incomingUrl = callBack {
NotificationCenter.default.post(name: NSNotification.Name.CDVPluginHandleOpenURL, object: incomingUrl)
} else if let incomingUrl = error {
Copy link
Member

Choose a reason for hiding this comment

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

Reusing the incomingUrl variable name here doesn't make the most sense, something like else if let err = error would be better (and then use err as the object passed to NotificationCenter.

For background, error is a Error? which means it might be nil.
if let err = error is a Swift construct that evaluates truthy if error is non-nil, and assigns the non-nil value to err (essentially changing from Error? to Error).

Copy link
Author

Choose a reason for hiding this comment

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

Ah, thanks for the explanation!
I adapted (and retestet) the commit accordingly.

@@ -64,6 +66,8 @@ class SFAuthenticationSessionOAuthSessionProvider : OAuthSessionProvider {
self.sfas = SFAuthenticationSession(url: endpoint, callbackURLScheme: callbackScheme, completionHandler: { (callBack:URL?, error:Error?) in
if let incomingUrl = callBack {
NotificationCenter.default.post(name: NSNotification.Name.CDVPluginHandleOpenURL, object: incomingUrl)
} else if let incomingUrl = error {
Copy link
Member

Choose a reason for hiding this comment

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

Same here with reusing incomingUrl

Copy link
Author

Choose a reason for hiding this comment

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

Fixed :)

@@ -210,6 +219,10 @@ class OAuthPlugin : CDVPlugin, SFSafariViewControllerDelegate, ASWebAuthenticati
}


@objc internal func _handleError_(_ notification : NSNotification) {
Copy link
Member

Choose a reason for hiding this comment

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

This method doesn't need to end in an underscore, just _handleError(_ notification : NSNotification) is fine.

Yes, Swift has a lot of underscores in weird places 😛

Comment on lines 139 to 143
if(!loginSuccessful) {
this.webView.getEngine().evaluateJavascript("window.dispatchEvent(new MessageEvent('message', { data: 'oauth::{\"error\":\"cancelled\"}' }));", null);
} else {
// reset loginSuccessful to make sure it is correctly initialized on the next login attempt
loginSuccessful=false;
Copy link
Member

Choose a reason for hiding this comment

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

Super minor nit, but formatting-wise, I prefer if (statement) with spaces, and spaces around the equals sign in assignments.

Copy link
Author

Choose a reason for hiding this comment

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

Definitely on your side, fixed it to be consistent with the rest of the code :)

@erkenberg erkenberg force-pushed the feature/detect-oAuth-login-cancellation branch from 28922fa to 06c1d57 Compare May 15, 2022 12:11
@erkenberg erkenberg force-pushed the feature/detect-oAuth-login-cancellation branch from 06c1d57 to 22ce32b Compare May 15, 2022 12:22
@erkenberg
Copy link
Author

As said, the dialog closing issue ist not really an issue, more a question of what is expected.

For Visualization:

If I click cancel in the top left, my code would trigger (as the login overlay is cancelled/closed) and I would send the cancelled error.

However, if I click the cancel next to continue (so in the actual login website), the identity provider would handle that and send a redirect URL with an error.
In my test cases it was an access_denied error, but I'm not sure if this is
a) the same for all providers and
b) if there are other cases than the cancel that could trigger this specific error.

Therefore I didn't want to mix those in the plugin and just regularly parse/send this url/message to the actual application.

@zalaris
Copy link

zalaris commented Jul 25, 2022

Hi @dpogue,

Are you going to merge this PR? We need that cancelation event as well.
Thank you!

@dpogue dpogue added this to the v4.1.0 milestone Sep 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants