Skip to content

Commit

Permalink
[App Check] Add limitedUse parameter to GACAppAttestProvider (#11545
Browse files Browse the repository at this point in the history
)

Added a constructor to `GACAppAttestProvider` with a `limitedUse` parameter to enable short-lived tokens. This was hardcoded to `YES` in PR #11544 but the `limited_use` request parameter causes requests to fail when sending to the `v1` App Check API (requires `v1beta`) -- the param is not ignored in `v1`. The existing constructor defaults to `limited_use` being set to `NO`.

Added TODOs to remove or refactor the constructor since the public API may change significantly before the feature launches.
  • Loading branch information
andrewheard committed Jul 20, 2023
1 parent 71c60c8 commit ec898f3
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 11 deletions.
10 changes: 9 additions & 1 deletion AppCheck/Sources/AppAttestProvider/API/GACAppAttestAPIService.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,20 @@ NS_ASSUME_NONNULL_BEGIN
@interface GACAppAttestAPIService : NSObject <GACAppAttestAPIServiceProtocol>

/// Default initializer.
///
/// TODO(andrewheard): Remove or refactor the `limitedUse` parameter from this constructor when the
/// short-lived (limited-use) token feature is fully implemented.
///
/// @param APIService An instance implementing `GACAppCheckAPIServiceProtocol` to be used to send
/// network requests to the App Check backend.
/// @param resourceName The name of the resource protected by App Check; for a Firebase App this is
/// "projects/{project_id}/apps/{app_id}".
/// @param limitedUse If YES, forces a short-lived token with a 5 minute TTL.
- (instancetype)initWithAPIService:(id<GACAppCheckAPIServiceProtocol>)APIService
resourceName:(NSString *)resourceName;
resourceName:(NSString *)resourceName
limitedUse:(BOOL)limitedUse NS_DESIGNATED_INITIALIZER;

- (instancetype)init NS_UNAVAILABLE;

@end

Expand Down
17 changes: 9 additions & 8 deletions AppCheck/Sources/AppAttestProvider/API/GACAppAttestAPIService.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,28 @@
static NSString *const kJSONContentType = @"application/json";
static NSString *const kHTTPMethodPost = @"POST";

// TODO(andrewheard): Remove constant when limited-use token feature is implemented.
// Value for `kRequestFieldLimitedUse` parameter. When `limited_use` is `YES`, forces a short-lived
// token with a 5 minute TTL.
static const BOOL kLimitedUseValue = YES;

@interface GACAppAttestAPIService ()

@property(nonatomic, readonly) id<GACAppCheckAPIServiceProtocol> APIService;

@property(nonatomic, readonly) NSString *resourceName;

// TODO(andrewheard): Remove or refactor property when short-lived token feature is implemented.
// When `YES`, forces a short-lived token with a 5 minute TTL.
@property(nonatomic, readonly) BOOL limitedUse;

@end

@implementation GACAppAttestAPIService

