|
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 |
|
| 17 | +#import "AppCheckCore/Sources/Public/AppCheckCore/GACAppAttestProvider.h" |
| 18 | + |
| 19 | +#import <DeviceCheck/DeviceCheck.h> |
17 | 20 | #import <XCTest/XCTest.h> |
18 | 21 |
|
19 | 22 | #import <OCMock/OCMock.h> |
20 | 23 | #import "FBLPromise+Testing.h" |
21 | 24 |
|
22 | | -#import "AppCheckCore/Sources/Public/AppCheckCore/GACAppAttestProvider.h" |
23 | | - |
24 | 25 | #import "AppCheckCore/Sources/AppAttestProvider/API/GACAppAttestAPIService.h" |
25 | 26 | #import "AppCheckCore/Sources/AppAttestProvider/API/GACAppAttestAttestationResponse.h" |
26 | 27 | #import "AppCheckCore/Sources/AppAttestProvider/GACAppAttestService.h" |
@@ -626,6 +627,76 @@ - (void)testGetToken_WhenAttestationIsRejected_ThenAttestationIsResetAndRetriedO |
626 | 627 | [self verifyAllMocks]; |
627 | 628 | } |
628 | 629 |
|
| 630 | +- (void)testGetToken_WhenExistingKeyIsRejectedByApple_ThenAttestationIsResetAndRetriedOnce_Success { |
| 631 | + // 1. Expect GACAppAttestService.isSupported. |
| 632 | + [OCMExpect([self.mockAppAttestService isSupported]) andReturnValue:@(YES)]; |
| 633 | + |
| 634 | + // 2. Expect storage getAppAttestKeyID. |
| 635 | + NSString *existingKeyID = @"existingKeyID"; |
| 636 | + OCMExpect([self.mockStorage getAppAttestKeyID]) |
| 637 | + .andReturn([FBLPromise resolvedWith:existingKeyID]); |
| 638 | + |
| 639 | + // 3. Expect a stored artifact to be requested. |
| 640 | + __auto_type rejectedPromise = [self rejectedPromiseWithError:[NSError errorWithDomain:self.name |
| 641 | + code:NSNotFound |
| 642 | + userInfo:nil]]; |
| 643 | + OCMExpect([self.mockArtifactStorage getArtifactForKey:existingKeyID]).andReturn(rejectedPromise); |
| 644 | + |
| 645 | + // 4. Expect random challenge to be requested. |
| 646 | + OCMExpect([self.mockAPIService getRandomChallenge]) |
| 647 | + .andReturn([FBLPromise resolvedWith:self.randomChallenge]); |
| 648 | + |
| 649 | + // 5. Expect the key to be attested with the challenge. |
| 650 | + NSError *attestationError = [NSError errorWithDomain:DCErrorDomain |
| 651 | + code:DCErrorInvalidKey |
| 652 | + userInfo:nil]; |
| 653 | + id attestCompletionArg = [OCMArg invokeBlockWithArgs:[NSNull null], attestationError, nil]; |
| 654 | + OCMExpect([self.mockAppAttestService attestKey:existingKeyID |
| 655 | + clientDataHash:self.randomChallengeHash |
| 656 | + completionHandler:attestCompletionArg]); |
| 657 | + |
| 658 | + // 6. Stored attestation to be reset. |
| 659 | + [self expectAttestationReset]; |
| 660 | + |
| 661 | + // 7. Expect the App Attest key pair to be generated and attested. |
| 662 | + NSString *newKeyID = @"newKeyID"; |
| 663 | + NSData *attestationData = [[NSUUID UUID].UUIDString dataUsingEncoding:NSUTF8StringEncoding]; |
| 664 | + [self expectAppAttestKeyGeneratedAndAttestedWithKeyID:newKeyID attestationData:attestationData]; |
| 665 | + |
| 666 | + // 8. Expect exchange request to be sent. |
| 667 | + GACAppCheckToken *appCheckToken = [[GACAppCheckToken alloc] initWithToken:@"App Check Token" |
| 668 | + expirationDate:[NSDate date]]; |
| 669 | + NSData *artifactData = [@"attestation artifact" dataUsingEncoding:NSUTF8StringEncoding]; |
| 670 | + __auto_type attestKeyResponse = |
| 671 | + [[GACAppAttestAttestationResponse alloc] initWithArtifact:artifactData token:appCheckToken]; |
| 672 | + OCMExpect([self.mockAPIService attestKeyWithAttestation:attestationData |
| 673 | + keyID:newKeyID |
| 674 | + challenge:self.randomChallenge |
| 675 | + limitedUse:NO]) |
| 676 | + .andReturn([FBLPromise resolvedWith:attestKeyResponse]); |
| 677 | + |
| 678 | + // 9. Expect the artifact received from Firebase backend to be saved. |
| 679 | + OCMExpect([self.mockArtifactStorage setArtifact:artifactData forKey:newKeyID]) |
| 680 | + .andReturn([FBLPromise resolvedWith:artifactData]); |
| 681 | + |
| 682 | + // 10. Call get token. |
| 683 | + XCTestExpectation *completionExpectation = |
| 684 | + [self expectationWithDescription:@"completionExpectation"]; |
| 685 | + [self.provider |
| 686 | + getTokenWithCompletion:^(GACAppCheckToken *_Nullable token, NSError *_Nullable error) { |
| 687 | + [completionExpectation fulfill]; |
| 688 | + |
| 689 | + XCTAssertEqualObjects(token.token, appCheckToken.token); |
| 690 | + XCTAssertEqualObjects(token.expirationDate, appCheckToken.expirationDate); |
| 691 | + XCTAssertNil(error); |
| 692 | + }]; |
| 693 | + |
| 694 | + [self waitForExpectations:@[ completionExpectation ] timeout:0.5 enforceOrder:YES]; |
| 695 | + |
| 696 | + // 11. Verify mocks. |
| 697 | + [self verifyAllMocks]; |
| 698 | +} |
| 699 | + |
629 | 700 | #pragma mark - FAC token refresh (assertion) |
630 | 701 |
|
631 | 702 | - (void)testGetToken_WhenKeyRegistered_Success { |
|
0 commit comments