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?
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);
}];
}];
});
}
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) {
...
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With