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

Added ASWebAuthenticationSession Support iOS12 #245

Merged
merged 4 commits into from
Nov 22, 2018

Conversation

cocojoe
Copy link
Member

@cocojoe cocojoe commented Nov 15, 2018

Changes

Follow up to #239

Internal changes to enable ASWebAuthenticationSession in iOS 12 and maintain support for Xcode 9.

References

#238

Testing

  • This change adds unit test coverage
  • This change has been tested on the latest version of the platform/language or why not

Checklist

@cocojoe cocojoe changed the title Added ASWebAuthenticationSession Support Added ASWebAuthenticationSession Support iOS12 Nov 15, 2018
@cocojoe
Copy link
Member Author

cocojoe commented Nov 15, 2018

@martinoconnor Was a little tricker to add backwards compatibility for Xcode 9. However, all good and passing all platform tests.

super.init(redirectURL: redirectURL, state: state, handler: handler, finish: finish, logger: logger)
self.authSession = SFAuthenticationSession(url: self.authorizeURL, callbackURLScheme: self.redirectURL.absoluteString) { [unowned self] in
#if canImport(AuthenticationServices)
Copy link
Member Author

Choose a reason for hiding this comment

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

So turns out there was this handy pre-processor added into Swift 4.1 that let's us check for a Framework.

self.authSession = authSession
authSession.start()
}
#else
Copy link
Member Author

Choose a reason for hiding this comment

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

This will be fallback in Xcode 9

init(url: URL, schemeURL: String, callback: @escaping (Bool) -> Void) {
self.callback = callback
self.authSession = SFAuthenticationSession(url: url, callbackURLScheme: schemeURL) { [unowned self] url, _ in
#if canImport(AuthenticationServices)
Copy link
Member Author

@cocojoe cocojoe Nov 20, 2018

Choose a reason for hiding this comment

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

As this Framework does not exist in Xcode 9, it can not compile without this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd swap the conditions to return earlier in the code:

#if NOT canImport(AuthenticationServices){
  ...
  authSession.start()
  return.
}

// No need for "else" here
if #available(iOS 12.0, *) {
 ...
} else {
 ...
}
self.authSession.start()

Also, consider adding this same comment on a line above the if check, whenever applicable, as would help whoever maintains this in the future to understand it.

Copy link
Member Author

Choose a reason for hiding this comment

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

These are two different kinds of checks, the #if is a pre-processor so if it's on Xcode 10+ include this code. If it was Xcode 9 only the code in the #else would actually be visible to the compiler. The if #available(iOS12) is a runtime check, no escaping it.

@@ -22,22 +22,45 @@

import UIKit
import SafariServices
#if canImport(AuthenticationServices)
Copy link
Member Author

Choose a reason for hiding this comment

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

As this Framework does not exist in Xcode 9, it can not compile without this.

self.authSession = authSession
authSession.start()
}
#else
Copy link
Member Author

Choose a reason for hiding this comment

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

Fallback Xcode 9

@@ -22,20 +22,50 @@

import UIKit
import SafariServices
#if canImport(AuthenticationServices)
Copy link
Member Author

Choose a reason for hiding this comment

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

As this Framework does not exist in Xcode 9, it can not compile without this.

}
self.authSession = authSession
authSession.start()
} else {
Copy link
Member Author

@cocojoe cocojoe Nov 20, 2018

Choose a reason for hiding this comment

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

Fallback iOS 11.0 (This whole class is only available in iOS 11.0+)

}
self.authSession = authSession
authSession.start()
} else {
Copy link
Member Author

@cocojoe cocojoe Nov 20, 2018

Choose a reason for hiding this comment

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

Fallback iOS 11.0 (This whole class is only available in iOS 11.0+)

init(url: URL, schemeURL: String, callback: @escaping (Bool) -> Void) {
self.callback = callback
self.authSession = SFAuthenticationSession(url: url, callbackURLScheme: schemeURL) { [unowned self] url, _ in
#if canImport(AuthenticationServices)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd swap the conditions to return earlier in the code:

#if NOT canImport(AuthenticationServices){
  ...
  authSession.start()
  return.
}

// No need for "else" here
if #available(iOS 12.0, *) {
 ...
} else {
 ...
}
self.authSession.start()

Also, consider adding this same comment on a line above the if check, whenever applicable, as would help whoever maintains this in the future to understand it.

self.callback(url != nil)
TransactionStore.shared.clear()
}
self.authSession?.start()
self.authSession = authSession
Copy link
Contributor

Choose a reason for hiding this comment

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

why are you doing the assignment here and not above? e.g.

self.authSession = SFAuthenticationSession(url: url, callbackURLScheme: schemeURL) .....

I see this in many files of this PR

Copy link
Contributor

Choose a reason for hiding this comment

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

After re-reading this.. Note that "fallback for 11" and "fallback for 9" have the exact same code. The only thing changing is SFAuthenticationSession and ASWebAuthenticationSession on 1 of the 3 cases. Please consider re-writing the code so that only that first line is wrapped around the OS check and the remaining is shared.

I imagine something like this is possible:

self.callback = callback
 #if canImport(AuthenticationServices) && #available(iOS 12.0, *)
      self.authSession = ASWebAuthenticationSession(url: url, callbackURLScheme: schemeURL) { 
      [unowned self] url, _ in
                self.callback(url != nil)
                TransactionStore.shared.clear()
            }
#else  
        self.authSession = SFAuthenticationSession(url: url, callbackURLScheme: schemeURL) { 
       [unowned self] url, _ in
                self.callback(url != nil)
                TransactionStore.shared.clear()
            }
#endif 

self.authSession.start()

Copy link
Member Author

Choose a reason for hiding this comment

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

The behaviour is slightly more complex than this, I could assign self.authSession = ASWeb/SFAuth However at that point it is now a common foundation type of NSObject. This is done so we can reuse one property, it's only real purpose here is to retain the object so the AuthenticationSession doesn't vanish until it's completed.

Problem now is you can't call self.authSession.start() as start() is not available in NSObject.

Copy link
Contributor

Choose a reason for hiding this comment

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

what about then,

self.callback = callback
let authSession;
 #if canImport(AuthenticationServices) && #available(iOS 12.0, *)
      authSession = ASWebAuthenticationSession(url: url, callbackURLScheme: schemeURL) { 
      [unowned self] url, _ in
                self.callback(url != nil)
                TransactionStore.shared.clear()
            }
#else  
        authSession = SFAuthenticationSession(url: url, callbackURLScheme: schemeURL) { 
       [unowned self] url, _ in
                self.callback(url != nil)
                TransactionStore.shared.clear()
            }
#endif 
self.authSession = authSession;
authSession.start()

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a good idea in theory. However, you're left with the same problem, Swift is strongly type, you must specify the type for your let authSession So you are back to the same problem as your previous suggestion.

Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

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

Left some suggestions but can't be applied because swift is a strongly typed language. The changes look OK anyway, so ⚡️

@cocojoe cocojoe added this to the vNext milestone Nov 22, 2018
@cocojoe cocojoe merged commit 294c63a into master Nov 22, 2018
@cocojoe cocojoe mentioned this pull request Dec 6, 2018
@cocojoe cocojoe deleted the added-aswebauthentication branch July 18, 2019 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants