Skip to content

Commit

Permalink
Sending authendication token for crashlytics and session
Browse files Browse the repository at this point in the history
  • Loading branch information
themiswang committed Feb 13, 2024
1 parent 2c76938 commit fb862ff
Show file tree
Hide file tree
Showing 18 changed files with 112 additions and 59 deletions.
1 change: 1 addition & 0 deletions Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
@property(nonatomic, readonly) NSOperationQueue *operationQueue;
@property(nonatomic, readonly) FIRCLSFileManager *fileManager;
@property(nonatomic, copy) NSString *fiid;
@property(nonatomic, copy) NSString *authToken;

- (void)prepareAndSubmitReport:(FIRCLSInternalReport *)report
dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken
Expand Down
7 changes: 5 additions & 2 deletions Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ - (void)prepareAndSubmitReport:(FIRCLSInternalReport *)report
// urgent mode. Since urgent mode happens when the app is in a crash loop,
// we can safely assume users aren't rotating their FIID, so this can be skipped.
if (!urgent) {
[self.installIDModel regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull newFIID) {
[self.installIDModel regenerateInstallIDIfNeededWithBlock:^(
NSString *_Nonnull newFIID, NSString *_Nonnull authToken) {
self.fiid = [newFIID copy];
self.authToken = [authToken copy];
}];
} else {
FIRCLSWarningLog(
Expand Down Expand Up @@ -186,7 +188,8 @@ - (void)uploadPackagedReportAtPath:(NSString *)path
FIRCLSReportAdapter *adapter = [[FIRCLSReportAdapter alloc] initWithPath:path
googleAppId:self.googleAppID
installIDModel:self.installIDModel
fiid:self.fiid];
fiid:self.fiid
authToken:self.authToken];

GDTCOREvent *event = [self.googleTransport eventForTransport];
event.dataObject = adapter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
* - Concern 2: Whatever the FIID is, we should send it with the Crash report so we're in sync with
* Sessions and other Firebase SDKs
*/
- (BOOL)regenerateInstallIDIfNeededWithBlock:(void (^)(NSString *fiid))block;
- (BOOL)regenerateInstallIDIfNeededWithBlock:(void (^)(NSString *fiid, NSString *authToken))block;

@end

Expand Down
33 changes: 19 additions & 14 deletions Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,30 @@ - (NSString *)generateInstallationUUID {

#pragma mark Privacy Shield

- (BOOL)regenerateInstallIDIfNeededWithBlock:(void (^)(NSString *fiid))block {
- (BOOL)regenerateInstallIDIfNeededWithBlock:(void (^)(NSString *fiid, NSString *authToken))block {
BOOL __block didRotate = false;

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

// This runs Completion async, so wait a reasonable amount of time for it to finish.
// Get a FID Authentication Token.
[self.installations
installationIDWithCompletion:^(NSString *_Nullable currentIID, NSError *_Nullable error) {
// Provide the IID to the callback. For this case we don't care
// if the FIID is null because it's the best we can do - we just want
// to send up the same FIID that is sent by other SDKs (eg. the Sessions SDK).
block(currentIID);

didRotate = [self rotateCrashlyticsInstallUUIDWithIID:currentIID error:error];

if (didRotate) {
FIRCLSInfoLog(@"Rotated Crashlytics Install UUID because Firebase Install ID changed");
}
dispatch_semaphore_signal(semaphore);
authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
NSError *_Nullable error) {
// This runs Completion async, so wait a reasonable amount of time for it to finish.
[self.installations installationIDWithCompletion:^(NSString *_Nullable currentIID,
NSError *_Nullable error) {
// Provide the IID to the callback. For this case we don't care
// if the FIID is null because it's the best we can do - we just want
// to send up the same FIID that is sent by other SDKs (eg. the Sessions SDK).
block(currentIID, tokenResult.authToken);

didRotate = [self rotateCrashlyticsInstallUUIDWithIID:currentIID error:error];

if (didRotate) {
FIRCLSInfoLog(@"Rotated Crashlytics Install UUID because Firebase Install ID changed");
}
dispatch_semaphore_signal(semaphore);
}];
}];

intptr_t result = dispatch_semaphore_wait(
Expand Down
3 changes: 2 additions & 1 deletion Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@
- (instancetype)initWithPath:(NSString *)folderPath
googleAppId:(NSString *)googleAppID
installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel
fiid:(NSString *)fiid;
fiid:(NSString *)fiid
authToken:(NSString *)authToken;
@end
6 changes: 5 additions & 1 deletion Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ @interface FIRCLSReportAdapter ()

@property(nonatomic, strong) FIRCLSInstallIdentifierModel *installIDModel;
@property(nonatomic, copy) NSString *fiid;
@property(nonatomic, copy) NSString *authToken;

@end

Expand All @@ -38,13 +39,15 @@ @implementation FIRCLSReportAdapter
- (instancetype)initWithPath:(NSString *)folderPath
googleAppId:(NSString *)googleAppID
installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel
fiid:(NSString *)fiid {
fiid:(NSString *)fiid
authToken:(NSString *)authToken {
self = [super init];
if (self) {
_folderPath = folderPath;
_googleAppID = googleAppID;
_installIDModel = installIDModel;
_fiid = [fiid copy];
_authToken = [authToken copy];

[self loadMetaDataFile];

Expand Down Expand Up @@ -156,6 +159,7 @@ - (google_crashlytics_Report)protoReport {
report.installation_uuid = FIRCLSEncodeString(self.installIDModel.installID);
report.firebase_installation_id = FIRCLSEncodeString(self.fiid);
report.app_quality_session_id = FIRCLSEncodeString(self.identity.app_quality_session_id);
report.firebase_authentication_token = FIRCLSEncodeString(self.authToken);
report.build_version = FIRCLSEncodeString(self.application.build_version);
report.display_version = FIRCLSEncodeString(self.application.display_version);
report.apple_payload = [self protoFilesPayload];
Expand Down
3 changes: 2 additions & 1 deletion Crashlytics/Protogen/nanopb/crashlytics.nanopb.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@



const pb_field_t google_crashlytics_Report_fields[10] = {
const pb_field_t google_crashlytics_Report_fields[11] = {
PB_FIELD( 1, BYTES , SINGULAR, POINTER , FIRST, google_crashlytics_Report, sdk_version, sdk_version, 0),
PB_FIELD( 3, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, gmp_app_id, sdk_version, 0),
PB_FIELD( 4, UENUM , SINGULAR, STATIC , OTHER, google_crashlytics_Report, platform, gmp_app_id, 0),
Expand All @@ -36,6 +36,7 @@ const pb_field_t google_crashlytics_Report_fields[10] = {
PB_FIELD( 10, MESSAGE , SINGULAR, STATIC , OTHER, google_crashlytics_Report, apple_payload, display_version, &google_crashlytics_FilesPayload_fields),
PB_FIELD( 16, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, firebase_installation_id, apple_payload, 0),
PB_FIELD( 17, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, app_quality_session_id, firebase_installation_id, 0),
PB_FIELD( 18, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, firebase_authentication_token, app_quality_session_id, 0),
PB_LAST_FIELD
};

Expand Down
4 changes: 3 additions & 1 deletion Crashlytics/Protogen/nanopb/crashlytics.nanopb.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef struct _google_crashlytics_Report {
google_crashlytics_FilesPayload apple_payload;
pb_bytes_array_t *firebase_installation_id;
pb_bytes_array_t *app_quality_session_id;
pb_bytes_array_t *firebase_authentication_token;
/* @@protoc_insertion_point(struct:google_crashlytics_Report) */
} google_crashlytics_Report;

Expand All @@ -84,12 +85,13 @@ typedef struct _google_crashlytics_Report {
#define google_crashlytics_Report_installation_uuid_tag 5
#define google_crashlytics_Report_firebase_installation_id_tag 16
#define google_crashlytics_Report_app_quality_session_id_tag 17
#define google_crashlytics_Report_firebase_authentication_token 18
#define google_crashlytics_Report_build_version_tag 6
#define google_crashlytics_Report_display_version_tag 7
#define google_crashlytics_Report_apple_payload_tag 10

/* Struct field encoding specification for nanopb */
extern const pb_field_t google_crashlytics_Report_fields[10];
extern const pb_field_t google_crashlytics_Report_fields[11];
extern const pb_field_t google_crashlytics_FilesPayload_fields[2];
extern const pb_field_t google_crashlytics_FilesPayload_File_fields[3];

Expand Down
9 changes: 6 additions & 3 deletions Crashlytics/UnitTests/FIRCLSContextManagerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ - (void)test_notSettingSessionID_protoHasNilSessionID {
FIRCLSReportAdapter *adapter = [[FIRCLSReportAdapter alloc] initWithPath:self.report.path
googleAppId:@"TestGoogleAppID"
installIDModel:self.installIDModel
fiid:@"TestFIID"];
fiid:@"TestFIID"
authToken:@"TestAuthToken"];

XCTAssertEqualObjects(adapter.identity.app_quality_session_id, @"");
}
Expand All @@ -92,7 +93,8 @@ - (void)test_settingSessionIDMultipleTimes_protoHasLastSessionID {
FIRCLSReportAdapter *adapter = [[FIRCLSReportAdapter alloc] initWithPath:self.report.path
googleAppId:@"TestGoogleAppID"
installIDModel:self.installIDModel
fiid:@"TestFIID"];
fiid:@"TestFIID"
authToken:@"TestAuthToken"];
NSLog(@"reportPath: %@", self.report.path);

XCTAssertEqualObjects(adapter.identity.app_quality_session_id, TestContextSessionID2);
Expand All @@ -110,7 +112,8 @@ - (void)test_settingSessionIDOutOfOrder_protoHasLastSessionID {
FIRCLSReportAdapter *adapter = [[FIRCLSReportAdapter alloc] initWithPath:self.report.path
googleAppId:@"TestGoogleAppID"
installIDModel:self.installIDModel
fiid:@"TestFIID"];
fiid:@"TestFIID"
authToken:@"TestAuthToken"];
NSLog(@"reportPath: %@", self.report.path);

XCTAssertEqualObjects(adapter.identity.app_quality_session_id, TestContextSessionID2);
Expand Down
50 changes: 30 additions & 20 deletions Crashlytics/UnitTests/FIRCLSInstallIdentifierModelTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ - (void)testCreateUUIDAndRotate {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
sleep(1);

XCTAssertFalse(didRotate);
Expand All @@ -85,8 +86,9 @@ - (void)testCreateUUIDAndErrorGettingInstanceID {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];

XCTAssertFalse(didRotate);
XCTAssertEqualObjects([_defaults objectForKey:FABInstallationUUIDKey], model.installID);
Expand Down Expand Up @@ -135,8 +137,9 @@ - (void)testIIDChanges {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertTrue(didRotate);

// Test that the UUID changed.
Expand All @@ -158,8 +161,9 @@ - (void)testIIDDoesntChange {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertFalse(didRotate);

// Test that the UUID changed.
Expand All @@ -180,8 +184,9 @@ - (void)testUUIDSetButNeverIIDNilIID {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertFalse(didRotate);

// Test that the UUID did not change. The FIID can be nil if
Expand All @@ -202,8 +207,9 @@ - (void)testUUIDSetButNeverIIDWithIID {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertFalse(didRotate);

// Test that the UUID did not change. The FIID can be nil if
Expand All @@ -226,8 +232,9 @@ - (void)testADIDWasSetButNeverIID {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertFalse(didRotate);

// Test that the UUID didn't change.
Expand All @@ -248,8 +255,9 @@ - (void)testADIDWasSetAndIIDBecomesSet {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertFalse(didRotate);

// Test that the UUID didn't change.
Expand All @@ -272,8 +280,9 @@ - (void)testADIDAndIIDWereSet {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertFalse(didRotate);

// Test that the UUID didn't change.
Expand All @@ -297,8 +306,9 @@ - (void)testADIDAndIIDWereSet2 {
[[FIRCLSInstallIdentifierModel alloc] initWithInstallations:iid];
XCTAssertNotNil(model.installID);

BOOL didRotate = [model regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid){
}];
BOOL didRotate = [model
regenerateInstallIDIfNeededWithBlock:^(NSString *_Nonnull fiid, NSString *_Nonnull authToken){
}];
XCTAssertTrue(didRotate);

// Test that the UUID change.
Expand Down
4 changes: 3 additions & 1 deletion Crashlytics/UnitTests/FIRCLSReportAdapterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ @interface FIRCLSReportAdapterTests : XCTestCase
@end

static NSString *const TestFIID = @"TEST_FIID";
static NSString *const TestAuthToken = @"TEST_AUTH_TOKEN";

@implementation FIRCLSReportAdapterTests

Expand All @@ -46,7 +47,8 @@ - (FIRCLSReportAdapter *)constructAdapterWithPath:(NSString *)path
return [[FIRCLSReportAdapter alloc] initWithPath:path
googleAppId:googleAppID
installIDModel:installIDModel
fiid:TestFIID];
fiid:TestFIID
authToken:TestAuthToken];
}

/// Attempt sending a proto report to the reporting endpoint
Expand Down
8 changes: 8 additions & 0 deletions Crashlytics/UnitTests/Mocks/FIRMockInstallations.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ @interface FIRMockInstallationsImpl : NSObject
@property(nonatomic, copy) NSString *installationID;
@property(nonatomic, strong) NSError *error;

// the init function is not public for the token result, use as a placeholder to mock the token
// completion block
@property(nonatomic, strong) FIRInstallationsAuthTokenResult *tokenResult;

@end

@implementation FIRMockInstallationsImpl

- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion {
completion(self.tokenResult, self.error);
}

- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion {
completion(self.installationID, self.error);
}
Expand Down
19 changes: 11 additions & 8 deletions FirebaseSessions/Sources/Installations+InstallationsProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@
import Foundation

@_implementationOnly import FirebaseInstallations

/// Return a tuple: (installationID, authenticationToken) for success result
protocol InstallationsProtocol {
func installationID(completion: @escaping (Result<String, Error>) -> Void)
func installationID(completion: @escaping (Result<(String, String), Error>) -> Void)
}

extension Installations: InstallationsProtocol {
func installationID(completion: @escaping (Result<String, Error>) -> Void) {
installationID { (installationID: String?, error: Error?) in
if let installationID = installationID {
completion(.success(installationID))
} else if let error = error {
completion(.failure(error))
func installationID(completion: @escaping (Result<(String, String), Error>) -> Void) {
authToken { [weak self] (authTokenResult: InstallationsAuthTokenResult?, error: Error?) in

self?.installationID { (installationID: String?, error: Error?) in
if let installationID = installationID {
completion(.success((installationID, authTokenResult?.authToken ?? "")))
} else if let error = error {
completion(.failure(error))
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions FirebaseSessions/Sources/SessionCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,13 @@ class SessionCoordinator: SessionCoordinatorProtocol {
-> Void) {
installations.installationID { result in
switch result {
case let .success(fiid):
event.setInstallationID(installationId: fiid)
case let .success(installationsInfo):
event.setInstallationID(installationId: installationsInfo.0)
event.setAuthenticationToken(authenticationToken: installationsInfo.1)
callback(.success(()))
case let .failure(error):
event.setInstallationID(installationId: "")
event.setAuthenticationToken(authenticationToken: "")
callback(.failure(FirebaseSessionsError.SessionInstallationsError(error)))
}
}
Expand Down
Loading

0 comments on commit fb862ff

Please sign in to comment.