mirror of
https://github.com/OAuthSwift/OAuthSwift.git
synced 2026-04-26 12:45:52 +03:00
[GH-ISSUE #223] Both success and failure called after canceling OAuth flow and retrying it #126
Labels
No labels
bug
cocoapod
duplicate
enhancement
feature-request
help wanted
help wanted
invalid
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/OAuthSwift#126
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @vronin on GitHub (Apr 14, 2016).
Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/223
There is a bug in OAuth flow for a following case.
iOS +
SFSafariViewController+ code grant (however, I think something like that will happen in wide range of scenarios which I haven’t thought through)The best way to reproduce is to start from empty Simulator (to make sure that no cookies are cached in
SFSafariViewController)SFSafariViewControllerSFSafariViewControlleragainauthorizeWithCallbackURLsuccess and failure callbacks will be called.Summary
The root cause is that we register multiple observers (one at step #1 and one at step #4). The observer from step #1 was never removed, because there is no code which handles canceling OAuth flow at step #3.
Details
Taking into account that old observer isn’t removed then on OAuth this function will be called.
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool. This function will post notification which will be handled by two observers. One of them will go and get a token and will get 401 (because code is used already).There are many underlying problems which produce this result
A) The demo application and example show in README instantiate new OAuth2Swift instance for each OAuth flow.
B)
OAuthSwift.removeCallbackNotificationObservercalled internally only for some results (successful or failed OAuth attempt). However, it won't be called, if a SFSafariViewController is just dismissed and no URL was opened.I tried to resolved #B (remove old observer) by explicitly calling
oauthswift.removeCallbackNotificationObserver(). However, because of #A, the new oauthswift instance doesn't hold a reference to old observer (self.observerwill be empty).Pretty much the only way is to solve this (without modifying OAuthSwift pod code) is to make oauthswift a singleton and call
OAuthSwift.removeCallbackNotificationObserverexplicitly . However, this opens next problem (also related to observers)C) If you make OAuthSwift a singleton then it will start crashing at
SafariURLHandler.handleat lineif let observer = self.observers[key]. The issue is that old instance of SafariURLHandler is not references by anything (because we have to create new authorize_url_handle for each new OAuth flow:oauthswift.authorize_url_handler = SafariURLHandler(viewController: viewController)). As result,selfis unowned and not references and a closure is still called ( because observer was never removed ).I found a temporary workaround/hack for this. The full solution (with several workarounds) are below.
Long term fix
However, I think the logic around registering and removing observers should be rethought to eliminate these workarounds.
Workaround
@phimage commented on GitHub (May 11, 2016):
maybe into 'safariViewControllerDidFinish' we must clear all the observers
observers into dictionary are easy to remove
but the global one, we must put a reference on OAuthSwift object into the SafariURLHandler (or a block to call removeCallbackNotificationObserver)
maybe into the didSet of url handler, by casting on SafariURLHandler or specific protocol
@martinpilch commented on GitHub (Jun 30, 2016):
Hi, any progress on this issue? I'm facing same problem
@phimage commented on GitHub (Jul 25, 2016):
cancelwill be added to OAuthSwift (this function callremoveCallbackNotificationObserver), function to call when a web view is dismissed without authentificationOAuthSwiftobject to SafariURLHandler`, this allow when pressing "Done" to remove all observers -> library update will make compile issue, but I will document in release...a current workaround is to let user do the
oauthSwift.removeCallbackNotificationObserver()inSFSafariViewControllerDelegate.safariViewControllerDidFinishfunctionand do also the workaround code from previous comment