Skip to content

Commit 43cd9c2

Browse files
authored
Merge App check auth integration into master branch (#11056)
* Auth integration with AppCheck (#10798) * Auth App check integration without unit testing * Add Unitest for AppCheck Auth Integration * Style the format for Auth-Appcheck Integration * Fix typo in import for FIRAppCheckInterop * Style this file * Fix wrong import * Fix style for this file * Fix style in this file * Add Source path for FIRAppCheckInterop * Add self to async block in Unit Test * Fix: pass appcheckInterop to request configuration * style the fixed files * revert files that are only for local testing * modify init method to avoid more changes * remove extra comments * upload for debug unit test * Revert Sample changes and add appcheck into unit tests * Fix issues in FIRAuthRequestConfiguration and typos in unit tests * fix error loading and revert pod files * Add spaces to keep style consistent * pass appCheckToken as URL fragment (#10877) * pass appCheckToken as URL fragment * pass appcheck token as url fragments to phone provider * for test purpose only: commented async function * test if it is google cloud error * formatting the file * formatting the file * fix comments issues * remove printing function * remove unused property * Adding Unit test for passing appchecktoekn as a url fragment * add import for FIRAppCheckTokenResultInterop * Add separate file for FIRFakeAppCheck and Modify accordingly * add copyright comments for bewly created files * Add declaration for completion in FIRFakeAppCheck * add correct param decalaration * clean FIRFakeAppCheck.h * add method in FIRAppcheck.h to avoid complaints * correct copyright info * fix typo in FIRFakeAppCheck.m * Recover declarations * solve comments issues * Add changes to unit tests for changes in FIRAuthRequestConfiguration * Add changelog * Edit changelog
1 parent 01f06ac commit 43cd9c2

15 files changed

+539
-68
lines changed

FirebaseAuth.podspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ supports email and password accounts, as well as several 3rd party authenticatio
3939
source + '**/*.[mh]',
4040
'FirebaseCore/Extension/*.h',
4141
'FirebaseAuth/Interop/*.h',
42+
'FirebaseAppCheck/Interop/*.h',
4243
]
4344
s.public_header_files = source + 'Public/FirebaseAuth/*.h'
4445
s.preserve_paths = [
@@ -51,6 +52,7 @@ supports email and password accounts, as well as several 3rd party authenticatio
5152
}
5253
s.framework = 'Security'
5354
s.ios.framework = 'SafariServices'
55+
s.dependency 'FirebaseAppCheckInterop', '~> 10.0'
5456
s.dependency 'FirebaseCore', '~> 10.0'
5557
s.dependency 'GoogleUtilities/AppDelegateSwizzler', '~> 7.8'
5658
s.dependency 'GoogleUtilities/Environment', '~> 7.8'

FirebaseAuth/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#Unrealeased
2+
- [feature] Added Firebase App Check support to Firebase Auth.
3+
14
# 10.7.0
25
- [added] Added an API for developers to pass the fullName from the Sign in with Apple credential to Firebase. (#10068)
36

FirebaseAuth/Sources/Auth/FIRAuth.m

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FirebaseAuth.h"
2929
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
3030

31+
#import "FirebaseAppCheck/Interop/FIRAppCheckInterop.h"
3132
#import "FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h"
3233
#import "FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h"
3334
#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h"
@@ -462,7 +463,8 @@ - (instancetype)initWithApp:(FIRApp *)app {
462463
self = [self initWithAPIKey:app.options.APIKey
463464
appName:app.name
464465
appID:app.options.googleAppID
465-
heartbeatLogger:app.heartbeatLogger];
466+
heartbeatLogger:app.heartbeatLogger
467+
appCheck:FIR_COMPONENT(FIRAppCheckInterop, app.container)];
466468
if (self) {
467469
_app = app;
468470
#if TARGET_OS_IOS
@@ -475,20 +477,22 @@ - (instancetype)initWithApp:(FIRApp *)app {
475477
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
476478
appName:(NSString *)appName
477479
appID:(NSString *)appID {
478-
return [self initWithAPIKey:APIKey appName:appName appID:appID heartbeatLogger:nil];
480+
return [self initWithAPIKey:APIKey appName:appName appID:appID heartbeatLogger:nil appCheck:nil];
479481
}
480482

481483
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
482484
appName:(NSString *)appName
483485
appID:(NSString *)appID
484-
heartbeatLogger:(nullable id<FIRHeartbeatLoggerProtocol>)heartbeatLogger {
486+
heartbeatLogger:(nullable id<FIRHeartbeatLoggerProtocol>)heartbeatLogger
487+
appCheck:(nullable id<FIRAppCheckInterop>)appCheck {
485488
self = [super init];
486489
if (self) {
487490
_listenerHandles = [NSMutableArray array];
488491
_requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:APIKey
489492
appID:appID
490493
auth:self
491-
heartbeatLogger:heartbeatLogger];
494+
heartbeatLogger:heartbeatLogger
495+
appCheck:appCheck];
492496
_firebaseAppName = [appName copy];
493497
#if TARGET_OS_IOS
494498
_settings = [[FIRAuthSettings alloc] init];

FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthProvider.m

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIROAuthCredential.h"
2121
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
2222

23+
#import "FirebaseAppCheck/Interop/FIRAppCheckTokenResultInterop.h"
2324
#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h"
2425
#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h"
2526
#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h"
@@ -325,6 +326,8 @@ - (void)getHeadFulLiteURLWithEventID:(NSString *)eventID
325326
NSString *apiKey =
326327
strongSelf->_auth.requestConfiguration.APIKey;
327328
NSString *tenantID = strongSelf->_auth.tenantID;
329+
id<FIRAppCheckInterop> appCheck =
330+
strongSelf->_auth.requestConfiguration.appCheck;
328331
NSMutableDictionary *urlArguments = [@{
329332
@"apiKey" : apiKey,
330333
@"authType" : kAuthTypeSignInWithRedirect,
@@ -361,6 +364,7 @@ - (void)getHeadFulLiteURLWithEventID:(NSString *)eventID
361364
urlArguments[@"hl"] =
362365
strongSelf->_auth.requestConfiguration.languageCode;
363366
}
367+
364368
NSString *argumentsString = [strongSelf
365369
httpArgumentsStringForArgsDictionary:urlArguments];
366370
NSString *URLString;
@@ -374,16 +378,41 @@ - (void)getHeadFulLiteURLWithEventID:(NSString *)eventID
374378
[NSString stringWithFormat:kHeadfulLiteURLStringFormat,
375379
authDomain, argumentsString];
376380
}
377-
if (completion) {
378-
NSCharacterSet *set =
379-
[NSCharacterSet URLFragmentAllowedCharacterSet];
380-
completion(
381-
[NSURL
382-
URLWithString:
383-
[URLString
384-
stringByAddingPercentEncodingWithAllowedCharacters:
385-
set]],
386-
nil);
381+
NSCharacterSet *set =
382+
[NSCharacterSet URLFragmentAllowedCharacterSet];
383+
NSURLComponents *components = [[NSURLComponents alloc]
384+
initWithString:
385+
[URLString
386+
stringByAddingPercentEncodingWithAllowedCharacters:
387+
set]];
388+
if (appCheck) {
389+
[appCheck
390+
getTokenForcingRefresh:false
391+
completion:^(
392+
id<FIRAppCheckTokenResultInterop> _Nonnull tokenResult) {
393+
if (tokenResult.error) {
394+
FIRLogWarning(
395+
kFIRLoggerAuth, @"I-AUT000018",
396+
@"Error getting App Check token; "
397+
@"using placeholder token "
398+
@"instead. Error: %@",
399+
tokenResult.error);
400+
}
401+
NSString *appCheckTokenFragment = [@"fac="
402+
stringByAppendingString:tokenResult
403+
.token];
404+
[components
405+
setFragment:appCheckTokenFragment];
406+
407+
if (completion) {
408+
completion([components URL], nil);
409+
}
410+
}];
411+
412+
} else {
413+
if (completion) {
414+
completion([components URL], nil);
415+
}
387416
}
388417
}];
389418
}

FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthProvider.m

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRPhoneAuthProvider.h"
2323
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
2424

25+
#import "FirebaseAppCheck/Interop/FIRAppCheckTokenResultInterop.h"
2526
#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h"
2627
#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h"
2728
#import "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h"
@@ -718,6 +719,9 @@ - (void)reCAPTCHAURLWithEventID:(NSString *)eventID completion:(FIRReCAPTCHAURLC
718719
NSString *clientID = self->_auth.app.options.clientID;
719720
NSString *appID = self->_auth.app.options.googleAppID;
720721
NSString *apiKey = self->_auth.requestConfiguration.APIKey;
722+
id<FIRAppCheckInterop> appCheck =
723+
self->_auth.requestConfiguration.appCheck;
724+
721725
NSMutableArray<NSURLQueryItem *> *queryItems = [@[
722726
[NSURLQueryItem queryItemWithName:@"apiKey" value:apiKey],
723727
[NSURLQueryItem queryItemWithName:@"authType"
@@ -738,7 +742,6 @@ - (void)reCAPTCHAURLWithEventID:(NSString *)eventID completion:(FIRReCAPTCHAURLC
738742
addObject:[NSURLQueryItem queryItemWithName:@"appId"
739743
value:appID]];
740744
}
741-
742745
if (self->_auth.requestConfiguration.languageCode) {
743746
[queryItems
744747
addObject:[NSURLQueryItem
@@ -752,8 +755,32 @@ - (void)reCAPTCHAURLWithEventID:(NSString *)eventID completion:(FIRReCAPTCHAURLC
752755
[NSString stringWithFormat:kReCAPTCHAURLStringFormat,
753756
authDomain]];
754757
[components setQueryItems:queryItems];
755-
if (completion) {
756-
completion([components URL], nil);
758+
if (appCheck) {
759+
[appCheck
760+
getTokenForcingRefresh:false
761+
completion:^(
762+
id<FIRAppCheckTokenResultInterop> _Nonnull tokenResult) {
763+
if (tokenResult.error) {
764+
FIRLogWarning(
765+
kFIRLoggerAuth, @"I-AUT000018",
766+
@"Error getting App Check token; "
767+
@"using placeholder token "
768+
@"instead. Error: %@",
769+
tokenResult.error);
770+
}
771+
NSString *appCheckTokenFragment = [@"fac="
772+
stringByAppendingString:tokenResult
773+
.token];
774+
[components
775+
setFragment:appCheckTokenFragment];
776+
if (completion) {
777+
completion([components URL], nil);
778+
}
779+
}];
780+
} else {
781+
if (completion) {
782+
completion([components URL], nil);
783+
}
757784
}
758785
}];
759786
}

FirebaseAuth/Sources/Backend/FIRAuthBackend.m

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525

2626
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FirebaseAuth.h"
2727

28+
#import "FirebaseAppCheck/Interop/FIRAppCheckInterop.h"
29+
#import "FirebaseAppCheck/Interop/FIRAppCheckTokenResultInterop.h"
2830
#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h"
31+
#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h"
2932
#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h"
3033
#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h"
3134
#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h"
@@ -615,9 +618,10 @@ + (NSString *)authUserAgent {
615618
GTMFetcherStandardUserAgentString(nil)];
616619
}
617620

618-
+ (NSMutableURLRequest *)requestWithURL:(NSURL *)URL
619-
contentType:(NSString *)contentType
620-
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration {
621+
+ (void)requestWithURL:(NSURL *)URL
622+
contentType:(NSString *)contentType
623+
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
624+
completionHandler:(void (^)(NSMutableURLRequest *_Nullable))completionHandler {
621625
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
622626
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
623627
NSString *additionalFrameworkMarker =
@@ -641,7 +645,23 @@ + (NSMutableURLRequest *)requestWithURL:(NSURL *)URL
641645
if (languageCode.length) {
642646
[request setValue:languageCode forHTTPHeaderField:kFirebaseLocalHeader];
643647
}
644-
return request;
648+
if (requestConfiguration.appCheck) {
649+
[requestConfiguration.appCheck
650+
getTokenForcingRefresh:false
651+
completion:^(id<FIRAppCheckTokenResultInterop> _Nonnull tokenResult) {
652+
if (tokenResult.error) {
653+
FIRLogWarning(kFIRLoggerAuth, @"I-AUT000018",
654+
@"Error getting App Check token; using placeholder token "
655+
@"instead. Error: %@",
656+
tokenResult.error);
657+
}
658+
[request setValue:tokenResult.token
659+
forHTTPHeaderField:@"X-Firebase-AppCheck"];
660+
completionHandler(request);
661+
}];
662+
} else {
663+
completionHandler(request);
664+
}
645665
}
646666

647667
@end
@@ -675,17 +695,19 @@ - (void)asyncPostToURLWithRequestConfiguration:(FIRAuthRequestConfiguration *)re
675695
contentType:(NSString *)contentType
676696
completionHandler:
677697
(void (^)(NSData *_Nullable, NSError *_Nullable))handler {
678-
NSMutableURLRequest *request = [FIRAuthBackend requestWithURL:URL
679-
contentType:contentType
680-
requestConfiguration:requestConfiguration];
681-
GTMSessionFetcher *fetcher = [_fetcherService fetcherWithRequest:request];
682-
NSString *emulatorHostAndPort = requestConfiguration.emulatorHostAndPort;
683-
if (emulatorHostAndPort) {
684-
fetcher.allowLocalhostRequest = YES;
685-
fetcher.allowedInsecureSchemes = @[ @"http" ];
686-
}
687-
fetcher.bodyData = body;
688-
[fetcher beginFetchWithCompletionHandler:handler];
698+
[FIRAuthBackend requestWithURL:URL
699+
contentType:contentType
700+
requestConfiguration:requestConfiguration
701+
completionHandler:^(NSMutableURLRequest *request) {
702+
GTMSessionFetcher *fetcher = [self->_fetcherService fetcherWithRequest:request];
703+
NSString *emulatorHostAndPort = requestConfiguration.emulatorHostAndPort;
704+
if (emulatorHostAndPort) {
705+
fetcher.allowLocalhostRequest = YES;
706+
fetcher.allowedInsecureSchemes = @[ @"http" ];
707+
}
708+
fetcher.bodyData = body;
709+
[fetcher beginFetchWithCompletionHandler:handler];
710+
}];
689711
}
690712

691713
@end

FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#import <Foundation/Foundation.h>
1818

19+
#import "FirebaseAppCheck/Interop/FIRAppCheckInterop.h"
1920
#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h"
2021
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuth.h"
2122

@@ -47,6 +48,10 @@ NS_ASSUME_NONNULL_BEGIN
4748
@brief The heartbeat logger used to add heartbeats to the corresponding request's header.
4849
*/
4950
@property(nonatomic, copy, nullable) id<FIRHeartbeatLoggerProtocol> heartbeatLogger;
51+
/** @property appCheck
52+
@brief The appCheck is used to generate a token.
53+
*/
54+
@property(nonatomic, copy, nullable) id<FIRAppCheckInterop> appCheck;
5055

5156
/** @property LanguageCode
5257
@brief The language code used in the request.
@@ -72,37 +77,29 @@ NS_ASSUME_NONNULL_BEGIN
7277
*/
7378
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey appID:(NSString *)appID;
7479

75-
/** @fn initWithAPIKey:appID:
80+
/** @fn initWithAPIKey:appID:auth:
7681
@brief Convenience initializer.
7782
@param APIKey The API key to be used in the request.
78-
@param appID The Firebase app ID to be passed in the request header.
79-
@param auth The FIRAuth instance used in the request.
83+
@param appID The Firebase app ID to be passed in the request header.
84+
@param auth The FIRAuth instance used in the request.
8085
*/
8186
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
8287
appID:(NSString *)appID
8388
auth:(nullable FIRAuth *)auth;
8489

85-
/** @fn initWithAPIKey:appID:heartbeatLogger:
90+
/** @fn initWithAPIKey:appID:auth:heartbeatLogger:appCheck:
8691
@brief Designated initializer.
8792
@param APIKey The API key to be used in the request.
88-
@param appID The Firebase app ID to be passed in the request header.
89-
@param heartbeatLogger The heartbeat logger used to add heartbeats to the request header.
90-
*/
91-
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
92-
appID:(NSString *)appID
93-
heartbeatLogger:(nullable id<FIRHeartbeatLoggerProtocol>)heartbeatLogger;
94-
95-
/** @fn initWithAPIKey:appID:heartbeatLogger:
96-
@brief Designated initializer.
97-
@param APIKey The API key to be used in the request.
98-
@param appID The Firebase app ID to be passed in the request header.
99-
@param auth The FIRAuth instance used in the request.
93+
@param appID The Firebase app ID to be passed in the request header.
94+
@param auth The FIRAuth instance used in the request.
10095
@param heartbeatLogger The heartbeat logger used to add heartbeats to the request header.
96+
@param appCheck The appCheck interop is a library to generate app check token.
10197
*/
10298
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
10399
appID:(NSString *)appID
104100
auth:(nullable FIRAuth *)auth
105101
heartbeatLogger:(nullable id<FIRHeartbeatLoggerProtocol>)heartbeatLogger
102+
appCheck:(nullable id<FIRAppCheckInterop>)appCheck
106103
NS_DESIGNATED_INITIALIZER;
107104

108105
@end

0 commit comments

Comments
 (0)