Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AppCheck.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Pod::Spec.new do |s|
s.osx.weak_framework = 'DeviceCheck'
s.tvos.weak_framework = 'DeviceCheck'

s.dependency 'AppCheckInterop', '~> 10.10'
s.dependency 'FirebaseCore', '~> 10.0'
s.dependency 'PromisesObjC', '~> 2.1'
s.dependency 'GoogleUtilities/Environment', '~> 7.8'
Expand Down
29 changes: 0 additions & 29 deletions AppCheck/Sources/Core/GACAppCheck+Internal.h

This file was deleted.

111 changes: 26 additions & 85 deletions AppCheck/Sources/Core/GACAppCheck.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@

#import "AppCheck/Sources/Public/AppCheck/GACAppCheckErrors.h"
#import "AppCheck/Sources/Public/AppCheck/GACAppCheckProvider.h"
#import "AppCheck/Sources/Public/AppCheck/GACAppCheckProviderFactory.h"

#import "AppCheck/Sources/Core/Errors/GACAppCheckErrorUtil.h"
#import "AppCheck/Sources/Core/GACAppCheck+Internal.h"
#import "AppCheck/Sources/Core/GACAppCheckLogger.h"
#import "AppCheck/Sources/Core/GACAppCheckSettings.h"
#import "AppCheck/Sources/Core/GACAppCheckToken+Internal.h"
Expand Down Expand Up @@ -64,14 +62,11 @@
@"FirebaseAppCheckTokenAutoRefreshEnabled";
// FIREBASE_APP_CHECK_ONLY_END

static id<GACAppCheckProviderFactory> _providerFactory;

static const NSTimeInterval kTokenExpirationThreshold = 5 * 60; // 5 min.

static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1IifQ==";

@interface GACAppCheck () <GACAppCheckInterop>
@property(class, nullable) id<GACAppCheckProviderFactory> providerFactory;
@interface GACAppCheck ()

@property(nonatomic, readonly) NSString *appName;
@property(nonatomic, readonly) id<GACAppCheckProvider> appCheckProvider;
Expand All @@ -83,33 +78,41 @@ @interface GACAppCheck () <GACAppCheckInterop>

@property(nonatomic, nullable) FBLPromise<GACAppCheckToken *> *ongoingRetrieveOrRefreshTokenPromise;
@property(nonatomic, nullable) FBLPromise<GACAppCheckToken *> *ongoingLimitedUseTokenPromise;

@end

@implementation GACAppCheck

#pragma mark - Internal

