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 .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
- name: Lint podspec using local source
run: |
pod lib lint ${{ matrix.podspec }} --verbose \
--sources=https://github.com/firebase/SpecsDev.git,https://cdn.cocoapods.org/ \
${{ matrix.includePodspecFlag }} ${{ matrix.flag }}

spm-build-test:
Expand Down
2 changes: 1 addition & 1 deletion GoogleSignIn.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The Google Sign-In SDK allows users to sign in with their Google account from th
]
s.ios.framework = 'UIKit'
s.osx.framework = 'AppKit'
s.dependency 'FirebaseAppCheck', '~> 10.0'
s.dependency 'AppCheckCore', '~> 0.1.0-alpha'
s.dependency 'AppAuth', '~> 1.6'
s.dependency 'GTMAppAuth', '~> 4.0'
s.dependency 'GTMSessionFetcher/Core', '>= 1.1', '< 4.0'
Expand Down
59 changes: 0 additions & 59 deletions GoogleSignIn/Sources/GIDAppCheck/API/GIDAppCheckProvider.h

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,25 @@
#import <Foundation/Foundation.h>

#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
#import "GoogleSignIn/Sources/GIDAppCheckTokenFetcher/API/GIDAppCheckTokenFetcher.h"
#import <AppCheckCore/GACAppCheckProvider.h>

@class FIRAppCheckToken;
@class GACAppCheckToken;

NS_ASSUME_NONNULL_BEGIN

extern NSUInteger const kGIDAppCheckTokenFetcherTokenError;
extern NSUInteger const kGIDAppCheckProviderFakeError;

NS_CLASS_AVAILABLE_IOS(14)
@interface GIDAppCheckTokenFetcherFake : NSObject <GIDAppCheckTokenFetcher>
@interface GIDAppCheckProviderFake : NSObject <GACAppCheckProvider>

/// Creates an instance with the provided app check token and error.
/// Creates an instance conforming to `GACAppCheckProvider` with the provided app check token and
/// error.
///
/// This protocol is mainly used for testing purposes so that the token fetching from Firebase App
/// Check can be faked.
/// @param token The `FIRAppCheckToken` to pass into the completion called from
/// `limitedUseTokenWithCompletion:`.
/// @param token The `GACAppCheckToken` instance to pass into the completion called from
/// `getTokenWithCompletion:`.
/// @param error The `NSError` to pass into the completion called from
/// `limitedUseTokenWithCompletion:`.
- (instancetype)initWithAppCheckToken:(nullable FIRAppCheckToken *)token
/// `getTokenWithCompletion:`.
- (instancetype)initWithAppCheckToken:(nullable GACAppCheckToken *)token
error:(nullable NSError *)error;

@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#import <TargetConditionals.h>
#import "GoogleSignIn/Sources/GIDAppCheck/Implementations/Fake/GIDAppCheckProviderFake.h"

#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
#import "GoogleSignIn/Sources/GIDAppCheckTokenFetcher/Implementations/GIDAppCheckTokenFetcherFake.h"

@import FirebaseAppCheck;
#import <AppCheckCore/GACAppCheckToken.h>

NSUInteger const kGIDAppCheckTokenFetcherTokenError = 1;
NSUInteger const kGIDAppCheckProviderFakeError = 1;

@interface GIDAppCheckTokenFetcherFake ()
@interface GIDAppCheckProviderFake ()

@property(nonatomic, strong, nullable) FIRAppCheckToken *token;
@property(nonatomic, strong, nullable) id<GACAppCheckTokenProtocol> token;
@property(nonatomic, strong, nullable) NSError *error;

@end

@implementation GIDAppCheckTokenFetcherFake
@implementation GIDAppCheckProviderFake

- (instancetype)initWithAppCheckToken:(nullable FIRAppCheckToken *)token
- (instancetype)initWithAppCheckToken:(nullable id<GACAppCheckTokenProtocol>)token
error:(nullable NSError *)error {
if (self = [super init]) {
_token = token;
Expand All @@ -39,10 +38,10 @@ - (instancetype)initWithAppCheckToken:(nullable FIRAppCheckToken *)token
return self;
}

- (void)limitedUseTokenWithCompletion:(void (^)(FIRAppCheckToken * _Nullable,
NSError * _Nullable))completion {
- (void)getTokenWithCompletion:(nonnull void (^)(GACAppCheckToken * _Nullable,
NSError * _Nullable))handler {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self.token, self.error);
handler(self.token, self.error);
});
}

