Reputation: 188
I have followed the instructions on https://firebase.google.com/docs/auth/ios/twitter-login to a T for Swift and I get the web popup to authorise the App I created on Twitter Dev, the callback is called and then the webview sits on an empty page of about:blank. Nothing can be done but click the Done button which then results in a Error Domain=FIRAuthErrorDomain Code=17058 "The interaction was cancelled by the user." Callback address is correct. I've used the Twitter Consumer API Keys as the keys to enter in the Firebase console.
What am I missing?
Upvotes: 4
Views: 2044
Reputation: 116
Invalid declaration of the OAuthProvider can be issue but, for me problem was that FirebaseAppDelegateProxyEnabled
was set to false
. You can simply solve that by setting FirebaseAppDelegateProxyEnabled
to true
, but if you want to have that proxy disabled you can do that but you need to add Auth.auth().canHandle(url)
to the func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
method in SceneDelegate
(for iOS 13+) and everything will work without problem.
Upvotes: 1
Reputation: 41
Got stucked in about:blank page for days, tried all the above but not working, solved by add following code in AppDelegate
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let twitterhandeled = Auth.auth().canHandle(url)
return twitterhandeled
}
Upvotes: 2
Reputation: 683
I found my solution looking at @tommy's answer.
If you're developing a SwiftUI app just add to your top level view:
.onOpenURL { url in
Auth.auth().canHandle(url) // Required for twitter login callback
}
Probably if your app is not using SwiftUI then @tommy code should work:
// Inside your AppDelegate
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let twitterhandeled = Auth.auth().canHandle(url)
return twitterhandeled
}
Upvotes: 2
Reputation: 307
For me there was no need in framework modifications.
As stated in a issue on GitHub: provider property should be
declared at a class or global level
So I just moved its initialisation out of a function.
Before:
class AuthViewController: UIViewController {
private func signIn() {
let provider = OAuthProvider(providerID: "twitter.com")
provider.getCredentialWith(nil) {
...
}
}
}
After:
class AuthViewController: UIViewController {
private let provider = OAuthProvider(providerID: "twitter.com")
private func signIn() {
provider.getCredentialWith(nil) {
...
}
}
}
Upvotes: 3
Reputation: 61
For everyone who still has an issue with getting callback working, I managed to fix it. Sadly, you have to edit the method in the library (not the best way, but still. Bug was reported to firebase team). The method should look like the one below (you can find it in the file named FIROAuthProvider.m, line 125. I intentionally left commented lines, so you see the problem there... Hope it helps somebody :)
- (void)getCredentialWithUIDelegate:(nullable id<FIRAuthUIDelegate>)UIDelegate
completion:(nullable FIRAuthCredentialCallback)completion {
if (![FIRAuthWebUtils isCallbackSchemeRegisteredForCustomURLScheme:self->_callbackScheme]) {
[NSException raise:NSInternalInconsistencyException
format:@"Please register custom URL scheme '%@' in the app's Info.plist file.",
self->_callbackScheme];
}
// __weak __typeof__(self) weakSelf = self;
// __weak FIRAuth *weakAuth = _auth;
// __weak NSString *weakProviderID = _providerID;
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
FIRAuthCredentialCallback callbackOnMainThread =
^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(credential, error);
});
}
};
NSString *eventID = [FIRAuthWebUtils randomStringWithLength:10];
NSString *sessionID = [FIRAuthWebUtils randomStringWithLength:10];
// __strong __typeof__(self) strongSelf = weakSelf;
[self
getHeadFulLiteURLWithEventID:eventID
sessionID:sessionID
completion:^(NSURL *_Nullable headfulLiteURL, NSError *_Nullable error) {
if (error) {
callbackOnMainThread(nil, error);
return;
}
FIRAuthURLCallbackMatcher callbackMatcher =
^BOOL(NSURL *_Nullable callbackURL) {
return [FIRAuthWebUtils
isExpectedCallbackURL:callbackURL
eventID:eventID
authType:kAuthTypeSignInWithRedirect
callbackScheme:self->_callbackScheme];
};
// __strong FIRAuth *strongAuth = weakAuth;
[_auth.authURLPresenter
presentURL:headfulLiteURL
UIDelegate:UIDelegate
callbackMatcher:callbackMatcher
completion:^(NSURL *_Nullable callbackURL,
NSError *_Nullable error) {
if (error) {
callbackOnMainThread(nil, error);
return;
}
NSString *OAuthResponseURLString =
[self OAuthResponseForURL:callbackURL
error:&error];
if (error) {
callbackOnMainThread(nil, error);
return;
}
__strong NSString *strongProviderID = _providerID;
FIROAuthCredential *credential = [[FIROAuthCredential alloc]
initWithProviderID:strongProviderID
sessionID:sessionID
OAuthResponseURLString:OAuthResponseURLString];
callbackOnMainThread(credential, nil);
}];
}];
});
}
Upvotes: 6
Reputation: 188
Ok so I resolved this question but not entirely sure how now. I believe it was because the callback wasn't being issued and thus not picked up by the app. The callback wasn't issue due to the authentication and I believe because I hadn't created the terms of service and privacy policy. So make sure you have done that in the Twitter dev page.
In the twitter dev page, the callback link is: https://yourApp.firebaseapp.com/__/auth/handler You'll find this in your firebase authentication settings when you enable twitter.
Ensure you have in info.plist LSApplicationQueriesSchemes an array of: twitter twitterauth
In your swift file:
var provider = OAuthProvider(providerID: "twitter.com")
Your button action:
@IBAction func onCustonTwitterButtonPressed(_ sender: Any) {
MyAppsCoreServicesScripts.logoutSocial() // My logout routine.
provider.getCredentialWith(nil) { credential, error in
if let error = error {
MyAppsCoreServicesScripts.showError(prefix: "Twitter Login",error: error, showMsg: true)
} else if credential != nil {
self.firebaseLogin(credential!)
}
}
}
Good luck! Hope this helps someone.
Upvotes: 0