aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Database/Login
diff options
context:
space:
mode:
authorGravatar Paul Beusterien <paulbeusterien@google.com>2017-05-15 12:27:07 -0700
committerGravatar Paul Beusterien <paulbeusterien@google.com>2017-05-15 12:27:07 -0700
commit98ba64449a632518bd2b86fe8d927f4a960d3ddc (patch)
tree131d9c4272fa6179fcda6c5a33fcb3b1bd57ad2e /Firebase/Database/Login
parent32461366c9e204a527ca05e6e9b9404a2454ac51 (diff)
Initial
Diffstat (limited to 'Firebase/Database/Login')
-rw-r--r--Firebase/Database/Login/FAuthTokenProvider.h36
-rw-r--r--Firebase/Database/Login/FAuthTokenProvider.m162
-rw-r--r--Firebase/Database/Login/FIRNoopAuthTokenProvider.h22
-rw-r--r--Firebase/Database/Login/FIRNoopAuthTokenProvider.m33
4 files changed, 253 insertions, 0 deletions
diff --git a/Firebase/Database/Login/FAuthTokenProvider.h b/Firebase/Database/Login/FAuthTokenProvider.h
new file mode 100644
index 0000000..dca0026
--- /dev/null
+++ b/Firebase/Database/Login/FAuthTokenProvider.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "FTypedefs.h"
+#import "FTypedefs_Private.h"
+
+@protocol FAuthTokenProvider <NSObject>
+
+- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback;
+
+- (void) listenForTokenChanges:(fbt_void_nsstring)listener;
+
+@end
+
+@interface FAuthTokenProvider : NSObject
+
++ (id<FAuthTokenProvider>) authTokenProviderForApp:(id)app;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
diff --git a/Firebase/Database/Login/FAuthTokenProvider.m b/Firebase/Database/Login/FAuthTokenProvider.m
new file mode 100644
index 0000000..e406ae7
--- /dev/null
+++ b/Firebase/Database/Login/FAuthTokenProvider.m
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FAuthTokenProvider.h"
+#import "FUtilities.h"
+#import "FIRDatabaseQuery_Private.h"
+#import "FIRNoopAuthTokenProvider.h"
+
+static NSString *const FIRAuthStateDidChangeInternalNotification = @"FIRAuthStateDidChangeInternalNotification";
+static NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = @"FIRAuthStateDidChangeInternalNotificationTokenKey";
+
+
+/**
+ * This is a hack that defines all the methods we need from FIRFirebaseApp. At runtime we use reflection to get an
+ * actual instance of FIRFirebaseApp. Since protocols don't carry any runtime information and selectors are invoked
+ * by name we can write code against this protocol as long as the method signatures of FIRFirebaseApp don't change.
+ */
+@protocol FIRFirebaseAppLike <NSObject>
+
+- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(void (^)(NSString *_Nullable token, NSError *_Nullable error))callback;
+
+@end
+
+
+/**
+ * This is a hack that defines all the methods we need from FIRAuth.
+ */
+@protocol FIRFirebaseAuthLike <NSObject>
+
+- (id<FIRFirebaseAppLike>) app;
+
+@end
+
+/**
+ * This is a hack that copies the definitions of Firebear error codes. If the error codes change in the original code, this
+ * will break at runtime due to undefined behavior!
+ */
+typedef NS_ENUM(NSUInteger, FIRErrorCode) {
+ /*! @var FIRErrorCodeNoAuth
+ @brief Represents the case where an auth-related message was sent to a @c FIRFirebaseApp
+ instance which has no associated @c FIRAuth instance.
+ */
+ FIRErrorCodeNoAuth,
+
+ /*! @var FIRErrorCodeNoSignedInUser
+ @brief Represents the case where an attempt was made to fetch a token when there is no signed
+ in user.
+ */
+ FIRErrorCodeNoSignedInUser,
+};
+
+
+@interface FAuthStateListenerWrapper : NSObject
+
+@property (nonatomic, copy) fbt_void_nsstring listener;
+
+@property (nonatomic, weak) id<FIRFirebaseAppLike> app;
+
+@end
+
+@implementation FAuthStateListenerWrapper
+
+- (instancetype) initWithListener:(fbt_void_nsstring)listener app:(id<FIRFirebaseAppLike>)app {
+ self = [super init];
+ if (self != nil) {
+ self->_listener = listener;
+ self->_app = app;
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(authStateDidChangeNotification:)
+ name:FIRAuthStateDidChangeInternalNotification
+ object:nil];
+ }
+ return self;
+}
+
+- (void) authStateDidChangeNotification:(NSNotification *)notification {
+ id<FIRFirebaseAuthLike> auth = notification.object;
+ if (auth.app == self->_app) {
+ NSDictionary *userInfo = notification.userInfo;
+ NSString *token = userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey];
+ dispatch_async([FIRDatabaseQuery sharedQueue], ^{
+ self.listener(token);
+ });
+ }
+}
+
+- (void) dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+@end
+
+
+@interface FIRFirebearAuthTokenProvider : NSObject <FAuthTokenProvider>
+
+@property (nonatomic, strong) id<FIRFirebaseAppLike> app;
+/** Strong references to the auth listeners as they are only weak in FIRFirebaseApp */
+@property (nonatomic, strong) NSMutableArray *authListeners;
+
+- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app;
+
+@end
+
+@implementation FIRFirebearAuthTokenProvider
+
+- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app {
+ self = [super init];
+ if (self != nil) {
+ self->_app = app;
+ self->_authListeners = [NSMutableArray array];
+ }
+ return self;
+}
+
+- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback {
+ // TODO: Don't fetch token if there is no current user
+ [self.app getTokenForcingRefresh:forceRefresh withCallback:^(NSString * _Nullable token, NSError * _Nullable error) {
+ dispatch_async([FIRDatabaseQuery sharedQueue], ^{
+ if (error != nil) {
+ if (error.code == FIRErrorCodeNoAuth) {
+ FFLog(@"I-RDB073001", @"Firebase Auth is not configured, not going to use authentication.");
+ callback(nil, nil);
+ } else if (error.code == FIRErrorCodeNoSignedInUser) {
+ // No signed in user is an expected case, callback as success with no token
+ callback(nil, nil);
+ } else {
+ callback(nil, error);
+ }
+ } else {
+ callback(token, nil);
+ }
+ });
+ }];
+}
+
+- (void) listenForTokenChanges:(_Nonnull fbt_void_nsstring)listener {
+ FAuthStateListenerWrapper *wrapper = [[FAuthStateListenerWrapper alloc] initWithListener:listener app:self.app];
+ [self.authListeners addObject:wrapper];
+}
+
+@end
+
+@implementation FAuthTokenProvider
+
++ (id<FAuthTokenProvider>) authTokenProviderForApp:(id)app {
+ return [[FIRFirebearAuthTokenProvider alloc] initWithFirebaseApp:app];
+}
+
+@end
diff --git a/Firebase/Database/Login/FIRNoopAuthTokenProvider.h b/Firebase/Database/Login/FIRNoopAuthTokenProvider.h
new file mode 100644
index 0000000..e27ddb4
--- /dev/null
+++ b/Firebase/Database/Login/FIRNoopAuthTokenProvider.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "FAuthTokenProvider.h"
+
+@interface FIRNoopAuthTokenProvider : NSObject <FAuthTokenProvider>
+
+@end
diff --git a/Firebase/Database/Login/FIRNoopAuthTokenProvider.m b/Firebase/Database/Login/FIRNoopAuthTokenProvider.m
new file mode 100644
index 0000000..8bf467b
--- /dev/null
+++ b/Firebase/Database/Login/FIRNoopAuthTokenProvider.m
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FIRNoopAuthTokenProvider.h"
+#import "FAuthTokenProvider.h"
+#import "FIRDatabaseQuery_Private.h"
+
+@implementation FIRNoopAuthTokenProvider
+
+- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback {
+ dispatch_async([FIRDatabaseQuery sharedQueue], ^{
+ callback(nil, nil);
+ });
+}
+
+- (void) listenForTokenChanges:(fbt_void_nsstring)listener {
+ // no-op, because token never changes
+}
+
+@end