Expand Down
41 changes: 37 additions & 4 deletions GoogleSignIn/Sources/GIDAppCheck/Implementations/GIDAppCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,50 @@
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST

#import <Foundation/Foundation.h>
#import "GoogleSignIn/Sources/GIDAppCheck/API/GIDAppCheckProvider.h"

NS_ASSUME_NONNULL_BEGIN

@class FIRAppCheckToken;
@protocol GACAppCheckProvider;
@protocol GACAppCheckTokenProtocol;

extern NSString *const kGIDAppCheckPreparedKey;

NS_CLASS_AVAILABLE_IOS(14)
@interface GIDAppCheck : NSObject <GIDAppCheckProvider>
@interface GIDAppCheck : NSObject

/// Creates the instance of this App Check wrapper class.
///
/// The instance is created using `+[NSUserDefaults standardUserDefaults]` and the standard App
/// Check provider.
///
/// @SeeAlso The App Check provider is constructed with `+[GIDAppCheck standardAppCheckProvider]`.
- (instancetype)init;

/// Creates the instance of this App Check wrapper class.
///
/// @param appCheckProvider The instance performing the Firebase App Check token requests. If `nil`,
/// then a default implementation will be used.
/// @param userDefaults The instance of `NSUserDefaults` that `GIDAppCheck` will use to store its
/// preparation status. If nil, `GIDAppCheck` will use `-[NSUserDefaults standardUserDefaults]`.
- (instancetype)initWithAppCheckProvider:(id<GACAppCheckProvider>)appCheckProvider
userDefaults:(NSUserDefaults *)userDefaults NS_DESIGNATED_INITIALIZER;

/// Prewarms the library for App Check by asking Firebase App Check to generate the App Attest key
/// id and perform the initial attestation process (if needed).
///
/// @param completion A `nullable` callback with a `nullable` `NSError` if preparation fails.
- (void)prepareForAppCheckWithCompletion:(nullable void (^)(NSError * _Nullable error))completion;

/// Fetches the limited use Firebase token.
///
/// @param completion A `nullable` callback with the `FIRAppCheckToken` if present, or an `NSError`
/// otherwise.
- (void)getLimitedUseTokenWithCompletion:
(nullable void (^)(id<GACAppCheckTokenProtocol> _Nullable token,
NSError * _Nullable error))completion;

- (instancetype)init NS_UNAVAILABLE;
/// Whether or not the App Attest key ID created and the attestation object has been fetched.
- (BOOL)isPrepared;

@end

Expand Down
66 changes: 51 additions & 15 deletions GoogleSignIn/Sources/GIDAppCheck/Implementations/GIDAppCheck.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,32 @@
*/

#import "GoogleSignIn/Sources/GIDAppCheck/Implementations/GIDAppCheck.h"
#import "GoogleSignIn/Sources/GIDAppCheck/API/GIDAppCheckProvider.h"
#import "GoogleSignIn/Sources/GIDAppCheckTokenFetcher/Implementations/FIRAppCheck+GIDAppCheckTokenFetcher.h"
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDAppCheckError.h"

@import FirebaseAppCheck;

#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST

#import <AppCheckCore/GACAppCheck.h>
#import <AppCheckCore/GACAppCheckSettings.h>
#import <AppCheckCore/GACAppCheckToken.h>
#import <AppCheckCore/GACAppAttestProvider.h>

#import "GoogleSignIn/Sources/GIDAppCheck/Implementations/GIDAppCheck.h"
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDAppCheckError.h"
#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h"

NSErrorDomain const kGIDAppCheckErrorDomain = @"com.google.GIDAppCheck";
NSString *const kGIDAppCheckPreparedKey = @"com.google.GIDAppCheckPreparedKey";
static NSString *const kGIDConfigClientIDKey = @"GIDClientID";
static NSString *const kGIDAppAttestServiceName = @"GoogleSignIn-iOS";
static NSString *const kGIDAppAttestResourceNameFormat = @"oauthClients/%@";
static NSString *const kGIDAppAttestBaseURL = @"https://firebaseappcheck.googleapis.com/v1beta";

