30
30
31
31
NS_ASSUME_NONNULL_BEGIN
32
32
33
+ // TODO: Verify the following request fields.
34
+ static NSString *const kRequestFieldArtifact = @" artifact" ;
35
+ static NSString *const kRequestFieldAssertion = @" assertion" ;
33
36
static NSString *const kRequestFieldAttestation = @" attestation_statement" ;
34
- static NSString *const kRequestFieldKeyID = @" key_id" ;
35
37
static NSString *const kRequestFieldChallenge = @" challenge" ;
38
+ static NSString *const kRequestFieldKeyID = @" key_id" ;
39
+
40
+ static NSString *const kExchangeAppAttestAssertionEndpoint = @" exchangeAppAttestAssertion" ;
41
+ static NSString *const kExchangeAppAttestAttestationEndpoint = @" exchangeAppAttestAttestation" ;
42
+ static NSString *const kGenerateAppAttestChallengeEndpoint = @" generateAppAttestChallenge" ;
36
43
37
44
static NSString *const kContentTypeKey = @" Content-Type" ;
38
45
static NSString *const kJSONContentType = @" application/json" ;
46
+ static NSString *const kHTTPMethodPost = @" POST" ;
39
47
40
48
@interface FIRAppAttestAPIService ()
41
49
@@ -60,29 +68,34 @@ - (instancetype)initWithAPIService:(id<FIRAppCheckAPIServiceProtocol>)APIService
60
68
return self;
61
69
}
62
70
63
- - (dispatch_queue_t )backgroundQueue {
64
- return dispatch_get_global_queue (QOS_CLASS_DEFAULT, 0 );
65
- }
71
+ #pragma mark - Assertion request
72
+
73
+ - (FBLPromise<FIRAppCheckToken *> *)getAppCheckTokenWithArtifact : (NSData *)artifact
74
+ challenge : (NSData *)challenge
75
+ assertion : (NSData *)assertion {
76
+ NSURL *URL = [self URLForEndpoint: kExchangeAppAttestAssertionEndpoint ];
66
77
67
- - (FBLPromise<FIRAppCheckToken *> *)appCheckTokenWithArtifact : (NSData *)artifact
68
- challenge : (NSData *)challenge
69
- assertion : (NSData *)assertion {
70
- // TODO: Implement.
71
- return [FBLPromise resolvedWith: nil ];
78
+ return [self HTTPBodyWithArtifact: artifact challenge: challenge assertion: assertion]
79
+ .then (^FBLPromise<GULURLSessionDataResponse *> *(NSData *HTTPBody) {
80
+ return [self .APIService sendRequestWithURL: URL
81
+ HTTPMethod: kHTTPMethodPost
82
+ body: HTTPBody
83
+ additionalHeaders: @{kContentTypeKey : kJSONContentType }];
84
+ })
85
+ .then (^id _Nullable (GULURLSessionDataResponse *_Nullable response) {
86
+ return [self .APIService appCheckTokenWithAPIResponse: response];
87
+ });
72
88
}
73
89
74
90
#pragma mark - Random Challenge
75
91
76
92
- (nonnull FBLPromise<NSData *> *)getRandomChallenge {
77
- NSString *URLString =
78
- [NSString stringWithFormat: @" %@ /projects/%@ /apps/%@ :generateAppAttestChallenge" ,
79
- self .APIService.baseURL, self .projectID, self .appID];
80
- NSURL *URL = [NSURL URLWithString: URLString];
93
+ NSURL *URL = [self URLForEndpoint: kGenerateAppAttestChallengeEndpoint ];
81
94
82
95
return [FBLPromise onQueue: [self backgroundQueue ]
83
96
do: ^id _Nullable {
84
97
return [self .APIService sendRequestWithURL: URL
85
- HTTPMethod: @" POST "
98
+ HTTPMethod: kHTTPMethodPost
86
99
body: nil
87
100
additionalHeaders: nil ];
88
101
}]
@@ -139,28 +152,50 @@ - (nullable NSData *)randomChallengeFromResponseBody:(NSData *)response error:(N
139
152
- (FBLPromise<FIRAppAttestAttestationResponse *> *)attestKeyWithAttestation : (NSData *)attestation
140
153
keyID : (NSString *)keyID
141
154
challenge : (NSData *)challenge {
142
- NSString *URLString =
143
- [NSString stringWithFormat: @" %@ /projects/%@ /apps/%@ :exchangeAppAttestAttestation" ,
144
- self .APIService.baseURL, self .projectID, self .appID];
145
- NSURL *URL = [NSURL URLWithString: URLString];
155
+ NSURL *URL = [self URLForEndpoint: kExchangeAppAttestAttestationEndpoint ];
146
156
147
157
return [self HTTPBodyWithAttestation: attestation keyID: keyID challenge: challenge]
148
158
.then (^FBLPromise<GULURLSessionDataResponse *> *(NSData *HTTPBody) {
149
159
return [self .APIService sendRequestWithURL: URL
150
- HTTPMethod: @" POST "
160
+ HTTPMethod: kHTTPMethodPost
151
161
body: HTTPBody
152
162
additionalHeaders: @{kContentTypeKey : kJSONContentType }];
153
163
})
154
- .then (^id _Nullable (GULURLSessionDataResponse *_Nullable URLResponse) {
155
- NSError *error;
164
+ .thenOn (
165
+ [self backgroundQueue ], ^id _Nullable (GULURLSessionDataResponse *_Nullable URLResponse) {
166
+ NSError *error;
156
167
157
- __auto_type response =
158
- [[FIRAppAttestAttestationResponse alloc ] initWithResponseData: URLResponse.HTTPBody
159
- requestDate: [NSDate date ]
160
- error: &error];
168
+ __auto_type response =
169
+ [[FIRAppAttestAttestationResponse alloc ] initWithResponseData: URLResponse.HTTPBody
170
+ requestDate: [NSDate date ]
171
+ error: &error];
161
172
162
- return response ?: error;
163
- });
173
+ return response ?: error;
174
+ });
175
+ }
176
+
177
+ #pragma mark - Request HTTP Body
178
+
179
+ - (FBLPromise<NSData *> *)HTTPBodyWithArtifact : (NSData *)artifact
180
+ challenge : (NSData *)challenge
181
+ assertion : (NSData *)assertion {
182
+ if (artifact.length <= 0 || challenge.length <= 0 || assertion.length <= 0 ) {
183
+ FBLPromise *rejectedPromise = [FBLPromise pendingPromise ];
184
+ [rejectedPromise reject: [FIRAppCheckErrorUtil
185
+ errorWithFailureReason: @" Missing or empty request parameter." ]];
186
+ return rejectedPromise;
187
+ }
188
+
189
+ return [FBLPromise onQueue: [self backgroundQueue ]
190
+ do: ^id {
191
+ id JSONObject = @{
192
+ kRequestFieldArtifact : [self base64StringWithData: artifact],
193
+ kRequestFieldChallenge : [self base64StringWithData: challenge],
194
+ kRequestFieldAssertion : [self base64StringWithData: assertion]
195
+ };
196
+
197
+ return [self HTTPBodyWithJSONObject: JSONObject];
198
+ }];
164
199
}
165
200
166
201
- (FBLPromise<NSData *> *)HTTPBodyWithAttestation : (NSData *)attestation
@@ -173,31 +208,56 @@ - (nullable NSData *)randomChallengeFromResponseBody:(NSData *)response error:(N
173
208
return rejectedPromise;
174
209
}
175
210
176
- return [FBLPromise
177
- onQueue: [self backgroundQueue ]
178
- do: ^id _Nullable {
179
- NSError *encodingError;
180
- NSData *payloadJSON = [NSJSONSerialization dataWithJSONObject: @{
181
- kRequestFieldKeyID : keyID,
182
- kRequestFieldAttestation : [self base64StringWithData: attestation],
183
- kRequestFieldChallenge : [self base64StringWithData: challenge]
184
- }
185
- options: 0
186
- error: &encodingError];
187
-
188
- if (payloadJSON != nil ) {
189
- return payloadJSON;
190
- } else {
191
- return [FIRAppCheckErrorUtil JSONSerializationError: encodingError];
192
- }
193
- }];
211
+ return [FBLPromise onQueue: [self backgroundQueue ]
212
+ do: ^id {
213
+ id JSONObject = @{
214
+ kRequestFieldKeyID : keyID,
215
+ kRequestFieldAttestation : [self base64StringWithData: attestation],
216
+ kRequestFieldChallenge : [self base64StringWithData: challenge]
217
+ };
218
+
219
+ return [self HTTPBodyWithJSONObject: JSONObject];
220
+ }];
221
+ }
222
+
223
+ - (FBLPromise<NSData *> *)HTTPBodyWithJSONObject : (nonnull id )JSONObject {
224
+ NSError *encodingError;
225
+ NSData *payloadJSON = [NSJSONSerialization dataWithJSONObject: JSONObject
226
+ options: 0
227
+ error: &encodingError];
228
+ FBLPromise<NSData *> *HTTPBodyPromise = [FBLPromise pendingPromise ];
229
+ if (payloadJSON) {
230
+ [HTTPBodyPromise fulfill: payloadJSON];
231
+ } else {
232
+ [HTTPBodyPromise reject: [FIRAppCheckErrorUtil JSONSerializationError: encodingError]];
233
+ }
234
+ return HTTPBodyPromise;
194
235
}
195
236
237
+ #pragma mark - Helpers
238
+
196
239
- (NSString *)base64StringWithData : (NSData *)data {
197
240
// TODO: Need to encode in base64URL?
198
241
return [data base64EncodedStringWithOptions: 0 ];
199
242
}
200
243
244
+ - (NSURL *)URLForEndpoint : (NSString *)endpoint {
245
+ NSString *URL = [[self class ] URLWithBaseURL: self .APIService.baseURL
246
+ projectID: self .projectID
247
+ appID: self .appID];
248
+ return [NSURL URLWithString: [NSString stringWithFormat: @" %@ :%@ " , URL, endpoint]];
249
+ }
250
+
251
+ + (NSString *)URLWithBaseURL : (NSString *)baseURL
252
+ projectID : (NSString *)projectID
253
+ appID : (NSString *)appID {
254
+ return [NSString stringWithFormat: @" %@ /projects/%@ /apps/%@ " , baseURL, projectID, appID];
255
+ }
256
+
257
+ - (dispatch_queue_t )backgroundQueue {
258
+ return dispatch_get_global_queue (QOS_CLASS_DEFAULT, 0 );
259
+ }
260
+
201
261
@end
202
262
203
263
NS_ASSUME_NONNULL_END
0 commit comments