Jacob Jennings Jacob Jennings -4 years ago 77
iOS Question

Access App Identifier Prefix programmatically

How can I access the Bundle Seed ID/Team ID/App Identifier Prefix string programmatically? (These are all the same thing as far as I can tell).

I am using the UICKeychainStore keychain wrapper to persist data across several applications. Each of these applications has a shared keychain access group in their entitlement plists, and share the same provisioning profile. By default, the keychain services use the first access group in the plist as the access group to save data to. This looks like "AS234SDG.com.myCompany.SpecificApp" when I debug UICKeychainStore. I would like to set the access group to "AS234SDG.com.myCompany.SharedStuff", but I can't seem to locate how to get the "AS234SDG" string of the access group programmatically, and would like to avoid hard-coding it if possible.

Answer Source

You can programmatically retrieve the Bundle Seed ID by looking at the access group attribute (i.e. kSecAttrAccessGroup) of an existing KeyChain item. In the code below, I look up for an existing KeyChain entry and create one if it doesn't not exist. Once I have a KeyChain entry, I extract the access group information from it and return the access group's first component separated by "." (period) as the Bundle Seed ID.

+ (NSString *)bundleSeedID {
    NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
                           (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass,
                           @"bundleSeedID", kSecAttrAccount,
                           @"", kSecAttrService,
                           (id)kCFBooleanTrue, kSecReturnAttributes,
                           nil];
    CFDictionaryRef result = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
    if (status == errSecItemNotFound)
        status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
    if (status != errSecSuccess)
        return nil;
    NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];
    NSArray *components = [accessGroup componentsSeparatedByString:@"."];
    NSString *bundleSeedID = [[components objectEnumerator] nextObject];
    CFRelease(result);
    return bundleSeedID;
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download