- (instancetype)initWithAPIService:(id<GACAppCheckAPIServiceProtocol>)APIService
resourceName:(NSString *)resourceName {
resourceName:(NSString *)resourceName
limitedUse:(BOOL)limitedUse {
self = [super init];
if (self) {
_APIService = APIService;
_resourceName = [resourceName copy];
_limitedUse = limitedUse;
}
return self;
}
Expand Down Expand Up @@ -194,7 +195,7 @@ - (nullable NSData *)randomChallengeFromResponseBody:(NSData *)response error:(N
kRequestFieldArtifact : [self base64StringWithData:artifact],
kRequestFieldChallenge : [self base64StringWithData:challenge],
kRequestFieldAssertion : [self base64StringWithData:assertion],
kRequestFieldLimitedUse : @(kLimitedUseValue)
kRequestFieldLimitedUse : @(self.limitedUse)
};

return [self HTTPBodyWithJSONObject:JSONObject];
Expand All @@ -217,7 +218,7 @@ - (nullable NSData *)randomChallengeFromResponseBody:(NSData *)response error:(N
kRequestFieldKeyID : keyID,
kRequestFieldAttestation : [self base64StringWithData:attestation],
kRequestFieldChallenge : [self base64StringWithData:challenge],
kRequestFieldLimitedUse : @(kLimitedUseValue)
kRequestFieldLimitedUse : @(self.limitedUse)
};

return [self HTTPBodyWithJSONObject:JSONObject];
Expand Down
21 changes: 20 additions & 1 deletion AppCheck/Sources/AppAttestProvider/GACAppAttestProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,23 @@ - (nullable instancetype)initWithStorageID:(NSString *)storageID
keychainAccessGroup:(nullable NSString *)accessGroup
requestHooks:
(nullable NSArray<GACAppCheckAPIRequestHook> *)requestHooks {
return [self initWithStorageID:storageID
resourceName:resourceName
baseURL:baseURL
APIKey:APIKey
keychainAccessGroup:accessGroup
limitedUse:NO
requestHooks:requestHooks];
}

- (nullable instancetype)initWithStorageID:(NSString *)storageID
resourceName:(NSString *)resourceName
baseURL:(nullable NSString *)baseURL
APIKey:(nullable NSString *)APIKey
keychainAccessGroup:(nullable NSString *)accessGroup
limitedUse:(BOOL)limitedUse
requestHooks:
(nullable NSArray<GACAppCheckAPIRequestHook> *)requestHooks {
#if GAC_APP_ATTEST_SUPPORTED_TARGETS
NSURLSession *URLSession = [NSURLSession
sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
Expand All @@ -163,7 +180,9 @@ - (nullable instancetype)initWithStorageID:(NSString *)storageID
requestHooks:requestHooks];

GACAppAttestAPIService *appAttestAPIService =
[[GACAppAttestAPIService alloc] initWithAPIService:APIService resourceName:resourceName];
[[GACAppAttestAPIService alloc] initWithAPIService:APIService
resourceName:resourceName
limitedUse:limitedUse];

GACAppAttestArtifactStorage *artifactStorage =
[[GACAppAttestArtifactStorage alloc] initWithKeySuffix:storageKeySuffix
Expand Down
25 changes: 25 additions & 0 deletions AppCheck/Sources/Public/AppCheck/GACAppAttestProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,31 @@ NS_SWIFT_NAME(InternalAppAttestProvider)
requestHooks:
(nullable NSArray<GACAppCheckAPIRequestHook> *)requestHooks;

/// Initializer with support for short-lived tokens.
///
/// TODO(andrewheard): Remove or refactor this constructor when the short-lived (limited-use) token
/// feature is fully implemented.
///
/// @param storageID A unique identifier to differentiate storage keys corresponding to the same
/// `resourceName`; may be a Firebase App Name or an SDK name.
/// @param resourceName The name of the resource protected by App Check; for a Firebase App this is
/// "projects/{project_id}/apps/{app_id}".
/// @param baseURL The base URL for the App Check service; defaults to
/// `https://firebaseappcheck.googleapis.com/v1` if nil.
/// @param APIKey The Google Cloud Platform API key, if needed, or nil.
/// @param accessGroup The Keychain Access Group.
/// @param limitedUse If YES, forces a short-lived token with a 5 minute TTL.
/// @param requestHooks Hooks that will be invoked on requests through this service.
/// @return An instance of `AppAttestProvider` if App Attest is supported or `nil`.
- (nullable instancetype)initWithStorageID:(NSString *)storageID
resourceName:(NSString *)resourceName
baseURL:(nullable NSString *)baseURL
APIKey:(nullable NSString *)APIKey
keychainAccessGroup:(nullable NSString *)accessGroup
limitedUse:(BOOL)limitedUse
requestHooks:
(nullable NSArray<GACAppCheckAPIRequestHook> *)requestHooks;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ - (void)setUp {
OCMStub([self.mockAPIService baseURL]).andReturn(kBaseURL);

self.appAttestAPIService = [[GACAppAttestAPIService alloc] initWithAPIService:self.mockAPIService
resourceName:kResourceName];
resourceName:kResourceName
limitedUse:NO];
}

- (void)tearDown {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ - (void)testInitWithValidApp {
baseURL:nil
APIKey:app.options.APIKey
keychainAccessGroup:nil
limitedUse:NO
requestHooks:nil]);
}
#endif // !TARGET_OS_MACCATALYST
Expand Down

0 comments on commit ec898f3

Please sign in to comment.