testAasaFile static method
Test Apple App Site Association (AASA) file
Implementation
static Future<VerificationResult> testAasaFile(
String domain,
String? teamId,
String? bundleIdentifier,
) async {
final url = Uri.parse(
'https://$domain/.well-known/apple-app-site-association',
);
try {
final response = await http.get(
url,
headers: {'Accept': 'application/json'},
);
// Check status code
if (response.statusCode != 200) {
return VerificationResult(
checkName: 'AASA File Accessibility',
status: VerificationStatus.error,
message: 'AASA file returned status ${response.statusCode}',
fixSuggestion:
'Ensure the AASA file is accessible at https://$domain/.well-known/apple-app-site-association',
details: {'statusCode': response.statusCode, 'url': url.toString()},
);
}
// Check Content-Type
final contentType = response.headers['content-type'] ?? '';
if (!contentType.contains('application/json') &&
!contentType.contains('application/pkcs7-mime')) {
return VerificationResult(
checkName: 'AASA File Content-Type',
status: VerificationStatus.warning,
message:
'AASA file Content-Type is "$contentType" (expected application/json)',
fixSuggestion:
'Ensure the server returns Content-Type: application/json for the AASA file',
details: {'contentType': contentType},
);
}
// Parse JSON
Map<String, dynamic> json;
try {
json = jsonDecode(response.body) as Map<String, dynamic>;
} catch (e) {
return VerificationResult(
checkName: 'AASA File JSON Validity',
status: VerificationStatus.error,
message: 'AASA file is not valid JSON: $e',
fixSuggestion: 'Ensure the AASA file is valid JSON',
);
}
// Check applinks structure
final applinks = json['applinks'] as Map<String, dynamic>?;
if (applinks == null) {
return VerificationResult(
checkName: 'AASA File Structure',
status: VerificationStatus.error,
message: 'AASA file missing "applinks" key',
fixSuggestion: 'Ensure the AASA file contains an "applinks" object',
);
}
final details = applinks['details'] as List<dynamic>?;
if (details == null || details.isEmpty) {
return VerificationResult(
checkName: 'AASA File Structure',
status: VerificationStatus.error,
message: 'AASA file missing "applinks.details" array',
fixSuggestion: 'Ensure the AASA file contains applinks.details array',
);
}
// Check if bundle identifier and team ID match
if (teamId != null && bundleIdentifier != null) {
final expectedAppId = '$teamId.$bundleIdentifier';
bool foundMatch = false;
for (final detail in details) {
if (detail is Map<String, dynamic>) {
final appId = detail['appID'] as String?;
if (appId == expectedAppId) {
foundMatch = true;
break;
}
}
}
if (!foundMatch) {
return VerificationResult(
checkName: 'AASA File App ID Match',
status: VerificationStatus.error,
message: 'AASA file does not contain appID "$expectedAppId"',
fixSuggestion:
'Ensure the AASA file contains an entry with appID "$expectedAppId"',
details: {'expectedAppId': expectedAppId},
);
}
}
return VerificationResult(
checkName: 'AASA File Verification',
status: VerificationStatus.success,
message: 'AASA file is accessible and valid',
details: {'url': url.toString(), 'domain': domain},
);
} catch (e) {
return VerificationResult(
checkName: 'AASA File Accessibility',
status: VerificationStatus.error,
message: 'Failed to fetch AASA file: $e',
fixSuggestion:
'Check network connectivity and ensure the domain is correctly configured',
);
}
}