Repository navigation
Share extension doesn't copy keychain-access-groups entitlement from main app #90
Description
Activity
Hey @Nils-Fischer! I think you should be able to use the app group for this:
let result = await SecureStore.getItemAsync(key, { accessGroup: "group.com.example.app" });
From Apple's docs on Keychain Groups:
When you collect related apps in an application group using the App Groups Entitlement, they share access to a group container, and gain the ability to message each other in certain ways. You can use app group names as keychain access group names, without adding them to the Keychain access groups entitlement.
Reacted by YU ChenReacted by Maxi and YU Chen@SeanBarker182 Thanks for your answer! It works.
Can you show me an example how you did this? I am also struggling with it
@catseyesolutions Sure. Here is my code.
const getEncryptionKey = async () => { try { let key = await SecureStore.getItemAsync(ENCRYPTION_KEY_STORAGE_KEY, { accessGroup: APP_GROUP, }); if (!key) { key = Crypto.randomUUID(); await SecureStore.setItemAsync(ENCRYPTION_KEY_STORAGE_KEY, key, { accessGroup: APP_GROUP, }); } return key; } catch (error) { logError(error); throw error; } };
It would be nice to be able to configure custom entitlements for share extension.
Good case if app and extension use firebase auth.
Now you are forced to use app group anduseUserAccessGroupwhich is async. You should make a switch to designated access group as soon as possible in the app and it share extension. Having the switch async makes it inconvenient - you have to wrap root components in both.More over you may have other package/library dependency that has no option to select the access groups - and always using default one.
But you actually can configure default access group by entitlements
The system considers the first item in the list of access groups to be the app’s default access group. This is the access group that keychain services assumes if you don’t otherwise specify one when adding keychain items. An app group can’t ever be the default, because the app ID is always present and appears earlier in the list. However, a keychain access group can be the default, because it appears before the app ID. In particular, the first keychain access group, if any, that you specify in the corresponding capability becomes the app’s default access group. If you don’t specify any keychain access groups, then the app ID is the default.
You actually do support custom entitlements in EAS pipeline
expo-share-extension/plugin/src/withExpoConfig.ts
Lines 49 to 57 in f34cf72
entitlements: { ...shareExtensionConfig?.entitlements, "com.apple.security.application-groups": [ getAppGroup(config), ], ...(config.ios.usesAppleSignIn && { "com.apple.developer.applesignin": ["Default"], }), }, I would suggest deduplicate logic in
withShareExtensionEntitlements(if not intended to be used standalone) by reading entitlements fromconfig.extra.eas.build.experimental.ios.appExtensionsmade bywithExpoConfigexport const withShareExtensionEntitlements: ConfigPlugin = (config) => { return withEntitlementsPlist(config, (config) => { const extensionName = getShareExtensionName(config); const iosExtensions: iOSExtensionConfig[] = config.extra?.eas?.build?.experimental?.ios?.appExtensions; const shareExtensionConfig = iosExtensions?.find( (extension) => extension.targetName === extensionName ); const targetName = getShareExtensionName(config); const targetPath = path.join( config.modRequest.platformProjectRoot, targetName ); const filePath = path.join(targetPath, `${targetName}.entitlements`); const shareExtensionEntitlements : Record<string, string | string[]> = shareExtensionConfig?.entitlements ?? {}; fs.mkdirSync(path.dirname(filePath), { recursive: true }); fs.writeFileSync(filePath, plist.build(shareExtensionEntitlements)); return config; }); };
Problem
I want to use
expo-secure-storeon the main app, as well as the share app.However,
expo-share-extensionplugin currently only copiescom.apple.security.application-groupsfrom the main app's entitlements to the share extension, but doesn't copykeychain-access-groups. This prevents the share extension from accessing keychain items (e.g., viaexpo-secure-store) that are shared with the main app.Solution
I would suggest changing
plugin/src/withShareExtensionEntitlements.tsto copy thekeychain-access-groupsentitlement as well (if present):I know there is some other way to do this with
react-native-shared-group-preferences, however that storage solution is not as secure asexpo-secure-storeand this fix is very minimal.