typedef void (^GIDAppCheckPrepareCompletion)(NSError * _Nullable);
typedef void (^GIDAppCheckTokenCompletion)(FIRAppCheckToken * _Nullable, NSError * _Nullable);
typedef void (^GIDAppCheckTokenCompletion)(id<GACAppCheckTokenProtocol> _Nullable,
NSError * _Nullable);

@interface GIDAppCheck ()

@property(nonatomic, strong) id<GIDAppCheckTokenFetcher> tokenFetcher;
@property(nonatomic, strong) GACAppCheck *appCheck;
@property(nonatomic, strong) dispatch_queue_t workerQueue;
@property(nonatomic, strong) NSUserDefaults *userDefaults;
@property(atomic, strong) NSMutableArray<GIDAppCheckPrepareCompletion> *prepareCompletions;
Expand All @@ -41,11 +50,23 @@ @interface GIDAppCheck ()

@implementation GIDAppCheck

- (instancetype)initWithAppCheckTokenFetcher:(nullable id<GIDAppCheckTokenFetcher>)tokenFetcher
userDefaults:(nullable NSUserDefaults *)userDefaults {
- (instancetype)init {
id<GACAppCheckProvider> provider = [GIDAppCheck standardAppCheckProvider];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
return [self initWithAppCheckProvider:provider userDefaults:userDefaults];
}

- (instancetype)initWithAppCheckProvider:(id<GACAppCheckProvider>)appCheckProvider
userDefaults:(NSUserDefaults *)userDefaults {
if (self = [super init]) {
_tokenFetcher = tokenFetcher ?: [FIRAppCheck appCheck];
_userDefaults = userDefaults ?: [NSUserDefaults standardUserDefaults];
_appCheck = [[GACAppCheck alloc] initWithServiceName:kGIDConfigClientIDKey
resourceName:[GIDAppCheck appAttestResourceName]
appCheckProvider:appCheckProvider
settings:[[GACAppCheckSettings alloc] init]
tokenDelegate:nil
keychainAccessGroup:nil];

_userDefaults = userDefaults;
_workerQueue = dispatch_queue_create("com.google.googlesignin.GIDAppCheckWorkerQueue", nil);
_prepareCompletions = [NSMutableArray array];
_preparing = NO;
Expand Down Expand Up @@ -89,8 +110,8 @@ - (void)prepareForAppCheckWithCompletion:(nullable GIDAppCheckPrepareCompletion)
return;
}

[self.tokenFetcher limitedUseTokenWithCompletion:^(FIRAppCheckToken * _Nullable token,
NSError * _Nullable error) {
[self.appCheck getLimitedUseTokenWithCompletion:^(id<GACAppCheckTokenProtocol> _Nullable token,
NSError * _Nullable error) {
NSError * __block maybeError = error;
@synchronized (self) {
if (!token && !error) {
Expand Down Expand Up @@ -118,8 +139,8 @@ - (void)prepareForAppCheckWithCompletion:(nullable GIDAppCheckPrepareCompletion)

- (void)getLimitedUseTokenWithCompletion:(nullable GIDAppCheckTokenCompletion)completion {
dispatch_async(self.workerQueue, ^{
[self.tokenFetcher limitedUseTokenWithCompletion:^(FIRAppCheckToken * _Nullable token,
NSError * _Nullable error) {
[self.appCheck getLimitedUseTokenWithCompletion:^(id<GACAppCheckTokenProtocol> _Nullable token,
NSError * _Nullable error) {
if (token) {
[self.userDefaults setBool:YES forKey:kGIDAppCheckPreparedKey];
}
Expand All @@ -130,6 +151,21 @@ - (void)getLimitedUseTokenWithCompletion:(nullable GIDAppCheckTokenCompletion)co
});
}

+ (NSString *)appAttestResourceName {
NSString *clientID = [NSBundle.mainBundle objectForInfoDictionaryKey:kGIDConfigClientIDKey];
return [NSString stringWithFormat:kGIDAppAttestResourceNameFormat, clientID];
}

+ (id<GACAppCheckProvider>)standardAppCheckProvider {
return [[GACAppAttestProvider alloc] initWithServiceName:kGIDAppAttestServiceName
resourceName:[GIDAppCheck appAttestResourceName]
baseURL:kGIDAppAttestBaseURL
APIKey:nil
keychainAccessGroup:nil
limitedUse:YES
requestHooks:nil];
}

@end

#endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST

This file was deleted.

This file was deleted.

Loading