Skip to content

Commit

Permalink
[android][ios][expo-updates] fix manifest isVerified/id values for ex…
Browse files Browse the repository at this point in the history
…po-cli-hosted and self-hosted apps (#9919)

# Why

The current logic for processing the manifest `id` and `isVerified` values for manifests coming from expo-updates breaks down in one case: expo-cli-hosted apps are getting the `id` replaced with `UNVERIFIED-IP.ADDR-app-slug` since they do not pass the check for being hosted on an Expo domain -- this is because we are not checking to see whether or not the manifest was signed & is already verified before replacing this `id` value.

# How

- Check for the `isVerified` key before replacing the `id` value.
- Since anonymous apps hosted from expo-cli are signed with a bad value (UNSIGNED) rather than actually unsigned, we need to pass this information into the manifest in order to distinguish them from anonymous, self-hosted apps (which are actually unsigned, and which we want to treat differently).

# Test Plan

Test the following cases on both platforms:
- anonymous self-hosted app (meaning a self-hosted app with the `@anonymous/` prefix in its id) should get its `id` replaced
- anonymous expo-cli-hosted app should NOT get its `id` replaced
- signed-in self-hosted app should get its `id` replaced
- signed-in self-hosted app should NOT get its `id` replaced

and `isVerified` should be `true` in all the above cases.
  • Loading branch information
esamelson committed Aug 25, 2020
1 parent 3f550d5 commit 517f1b9
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 10 deletions.
Expand Up @@ -300,7 +300,9 @@ private void launchWithNoDatabase(Context context, Exception e) {

private JSONObject processAndSaveManifest(JSONObject manifest) throws JSONException {
Uri parsedManifestUrl = Uri.parse(mManifestUrl);
if (isThirdPartyHosted(parsedManifestUrl) && !Constants.isStandaloneApp()) {
if (!manifest.has(ExponentManifest.MANIFEST_IS_VERIFIED_KEY) &&
isThirdPartyHosted(parsedManifestUrl) &&
!Constants.isStandaloneApp()) {
// Sandbox third party apps and consider them verified
// for https urls, sandboxed id is of form quinlanj.github.io/myProj-myApp
// for http urls, sandboxed id is of form UNVERIFIED-quinlanj.github.io/myProj-myApp
Expand All @@ -312,14 +314,16 @@ private JSONObject processAndSaveManifest(JSONObject manifest) throws JSONExcept
manifest.put(ExponentManifest.MANIFEST_ID_KEY, sandboxedId);
manifest.put(ExponentManifest.MANIFEST_IS_VERIFIED_KEY, true);
}
if (mExponentManifest.isAnonymousExperience(manifest)) {
// automatically verified
manifest.put(ExponentManifest.MANIFEST_IS_VERIFIED_KEY, true);
}
if (!manifest.has(ExponentManifest.MANIFEST_IS_VERIFIED_KEY)) {
manifest.put(ExponentManifest.MANIFEST_IS_VERIFIED_KEY, false);
}

if (!manifest.optBoolean(ExponentManifest.MANIFEST_IS_VERIFIED_KEY, false) &&
mExponentManifest.isAnonymousExperience(manifest)) {
// automatically verified
manifest.put(ExponentManifest.MANIFEST_IS_VERIFIED_KEY, true);
}

String bundleUrl = ExponentUrls.toHttp(manifest.getString(ExponentManifest.MANIFEST_BUNDLE_URL_KEY));

Analytics.markEvent(Analytics.TimedEvent.FINISHED_FETCHING_MANIFEST);
Expand Down
12 changes: 7 additions & 5 deletions ios/Exponent/Kernel/AppLoader/EXAppLoaderExpoUpdates.m
Expand Up @@ -378,7 +378,7 @@ - (void)_loadDevelopmentJavaScriptResource
- (NSDictionary *)_processManifest:(NSDictionary *)manifest
{
NSMutableDictionary *mutableManifest = [manifest mutableCopy];
if (![EXKernelLinkingManager isExpoHostedUrl:_httpManifestUrl] && !EXEnvironment.sharedEnvironment.isDetached){
if (!mutableManifest[@"isVerified"] && ![EXKernelLinkingManager isExpoHostedUrl:_httpManifestUrl] && !EXEnvironment.sharedEnvironment.isDetached){
// the manifest id determines the namespace/experience id an app is sandboxed with
// if manifest is hosted by third parties, we sandbox it with the hostname to avoid clobbering exp.host namespaces
// for https urls, sandboxed id is of form quinlanj.github.io/myProj-myApp
Expand All @@ -388,12 +388,14 @@ - (NSDictionary *)_processManifest:(NSDictionary *)manifest
mutableManifest[@"id"] = [NSString stringWithFormat:@"%@%@%@%@", securityPrefix, _httpManifestUrl.host, _httpManifestUrl.path ?: @"", slugSuffix];
mutableManifest[@"isVerified"] = @(YES);
}
if (EXEnvironment.sharedEnvironment.isManifestVerificationBypassed || [self _isAnonymousExperience:manifest]) {
mutableManifest[@"isVerified"] = @(YES);
}
if (mutableManifest[@"isVerified"] == nil) {
if (!mutableManifest[@"isVerified"]) {
mutableManifest[@"isVerified"] = @(NO);
}

if (![mutableManifest[@"isVerified"] boolValue] && (EXEnvironment.sharedEnvironment.isManifestVerificationBypassed || [self _isAnonymousExperience:manifest])) {
mutableManifest[@"isVerified"] = @(YES);
}

return [mutableManifest copy];
}

Expand Down
Expand Up @@ -103,6 +103,7 @@ public void onResponse(Call call, Response response) throws IOException {
if (isSigned && "UNSIGNED".equals(manifestJson.getString("signature"))) {
isSigned = false;
manifestJson = new JSONObject(manifestJson.getString("manifestString"));
manifestJson.put("isVerified", false);
}

if (isSigned) {
Expand Down
Expand Up @@ -110,6 +110,9 @@ - (void)downloadManifestFromURL:(NSURL *)url
NSError *err;
manifest = [NSJSONSerialization JSONObjectWithData:[(NSString *)innerManifestString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&err];
NSAssert(!err && manifest && [manifest isKindOfClass:[NSDictionary class]], @"manifest should be a valid JSON object");
NSMutableDictionary *mutableManifest = [manifest mutableCopy];
mutableManifest[@"isVerified"] = @(NO);
manifest = [mutableManifest copy];
}

if (isSigned) {
Expand Down

0 comments on commit 517f1b9

Please sign in to comment.