- (nullable instancetype)initWithApp:(FIRApp *)app {
id<GACAppCheckProviderFactory> providerFactory = [GACAppCheck providerFactory];
- (instancetype)initWithAppName:(NSString *)appName
appCheckProvider:(id<GACAppCheckProvider>)appCheckProvider
storage:(id<GACAppCheckStorageProtocol>)storage
tokenRefresher:(id<GACAppCheckTokenRefresherProtocol>)tokenRefresher
notificationCenter:(NSNotificationCenter *)notificationCenter
settings:(id<GACAppCheckSettingsProtocol>)settings {
self = [super init];
if (self) {
_appName = appName;
_appCheckProvider = appCheckProvider;
_storage = storage;
_tokenRefresher = tokenRefresher;
_notificationCenter = notificationCenter;
_settings = settings;

if (providerFactory == nil) {
GACLogError(kFIRLoggerAppCheckMessageCodeProviderFactoryIsMissing,
@"Cannot instantiate `GACAppCheck` for app: %@ without a provider factory. "
@"Please register a provider factory using "
@"`AppCheck.setAppCheckProviderFactory(_ ,forAppName:)` method.",
app.name);
return nil;
__auto_type __weak weakSelf = self;
tokenRefresher.tokenRefreshHandler = ^(GACAppCheckTokenRefreshCompletion _Nonnull completion) {
__auto_type strongSelf = weakSelf;
[strongSelf periodicTokenRefreshWithCompletion:completion];
};
}
return self;
}

id<GACAppCheckProvider> appCheckProvider = [providerFactory createProviderWithApp:app];
if (appCheckProvider == nil) {
GACLogError(kFIRLoggerAppCheckMessageCodeProviderIsMissing,
@"Cannot instantiate `GACAppCheck` for app: %@ without an app check provider. "
@"Please make sure the provider factory returns a valid app check provider.",
app.name);
return nil;
}
#pragma mark - Public

- (instancetype)initWithApp:(FIRApp *)app
appCheckProvider:(id<GACAppCheckProvider>)appCheckProvider {
id<GACAppCheckSettingsProtocol> settings = [[GACAppCheckSettings alloc]
initWithUserDefaults:[NSUserDefaults standardUserDefaults]
mainBundle:[NSBundle mainBundle]
Expand Down Expand Up @@ -137,50 +140,6 @@ - (nullable instancetype)initWithApp:(FIRApp *)app {
settings:settings];
}

- (instancetype)initWithAppName:(NSString *)appName
appCheckProvider:(id<GACAppCheckProvider>)appCheckProvider
storage:(id<GACAppCheckStorageProtocol>)storage
tokenRefresher:(id<GACAppCheckTokenRefresherProtocol>)tokenRefresher
notificationCenter:(NSNotificationCenter *)notificationCenter
settings:(id<GACAppCheckSettingsProtocol>)settings {
self = [super init];
if (self) {
_appName = appName;
_appCheckProvider = appCheckProvider;
_storage = storage;
_tokenRefresher = tokenRefresher;
_notificationCenter = notificationCenter;
_settings = settings;

__auto_type __weak weakSelf = self;
tokenRefresher.tokenRefreshHandler = ^(GACAppCheckTokenRefreshCompletion _Nonnull completion) {
__auto_type strongSelf = weakSelf;
[strongSelf periodicTokenRefreshWithCompletion:completion];
};
}
return self;
}

#pragma mark - Public

+ (instancetype)appCheck {
FIRApp *defaultApp = [FIRApp defaultApp];
if (!defaultApp) {
[NSException raise:GACAppCheckErrorDomain
format:@"The default FirebaseApp instance must be configured before the default"
@"AppCheck instance can be initialized. One way to ensure this is to "
@"call `FirebaseApp.configure()` in the App Delegate's "
@"`application(_:didFinishLaunchingWithOptions:)` (or the `@main` struct's "
@"initializer in SwiftUI)."];
}
return [self appCheckWithApp:defaultApp];
}

+ (nullable instancetype)appCheckWithApp:(FIRApp *)firebaseApp {
id<GACAppCheckInterop> appCheck = FIR_COMPONENT(GACAppCheckInterop, firebaseApp.container);
return (GACAppCheck *)appCheck;
}

- (void)tokenForcingRefresh:(BOOL)forcingRefresh
completion:(void (^)(GACAppCheckToken *_Nullable token,
NSError *_Nullable error))handler {
Expand All @@ -206,10 +165,6 @@ - (void)limitedUseTokenWithCompletion:(void (^)(GACAppCheckToken *_Nullable toke
});
}

+ (void)setAppCheckProviderFactory:(nullable id<GACAppCheckProviderFactory>)factory {
self.providerFactory = factory;
}

- (void)setIsTokenAutoRefreshEnabled:(BOOL)isTokenAutoRefreshEnabled {
self.settings.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
}
Expand All @@ -218,20 +173,6 @@ - (BOOL)isTokenAutoRefreshEnabled {
return self.settings.isTokenAutoRefreshEnabled;
}

#pragma mark - App Check Provider Ingestion

+ (void)setProviderFactory:(nullable id<GACAppCheckProviderFactory>)providerFactory {
@synchronized(self) {
_providerFactory = providerFactory;
}
}

+ (nullable id<GACAppCheckProviderFactory>)providerFactory {
@synchronized(self) {
return _providerFactory;
}
}

#pragma mark - GACAppCheckInterop

- (void)getTokenForcingRefresh:(BOOL)forcingRefresh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,11 @@

#import "AppCheck/Sources/Public/AppCheck/GACDeviceCheckProviderFactory.h"

#import "AppCheck/Sources/Public/AppCheck/GACAppCheck.h"
#import "AppCheck/Sources/Public/AppCheck/GACAppCheckProvider.h"
#import "AppCheck/Sources/Public/AppCheck/GACDeviceCheckProvider.h"

@implementation GACDeviceCheckProviderFactory

+ (void)load {
Copy link
Member

Choose a reason for hiding this comment

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

Great to see load going away.

[GACAppCheck setAppCheckProviderFactory:[[self alloc] init]];
}

- (nullable id<GACAppCheckProvider>)createProviderWithApp:(nonnull FIRApp *)app {
return [[GACDeviceCheckProvider alloc] initWithApp:app];
}
Expand Down
34 changes: 9 additions & 25 deletions AppCheck/Sources/Public/AppCheck/GACAppCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

#import <Foundation/Foundation.h>

#import <AppCheckInterop/GACAppCheckInterop.h>

@class FIRApp;
@class GACAppCheckToken;
@protocol GACAppCheckProviderFactory;
@protocol GACAppCheckProvider;

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -35,21 +37,16 @@ FOUNDATION_EXPORT NSString *const kGACAppCheckTokenNotificationKey NS_SWIFT_NAME
FOUNDATION_EXPORT NSString *const kGACAppCheckAppNameNotificationKey NS_SWIFT_NAME(InternalAppCheckAppNameNotificationKey);

NS_SWIFT_NAME(InternalAppCheck)
@interface GACAppCheck : NSObject
@interface GACAppCheck : NSObject <GACAppCheckInterop>

- (instancetype)init NS_UNAVAILABLE;

/// Returns a default instance of `AppCheck`.
/// @return An instance of `AppCheck` for `FirebaseApp.defaultApp()`.
/// @throw Throws an exception if the default app is not configured yet or required `FirebaseApp`
/// options are missing.
+ (instancetype)appCheck NS_SWIFT_NAME(appCheck());

/// Returns an instance of `AppCheck` for an application.
/// @param firebaseApp A configured `FirebaseApp` instance if exists.
/// @return An instance of `AppCheck` corresponding to the passed application.
/// @throw Throws an exception if required `FirebaseApp` options are missing.
+ (nullable instancetype)appCheckWithApp:(FIRApp *)firebaseApp NS_SWIFT_NAME(appCheck(app:));
/// @param app A configured `FirebaseApp` instance.
/// @param appCheckProvider An `InternalAppCheckProvider` instance that provides App Check tokens.
/// @return An instance of `AppCheck` corresponding to the provided `app`.
- (instancetype)initWithApp:(FIRApp *)app
appCheckProvider:(id<GACAppCheckProvider>)appCheckProvider;

/// Requests Firebase app check token. This method should *only* be used if you need to authorize
/// requests to a non-Firebase backend. Requests to Firebase backend are authorized automatically if
Expand Down Expand Up @@ -81,19 +78,6 @@ NS_SWIFT_NAME(InternalAppCheck)
- (void)limitedUseTokenWithCompletion:(void (^)(GACAppCheckToken *_Nullable token,
NSError *_Nullable error))handler;

/// Sets the `AppCheckProviderFactory` to use to generate
/// `AppCheckDebugProvider` objects.
///
/// An instance of `DeviceCheckProviderFactory` is used by default, but you can
/// also use a custom `AppCheckProviderFactory` implementation or an
/// instance of `AppCheckDebugProviderFactory` to test your app on a simulator
/// on a local machine or a build server.
///
/// NOTE: Make sure to call this method before `FirebaseApp.configure()`. If
/// this method is called after configuring Firebase, the changes will not take
/// effect.
+ (void)setAppCheckProviderFactory:(nullable id<GACAppCheckProviderFactory>)factory;

/// If this flag is disabled then Firebase app check will not periodically auto-refresh the app
/// check token. The default value of the flag is equal to
/// `FirebaseApp.dataCollectionDefaultEnabled`. To disable the flag by default set
Expand Down
10 changes: 2 additions & 8 deletions AppCheck/Tests/Unit/Core/GACAppCheckIntegrationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,6 @@ - (void)setUp {
- (void)tearDown {
[FIRApp resetApps];

if (@available(iOS 11.0, macOS 10.15, macCatalyst 13.0, tvOS 11.0, watchOS 9.0, *)) {
// Recover default provider factory.
[GACAppCheck setAppCheckProviderFactory:[[GACDeviceCheckProviderFactory alloc] init]];
}

[self.mockTokenRefresher stopMocking];
self.mockTokenRefresher = nil;
[self.mockProviderFactory stopMocking];
Expand Down Expand Up @@ -207,16 +202,15 @@ - (void)configureAppWithName:(NSString *)appName {
}

- (void)usageExample {
// Set a custom app check provider factory for the default FIRApp.
[GACAppCheck setAppCheckProviderFactory:[[AppCheckProviderFactory alloc] init]];
[FIRApp configure];

FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:@"path"];
[FIRApp configureWithName:@"AppName" options:options];

FIRApp *defaultApp = [FIRApp defaultApp];

id<GACAppCheckInterop> defaultAppCheck = FIR_COMPONENT(GACAppCheckInterop, defaultApp.container);
id<GACAppCheckInterop> defaultAppCheck =
[[GACAppCheck alloc] initWithApp:defaultApp appCheckProvider:self.mockAppCheckProvider];

[defaultAppCheck getTokenForcingRefresh:NO
completion:^(id<GACAppCheckTokenResultInterop> tokenResult) {
Expand Down
10 changes: 2 additions & 8 deletions AppCheck/Tests/Unit/Core/GACAppCheckTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@
static NSString *const kDummyToken = @"eyJlcnJvciI6IlVOS05PV05fRVJST1IifQ==";

@interface GACAppCheck (Tests) <GACAppCheckInterop>

- (instancetype)initWithAppName:(NSString *)appName
appCheckProvider:(id<GACAppCheckProvider>)appCheckProvider
storage:(id<GACAppCheckStorageProtocol>)storage
tokenRefresher:(id<GACAppCheckTokenRefresherProtocol>)tokenRefresher
notificationCenter:(NSNotificationCenter *)notificationCenter
settings:(id<GACAppCheckSettingsProtocol>)settings;

- (nullable instancetype)initWithApp:(FIRApp *)app;
@end

@interface GACAppCheckTests : XCTestCase
Expand Down Expand Up @@ -146,23 +146,17 @@ - (void)testInitWithApp {
OCMExpect([mockStorage initWithTokenKey:tokenKey accessGroup:appGroupID]).andReturn(mockStorage);

// 4. Stub attestation provider.
OCMockObject<GACAppCheckProviderFactory> *mockProviderFactory =
OCMProtocolMock(@protocol(GACAppCheckProviderFactory));
OCMockObject<GACAppCheckProvider> *mockProvider = OCMProtocolMock(@protocol(GACAppCheckProvider));
OCMExpect([mockProviderFactory createProviderWithApp:mockApp]).andReturn(mockProvider);

[GACAppCheck setAppCheckProviderFactory:mockProviderFactory];

// 5. Call init.
GACAppCheck *appCheck = [[GACAppCheck alloc] initWithApp:mockApp];
GACAppCheck *appCheck = [[GACAppCheck alloc] initWithApp:mockApp appCheckProvider:mockProvider];
XCTAssert([appCheck isKindOfClass:[GACAppCheck class]]);

// 6. Verify mocks.
OCMVerifyAll(mockApp);
OCMVerifyAll(mockAppOptions);
OCMVerifyAll(mockTokenRefresher);
OCMVerifyAll(mockStorage);
OCMVerifyAll(mockProviderFactory);
OCMVerifyAll(mockProvider);

// 7. Stop mocking real class mocks.
Expand Down
Loading