aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase
diff options
context:
space:
mode:
authorGravatar Ryan Wilson <wilsonryan@google.com>2018-07-11 17:40:25 -0400
committerGravatar GitHub <noreply@github.com>2018-07-11 17:40:25 -0400
commit79f663d5eaaa4b7f9fe46d176c82660d38e4be8a (patch)
tree47b27cb93aa0372eb141668526552b3559ac1dbb /Firebase
parentc6b4b03fffc3cea7c9525e5c79dce28f52900521 (diff)
Add Auth interoperability library. (#1501)
* Add Auth interoperability library. This allows other SDKs to retrieve the user ID and fetch a new Auth token in a type-safe way through the Core container. * Remove unnecessary import. * Add missing copyright. * Resolve comments. - Remove unnecessary umbrella header. - Move to version 1.0. - Add tvOS support for app lifecycle changes. * Move public interop headers to private. * Add public_header_files too. * Moved headers back into public. * Shorten Interoperability and Interoperable to Interop. * Add AuthInterop to travis linting. * Fixed tag format in AuthInterop.podspec. * Add AuthInterop path to Firestore Podfile.
Diffstat (limited to 'Firebase')
-rw-r--r--Firebase/Auth/Source/FIRAuth.m222
-rw-r--r--Firebase/Auth/Source/FIRAuth_Internal.h4
-rw-r--r--Firebase/Auth/Source/FIRUser.m2
-rw-r--r--Firebase/Core/FIRApp.m1
4 files changed, 131 insertions, 98 deletions
diff --git a/Firebase/Auth/Source/FIRAuth.m b/Firebase/Auth/Source/FIRAuth.m
index 691c6ce..b353ebb 100644
--- a/Firebase/Auth/Source/FIRAuth.m
+++ b/Firebase/Auth/Source/FIRAuth.m
@@ -18,8 +18,17 @@
#import "FIRAuth_Internal.h"
+#if __has_include(<UIKit/UIKit.h>)
+#import <UIKit/UIKit.h>
+#endif
+
+#import <FirebaseAuthInterop/FIRAuthInterop.h>
#import <FirebaseCore/FIRAppAssociationRegistration.h>
#import <FirebaseCore/FIRAppInternal.h>
+#import <FirebaseCore/FIRComponent.h>
+#import <FirebaseCore/FIRComponentContainer.h>
+#import <FirebaseCore/FIRComponentRegistrant.h>
+#import <FirebaseCore/FIRCoreConfigurable.h>
#import <FirebaseCore/FIRLogger.h>
#import <FirebaseCore/FIROptions.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
@@ -63,7 +72,6 @@
#import "FIRVerifyPhoneNumberResponse.h"
#if TARGET_OS_IOS
-#import <UIKit/UIKit.h>
#import "FIRAuthAPNSToken.h"
#import "FIRAuthAPNSTokenManager.h"
#import "FIRAuthAppCredentialManager.h"
@@ -218,9 +226,9 @@ static NSMutableDictionary *gKeychainServiceNameForAppName;
#pragma mark - FIRAuth
#if TARGET_OS_IOS
-@interface FIRAuth () <FIRAuthAppDelegateHandler>
+@interface FIRAuth () <FIRAuthAppDelegateHandler, FIRAuthInterop, FIRComponentRegistrant, FIRCoreConfigurable, FIRComponentLifecycleMaintainer>
#else
-@interface FIRAuth ()
+@interface FIRAuth () <FIRAuthInterop, FIRComponentRegistrant, FIRCoreConfigurable, FIRComponentLifecycleMaintainer>
#endif
/** @property firebaseAppId
@@ -300,42 +308,12 @@ static NSMutableDictionary *gKeychainServiceNameForAppName;
}
+ (void)load {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- gKeychainServiceNameForAppName = [[NSMutableDictionary alloc] init];
-
- NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
+ [FIRComponentContainer registerAsComponentRegistrant:self];
+ [FIRApp registerAsConfigurable:self];
+}
- // Ensures the @c FIRAuth instance for a given app gets loaded as soon as the app is ready.
- [defaultCenter addObserverForName:kFIRAppReadyToConfigureSDKNotification
- object:[FIRApp class]
- queue:nil
- usingBlock:^(NSNotification *notification) {
- [FIRAuth authWithApp:[FIRApp appNamed:notification.userInfo[kFIRAppNameKey]]];
- }];
- // Ensures the saved user is cleared when the app is deleted.
- [defaultCenter addObserverForName:kFIRAppDeleteNotification
- object:[FIRApp class]
- queue:nil
- usingBlock:^(NSNotification *notification) {
- dispatch_async(FIRAuthGlobalWorkQueue(), ^{
- // This doesn't stop any request already issued, see b/27704535 .
- NSString *appName = notification.userInfo[kFIRAppNameKey];
- NSString *keychainServiceName = [FIRAuth keychainServiceNameForAppName:appName];
- if (keychainServiceName) {
- [self deleteKeychainServiceNameForAppName:appName];
- FIRAuthKeychain *keychain = [[FIRAuthKeychain alloc] initWithService:keychainServiceName];
- NSString *userKey = [NSString stringWithFormat:kUserKey, appName];
- [keychain removeDataForKey:userKey error:NULL];
- }
- dispatch_async(dispatch_get_main_queue(), ^{
- [[NSNotificationCenter defaultCenter]
- postNotificationName:FIRAuthStateDidChangeNotification
- object:nil];
- });
- });
- }];
- });
++ (void)initialize {
+ gKeychainServiceNameForAppName = [[NSMutableDictionary alloc] init];
}
+ (FIRAuth *)auth {
@@ -352,11 +330,10 @@ static NSMutableDictionary *gKeychainServiceNameForAppName;
}
+ (FIRAuth *)authWithApp:(FIRApp *)app {
- return [FIRAppAssociationRegistration registeredObjectWithHost:app
- key:NSStringFromClass(self)
- creationBlock:^FIRAuth *_Nullable() {
- return [[FIRAuth alloc] initWithApp:app];
- }];
+ // Get the instance of Auth from the container, which will create or return the cached instance
+ // associated with this app.
+ id<FIRAuthInterop> auth = FIR_COMPONENT(FIRAuthInterop, app.container);
+ return (FIRAuth *)auth;
}
- (instancetype)initWithApp:(FIRApp *)app {
@@ -365,62 +342,19 @@ static NSMutableDictionary *gKeychainServiceNameForAppName;
if (self) {
_app = app;
__weak FIRAuth *weakSelf = self;
+
+ // TODO: Remove this block once Firestore, Database, and Storage move to the new interop API.
app.getTokenImplementation = ^(BOOL forceRefresh, FIRTokenCallback callback) {
- dispatch_async(FIRAuthGlobalWorkQueue(), ^{
- FIRAuth *strongSelf = weakSelf;
- // Enable token auto-refresh if not aleady enabled.
- if (strongSelf && !strongSelf->_autoRefreshTokens) {
- FIRLogInfo(kFIRLoggerAuth, @"I-AUT000002", @"Token auto-refresh enabled.");
- strongSelf->_autoRefreshTokens = YES;
- [strongSelf scheduleAutoTokenRefresh];
-
- #if TARGET_OS_IOS // TODO: Is a similar mechanism needed on macOS?
- strongSelf->_applicationDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter]
- addObserverForName:UIApplicationDidBecomeActiveNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification *notification) {
- FIRAuth *strongSelf = weakSelf;
- if (strongSelf) {
- strongSelf->_isAppInBackground = NO;
- if (!strongSelf->_autoRefreshScheduled) {
- [weakSelf scheduleAutoTokenRefresh];
- }
- }
- }];
- strongSelf->_applicationDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter]
- addObserverForName:UIApplicationDidEnterBackgroundNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification *notification) {
- FIRAuth *strongSelf = weakSelf;
- if (strongSelf) {
- strongSelf->_isAppInBackground = YES;
- }
- }];
- #endif
- }
- // Call back with 'nil' if there is no current user.
- if (!strongSelf || !strongSelf->_currentUser) {
- dispatch_async(dispatch_get_main_queue(), ^{
- callback(nil, nil);
- });
- return;
- }
- // Call back with current user token.
- [strongSelf->_currentUser internalGetTokenForcingRefresh:forceRefresh
- callback:^(NSString *_Nullable token,
- NSError *_Nullable error) {
- dispatch_async(dispatch_get_main_queue(), ^{
- callback(token, error);
- });
- }];
- });
+ // In the meantime, redirect call to the interop method that provides this functionality.
+ __weak FIRAuth *weakSelf = self;
+ [weakSelf getTokenForcingRefresh:forceRefresh withCallback:callback];
};
+
+ // TODO: Remove this block once Firestore, Database, and Storage move to the new interop API.
app.getUIDImplementation = ^NSString *_Nullable() {
__block NSString *uid;
dispatch_sync(FIRAuthGlobalWorkQueue(), ^{
- uid = [weakSelf getUID];
+ uid = [weakSelf getUserID];
});
return uid;
};
@@ -1878,7 +1812,105 @@ static NSDictionary<NSString *, NSString *> *FIRAuthParseURL(NSString *urlString
return YES;
}
-- (nullable NSString *)getUID {
+#pragma mark - Interoperability
+
++ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
+ FIRComponentCreationBlock authCreationBlock =
+ ^id _Nullable(FIRComponentContainer *_Nonnull container, BOOL *_Nonnull isCacheable) {
+ *isCacheable = YES;
+ return [[FIRAuth alloc] initWithApp:container.app];
+ };
+ FIRComponent *authInterop = [FIRComponent componentWithProtocol:@protocol(FIRAuthInterop)
+ creationBlock:authCreationBlock];
+ return @[authInterop];
+}
+
+#pragma mark - FIRCoreConfigurable
+
++ (void)configureWithApp:(nonnull FIRApp *)app {
+ // TODO: Evaluate what actually needs to be configured here instead of initializing a full
+ // instance.
+ // Ensures the @c FIRAuth instance for a given app gets loaded as soon as the app is ready.
+ [FIRAuth authWithApp:app];
+}
+
+#pragma mark - FIRComponentLifecycleMaintainer
+
+- (void)appWillBeDeleted:(nonnull FIRApp *)app {
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^{
+ // This doesn't stop any request already issued, see b/27704535 .
+ NSString *keychainServiceName = [FIRAuth keychainServiceNameForAppName:app.name];
+ if (keychainServiceName) {
+ [[self class] deleteKeychainServiceNameForAppName:app.name];
+ FIRAuthKeychain *keychain = [[FIRAuthKeychain alloc] initWithService:keychainServiceName];
+ NSString *userKey = [NSString stringWithFormat:kUserKey, app.name];
+ [keychain removeDataForKey:userKey error:NULL];
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // TODO: Move over to fire an event instead, once ready.
+ [[NSNotificationCenter defaultCenter] postNotificationName:FIRAuthStateDidChangeNotification
+ object:nil];
+ });
+ });
+}
+
+#pragma mark - FIRAuthInterop
+
+- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback {
+ __weak FIRAuth *weakSelf = self;
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^{
+ FIRAuth *strongSelf = weakSelf;
+ // Enable token auto-refresh if not aleady enabled.
+ if (strongSelf && !strongSelf->_autoRefreshTokens) {
+ FIRLogInfo(kFIRLoggerAuth, @"I-AUT000002", @"Token auto-refresh enabled.");
+ strongSelf->_autoRefreshTokens = YES;
+ [strongSelf scheduleAutoTokenRefresh];
+
+#if TARGET_OS_IOS || TARGET_OS_TV // TODO: Is a similar mechanism needed on macOS?
+ strongSelf->_applicationDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter]
+ addObserverForName:UIApplicationDidBecomeActiveNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification *notification) {
+ FIRAuth *strongSelf = weakSelf;
+ if (strongSelf) {
+ strongSelf->_isAppInBackground = NO;
+ if (!strongSelf->_autoRefreshScheduled) {
+ [weakSelf scheduleAutoTokenRefresh];
+ }
+ }
+ }];
+ strongSelf->_applicationDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter]
+ addObserverForName:UIApplicationDidEnterBackgroundNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification *notification) {
+ FIRAuth *strongSelf = weakSelf;
+ if (strongSelf) {
+ strongSelf->_isAppInBackground = YES;
+ }
+ }];
+#endif
+ }
+ // Call back with 'nil' if there is no current user.
+ if (!strongSelf || !strongSelf->_currentUser) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(nil, nil);
+ });
+ return;
+ }
+ // Call back with current user token.
+ [strongSelf->_currentUser internalGetTokenForcingRefresh:forceRefresh
+ callback:^(NSString *_Nullable token,
+ NSError *_Nullable error) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ callback(token, error);
+ });
+ }];
+ });
+}
+
+- (nullable NSString *)getUserID {
return _currentUser.uid;
}
diff --git a/Firebase/Auth/Source/FIRAuth_Internal.h b/Firebase/Auth/Source/FIRAuth_Internal.h
index 4d87a08..519ece3 100644
--- a/Firebase/Auth/Source/FIRAuth_Internal.h
+++ b/Firebase/Auth/Source/FIRAuth_Internal.h
@@ -69,11 +69,11 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
appName:(NSString *)appName NS_DESIGNATED_INITIALIZER;
-/** @fn getUID
+/** @fn getUserID
@brief Gets the identifier of the current user, if any.
@return The identifier of the current user, or nil if there is no current user.
*/
-- (nullable NSString *)getUID;
+- (nullable NSString *)getUserID;
/** @fn updateKeychainWithUser:error:
@brief Updates the keychain for the given user.
diff --git a/Firebase/Auth/Source/FIRUser.m b/Firebase/Auth/Source/FIRUser.m
index ad0b1d4..f3832a7 100644
--- a/Firebase/Auth/Source/FIRUser.m
+++ b/Firebase/Auth/Source/FIRUser.m
@@ -766,7 +766,7 @@ static void callInMainThreadWithAuthDataResultAndError(
callInMainThreadWithAuthDataResultAndError(completion, authResult, error);
return;
}
- if (![authResult.user.uid isEqual:[self->_auth getUID]]) {
+ if (![authResult.user.uid isEqual:[self->_auth getUserID]]) {
callInMainThreadWithAuthDataResultAndError(completion, authResult,
[FIRAuthErrorUtils userMismatchError]);
return;
diff --git a/Firebase/Core/FIRApp.m b/Firebase/Core/FIRApp.m
index 9f698cf..5fca127 100644
--- a/Firebase/Core/FIRApp.m
+++ b/Firebase/Core/FIRApp.m
@@ -517,6 +517,7 @@ static NSMutableDictionary *sLibraryVersions;
}
}
+// TODO: Remove once SDKs transition to Auth interop library.
- (nullable NSString *)getUID {
if (!_getUIDImplementation) {
FIRLogWarning(kFIRLoggerCore, @"I-COR000025", @"FIRAuth getUID implementation wasn't set.");