Hey all, I'm encountering persistent issues while attempting to migrate users for an app transfer using Sign In with Apple. I hope to get some insights or solutions from those who might have faced similar challenges.
Context: We're transferring an app from one developer account to another. The app previously only had Sign In with Apple configured for iOS, not for web. We're now trying to set up the user migration process as part of the transfer.
Current Setup:
Old App Bundle ID: old.bundle.id24
Old Team ID: 123456789
New Team ID: 234567890
Issue:
When attempting to generate transfer identifiers for our users, we're encountering an "invalid_client" error. Here's what we've observed:
Using old_client_id = 'old.bundle.id24': Successfully generates an access token but fails at the user migration info step with an "invalid_client" error.
Using old_client_id = 'old.bundle.id' (without '24'): Fails to generate an access token with an "invalid_client" error.
Simplified script I am using
old_client_id = 'old.bundle.id24'
old_team_id = '123456789'
new_team_id = '234567890'
# JWT Payload for client secret
jwt_payload = {
'iss': old_team_id,
'iat': int(time.time()),
'exp': int(time.time()) + 15552000, # 180 days
'aud': 'https://appleid.apple.com',
'sub': f'{old_team_id}.{old_client_id}'
}
# Generate client secret
client_secret = jwt.encode(jwt_payload, private_key, algorithm='ES256', headers={'kid': key_id, 'alg': 'ES256'})
# Request access token
token_response = requests.post('https://appleid.apple.com/auth/token',
data={
'grant_type': 'client_credentials',
'scope': 'user.migration',
'client_id': old_client_id,
'client_secret': client_secret
},
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
# If successful, proceed to user migration info request
if token_response.status_code == 200:
access_token = token_response.json()['access_token']
migration_response = requests.post('https://appleid.apple.com/auth/usermigrationinfo',
data={
'sub': user_sub,
'target': new_team_id,
'client_id': old_client_id,
'client_secret': client_secret
},
headers={
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/x-www-form-urlencoded'
}
)
# This is where we get the "invalid_client" error
print(migration_response.status_code, migration_response.text)
What we've tried:
Verified all IDs (client ID, team ID, key ID) match between our code and the Apple Developer portal.
Ensured the JWT is correctly signed with the ES256 algorithm.
Checked that the client secret hasn't expired.
Verified the content type is set correctly for all requests.
Waited 72h+ since the key was first generated.
Questions:
Could the lack of web configuration in the original app be causing this issue? If so, how can we rectify this post-transfer?
Is there a specific way to handle migrations for apps that were only configured for iOS Sign In with Apple?
Are there any known issues or additional steps required when the old and new bundle IDs differ slightly (e.g., with/without '24' at the end)?
How can we further diagnose the root cause of this "invalid_client" error, given that it occurs at different stages depending on the client ID used?
Any insights, suggestions, or solutions would be greatly appreciated - I really don't know what to try at this point... Thank you in advance for your help!
Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.
Post
Replies
Boosts
Views
Activity
Hey all,
I'm encountering persistent issues while attempting to migrate users for an app transfer using Sign In with Apple. I hope to get some insights or solutions from those who might have faced similar challenges.
Context:
We're transferring an app from one developer account to another.
The app previously only had Sign In with Apple configured for iOS, not for web.
We're now trying to set up the user migration process as part of the transfer.
Current Setup:
Old App Bundle ID: old.bundle.id24
Old Team ID: 123456789
New Team ID: 234567890
Issue:
When attempting to generate transfer identifiers for our users, we're encountering an "invalid_client" error. Here's what we've observed:
Using old_client_id = 'old.bundle.id24': Successfully generates an access token but fails at the user migration info step with an "invalid_client" error.
Using old_client_id = 'old.bundle.id' (without '24'): Fails to generate an access token with an "invalid_client" error.
Simplified script I am using
old_client_id = 'old.bundle.id24'
old_team_id = '123456789'
new_team_id = '234567890'
# JWT Payload for client secret
jwt_payload = {
'iss': old_team_id,
'iat': int(time.time()),
'exp': int(time.time()) + 15552000, # 180 days
'aud': 'https://appleid.apple.com',
'sub': f'{old_team_id}.{old_client_id}'
}
# Generate client secret
client_secret = jwt.encode(jwt_payload, private_key, algorithm='ES256', headers={'kid': key_id, 'alg': 'ES256'})
# Request access token
token_response = requests.post('https://appleid.apple.com/auth/token',
data={
'grant_type': 'client_credentials',
'scope': 'user.migration',
'client_id': old_client_id,
'client_secret': client_secret
},
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
# If successful, proceed to user migration info request
if token_response.status_code == 200:
access_token = token_response.json()['access_token']
migration_response = requests.post('https://appleid.apple.com/auth/usermigrationinfo',
data={
'sub': user_sub,
'target': new_team_id,
'client_id': old_client_id,
'client_secret': client_secret
},
headers={
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/x-www-form-urlencoded'
}
)
# This is where we get the "invalid_client" error
print(migration_response.status_code, migration_response.text)
What we've tried:
Verified all IDs (client ID, team ID, key ID) match between our code and the Apple Developer portal.
Ensured the JWT is correctly signed with the ES256 algorithm.
Checked that the client secret hasn't expired.
Verified the content type is set correctly for all requests.
Waited 72h+ since the key was first generated.
Questions:
Could the lack of web configuration in the original app be causing this issue? If so, how can we rectify this post-transfer?
Is there a specific way to handle migrations for apps that were only configured for iOS Sign In with Apple?
Are there any known issues or additional steps required when the old and new bundle IDs differ slightly (e.g., with/without '24' at the end)?
How can we further diagnose the root cause of this "invalid_client" error, given that it occurs at different stages depending on the client ID used?
Any insights, suggestions, or solutions would be greatly appreciated - I really don't know what to try at this point... Thank you in advance for your help!
"Sign in with Apple" logo - how to make personalized for MacOS using my customized logo for the specific application?
Hello Apple Developer,
I have some questions regarding slow keychain access. We recently launched a product, and users with certain specific device models have reported slow performance. I'm not sure what's causing this issue and would appreciate your help in analyzing it.When using keychain groups, I didn’t specify a group, and on some devices, the queries are particularly slow. I'm unsure of the reason for this.I’m using kSecAttrTokenIDSecureEnclave, and each time I execute SecItemCopyMatching or SecItemDelete, the operation is particularly slow, taking around 2 seconds.It’s strange that when setting the default keychain group (team ID + bundle ID), the access is not slow. However, since the project has enabled the keychain group, if I set a keychain group, I cannot access the data that was stored before setting the keychain group.
Here is a snippet of my code:
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:(__bridge id)kSecAttrTokenIDSecureEnclave,(__bridge id)kSecAttrTokenID,
(__bridge id)kSecAttrKeyTypeEC,(__bridge id)kSecAttrKeyType,
@256,(__bridge id)kSecAttrKeySizeInBits,
PrivateKeyAttrs,(__bridge id)kSecPrivateKeyAttrs,nil];
privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)parameters, &error);
Here is a search of my code:
SecKeyRef privateKey = NULL;
//CFTypeRef *private = &privateKey;
NSDictionary *query = nil;
query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassKey,
(__bridge id)kSecAttrApplicationTag: serviceID,
(__bridge id)kSecReturnRef: @YES
};
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&privateKey);
if (privateKey) {
CFRelease(privateKey);
}
I am trying to understand the mechanics of how iOS/iPadOS apps work on macs with Apple Silicon.
In particular, I'd like to understand the runtime environment of these apps.
I installed one to test it on a mac. I ran codesign --entitlements on a mac, on an iOS app downloaded form the mac app store.
I was very surprised to see the sandbox entitement was NOT present.
On iOS all apps are sandboxed, so I was very surprised to see that the macOS translation was not sandbox. This seems like a significant weakening of the security.
Can anyone shed some light on that?
This is a continuation of
https://developer.apple.com/forums/thread/760861
Still a mixed Qt/C++/ObjC app, developed with Qt Creator.
The gist ist that I can call Sign in With Apple and authorise, but once the Authorisation Window/Panel goes away, the app is blocked.
PBSigninWithApple:: PBSigninWithApple()
{
myImpl = [[PBSigninWithApple alloc] initWithOwner:this];
}
- (id)initWithOwner:(PBSigninWithApple *) owner {
self = [super init];
myOwnerSIWA = owner;
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
controller.presentationContextProvider = self;
controller.delegate = self;
[controller performRequests];
return self;
}
The code example above is obviously reduced, but the real things works. I get the Sign in With Apple window and can authorise by TouchId.
The didCompleteWithAuthorization and didCompleteWithError methods also work, emitting the the idendityToken to the calling superclass works, the authorisation window goes away - but not really. The calling QT app is semi-blocked. I can close windows ny using the Escape key, but any clicking just gives the dreaded beep and nothing happens. So I assume that we didn‘t tear down everything and that the anchor or whatever still has to focus.
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(macos(10.15)) {
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
NSString *user = appleIDCredential.user;
NSData *identityToken = appleIDCredential.identityToken;
NSData *authorizationCode = appleIDCredential.authorizationCode;
emit myOwnerSIWA->accessCodeReceived(identityToken);
}
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:ASAuthorizationAppleIDProviderCredentialRevokedNotification
object:nil];
[myAnker close];
[self release];
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(ASAuthorization *)authorization API_AVAILABLE(macos(10.15)) {
emit myOwnerSIWA->accessCodeReceived(QString(""));
[[NSNotificationCenter defaultCenter]
removeObserver:self name:ASAuthorizationAppleIDProviderCredentialRevokedNotification
object:nil];
}
-(ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(macos(10.15)) {
NSRect frame = NSMakeRect(30, 30, 230, 230);
NSUInteger windowStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskFullSizeContentView;
NSWindow* window = [[[NSWindow alloc] initWithContentRect:frame
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO] autorelease];
window.minSize = CGSizeMake(200, 100);
window.releasedWhenClosed = TRUE;
myAnker = window;
return window;
}
We did an app transfer in mid-August as part of our process to incorporate the business.
We have approximately 100,000 users who have logged in with their Apple IDs, and as part of the transfer process, we followed the documentation below to transfer the account information.
https://developer.apple.com/documentation/sign_in_with_apple/bringing_new_apps_and_users_into_your_team
During the identifier exchange process, an invalid_request error occurred for approximately 10,000 users.
https://developer.apple.com/documentation/sign_in_with_apple/bringing_new_apps_and_users_into_your_team#3559300
We successfully transferred the remaining users using the same script and procedure.
Even when repeated multiple times, the error consistently occurs with the same users.
Based on this situation, we believe that the error may be caused by user-related factor.
Specifically, we would like to understand the potential causes of request errors other than the reasons listed below. The only user-related cause, ‘The user has revoked authorization for the client,’ is not relevant to this case, as it pertains to an error when issuing the transfer identifier. (not exchanging)
https://developer.apple.com/documentation/technotes/tn3107-resolving-sign-in-with-apple-response-errors#Possible-reasons-for-invalid-request-errors
Details of the request content are documented in FB14898615. Although we submitted feedback from the account after the transfer, we have not received a response for over a week, so we are reaching out here as well.
[Similar problem]
https://developer.apple.com/forums/thread/761968
I am in the process of creating a multiplatform app with a shared code base using swiftUI for iOS and mac. This app has a widget extension target for both iOS and mac and a helper app for mac only. I am trying to share data and userdefaults between the main app and the widget extension for ios, and for the mac share data between the main app, widget extension and the helper app.
I have setup an app group container to share data between all targets. However this is only working on iOS. The app group capability is not extended to macOS.
I have been researching for weeks now and all the answers I can find are for if the macOS were a different target, which would entail me having the macos group container prefixed with my team identifier.
With a multiplatform app, the main app simply won't let me prefix the group container with my team identifier. Which unfortunately xcode prevents me from doing for a multiplatform app.
I have no idea of how to solve this issue and any help will be appreciated.
The user migration API (https://appleid.apple.com/auth/usermigrationinfo) is inconsistent when we call it with the correct parameters and tokens to retrieve new user subs/emails for users made under a previous Entity before completing an Entity Transfer:
65% of our requests return with no new sub or email and we receive an {'error': 'invalid_request', 'email_verified': False} response back from the API when sending it our transfer subs.
34% of our requests succeed in getting a sub but no new private relay email from the same API with the same parameters- isn't it always supposed to return an email?
1% of our requests successfully responded with a new sub and private relay email.
We know it is not from anything in the request expiring because we regenerate the secrets, access_tokens, and transfer subs before making each request. All the other parameters are exactly the same as the successful API calls.
I can respond over email with more app/team-specific details or our request code. Thanks!
How to install root trusted certificate via SSH ?
I already read that SecTrustSettingsSetTrustSettings requires user interaction.
That mean that it requires user login and password be entered.
But is it possible to move that authetification to command line, outside UI session?
I made a sample tool that try to do this.
https://github.com/DanilKorotenko/certificateTool
Accordingly to the documentation:
https://developer.apple.com/library/archive/documentation/Security/Conceptual/authorization_concepts/02authconcepts/authconcepts.html#//apple_ref/doc/uid/TP30000995-CH205-CJBJBGAA
If the timeout attribute is missing, the credential can be used to grant the right as long as the login session lasts, unless the credential is explicitly destroyed.
When I call function AuthorizationCopyRights,
I create a shared credential (login+password).
Authorization rule com.apple.trust-settings.admin does not have timeout attribute.
security authorizationdb read com.apple.trust-settings.admin
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>class</key>
<string>rule</string>
<key>comment</key>
<string>For modifying Trust Settings in the Admin domain. Requires entitlement or admin authentication.</string>
<key>created</key>
<real>745942864.47938299</real>
<key>k-of-n</key>
<integer>1</integer>
<key>modified</key>
<real>745942864.47938299</real>
<key>rule</key>
<array>
<string>entitled</string>
<string>authenticate-admin</string>
</array>
<key>version</key>
<integer>1</integer>
</dict>
</plist>
But. If read authd log, when running this tool, in logs we can read this:
default 18:28:43.117724+0300 authd Validating shared credential trustadmin (707) for authenticate-admin (engine 396)
default 18:28:43.117733+0300 authd credential 707 expired '0.136439 > 0' (does NOT satisfy rule) (engine 396)
It says that our credential is expired.
But it should not be expired because the rule does not have timeout.
In summary, accordingly to documentation, SecTrustSettingsSetTrustSettings should not require authentification, when calling process is running as root. Because, com.apple.trust-settings.admin right rule does not have timeout, and since that root authetification on process call will create shared credential which SecTrustSettingsSetTrustSettings will use.
But in reality the behavior is different.
I found, that on some other macs, that tool works as expected. It adds trust certificate silently.
May be there is some special condition for exactly this roght? May be there is some special preferences, flags or environment variables?
Steps To Reproduce
Change this constants in code before build.
const char *userLogin = "your-adminuser";
const char *userPass = "your-password";
const char *certificateName = "your-certificateFileName";
You may use testCertificate, or create our own.
Build project.
Connect to localhost by ssh
ssh <youruser>@localhost
Go to build folder.
sudo ./certificateTool
Actual result:
The tool returns:
SecTrustSettingsSetTrustSettings failure. Error: -60007
That means that user interaction is required.
Expected result:
User interaction does not required.
Hello, I'm developing an SDK that will allow iOS devices (iOS 13+) to connect to AWS IoT Core using Native C. The endpoint requires a mutual TLS handshake to connect. I have been able to successfully import a Certificate and Private Key into the keychain and generate a SecIdentityRef that combines the cert/key pair which I believe is necessary to establish a TCP TLS nw_connection.
I've searched around and while I can find the individual pieces related to creating a TLS connection, I can't seem to find any that show how things go together.
The goal would be to use
nw_connection_create(endpoint, parameters);
to establish a TLS connection.
This is currently how I am creating the parameters for this connection.
transport_ctx->secitem_identity is where the SecIdentityRef is kept.
nw_parameters_create_secure_tcp(
// nw_parameters_configure_protocol_block_t for configure_tls
^(nw_protocol_options_t tls_options) {
sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
// Set the minimum TLS version to TLS 1.2
sec_protocol_options_set_min_tls_protocol_version(sec_options, tls_protocol_version_TLSv12);
// Set the maximum TLS version to TLS 1.3
sec_protocol_options_set_max_tls_protocol_version(sec_options, tls_protocol_version_TLSv13);
sec_protocol_options_set_local_identity(sec_options, transport_ctx->secitem_identity);
},
// nw_parameters_configure_protocol_block_t for configure_tcp
// This is also manually set with a code block but not relevant to this q.
NW_PARAMETERS_DEFAULT_CONFIGURATION);
My question is whether or not I'm even on the right track with attempting to use these functions to setup the TLS options associated with the parameters? The sec_protocol_options_set_local_identity appears to be listed under "Security legacy reference" in the apple dev docs: https://developer.apple.com/documentation/security/sec_protocol_options_set_local_identity(_:_:)?language=objc
And the surrounding documentation related to using TLS with a network connection feels sparse at best.
Follow up question is whether there is any documentation or reading material available for setting up TLS with a TCP socket connection. I'd love to not have to take up time asking these questions if there's somewhere I can just learn it.
Thanks!
In AuthorizationServices support for displayName exists in:
class ASAuthorizationSecurityKeyPublicKeyCredentialProvider func createCredentialRegistrationRequest( challenge: Data, displayName: String, name: String, userID: Data ) -> ASAuthorizationSecurityKeyPublicKeyCredentialRegistrationRequest
but is not supported in the corresponding class:
class ASAuthorizationPlatformPublicKeyCredentialProvider func createCredentialRegistrationRequest( challenge: Data, name: String, userID: Data ) -> ASAuthorizationPlatformPublicKeyCredentialRegistrationRequest
I was under the impression that this should be supported in public key credential registration?
I've created a p256 ec key in the SE, stored it in the keychain, and have a X.509 certificate for that key, now I want to create and store a SecIdentity item in the keychain on iOS. SecIdentityCreateWithCertificate is available on macOS only., so that is not an option. How am I supposed to create a SecIdentity without having that call available?
How app knows that Require Face ID is enable for them?
How app knows that they active after successfully authenticate by iOS 18 Require Face ID feature?
If any app implement any Extension(In my case Action Extension and Autofill Credential provider) then how they extension knows that they active after successfully authenticate by iOS 18 Require Face ID feature?
is there any app notification or any api to help me out?
Everytime for any website/app we found empty serviceIdentifier in func prepareOneTimeCodeCredentialList(for serviceIdentifiers: [ASCredentialServiceIdentifier])
which cause we are unable to filter item as per domain or URL.
I'm using the same code to authenticate using passkeys on iOS and macOS. On iOS (simulator, on-device, and deployed with TestFlight), I have no issues registering or authenticating with a passkey. On macOS using Catalyst, when I attempt to authenticate with a passkey (ASAuthorizationController#performRequests), I see the following error:
Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1004 "Application with identifier TEAMID.com.bundle is not associated with domain bundle.com" UserInfo={NSLocalizedFailureReason=Application with identifier TEAMID.com.bundle is not associated with domain bundle.com}
I've double-checked my apple-app-site-association file is being served from the associated domain, and I've double-checked that the Apple CDN is also returning that same association file with webcredentials for my team/bundle.
Any ideas why it would succeed in iOS environments but fail under macOS with Catalyst?
macOS popup a dialog "Allow App to find devices on local networks?" to ask Local Network permission. I would like to analyze when it popup and how it impacts my app user scenario. But this dialog only popup when Local Network privacy list not contain this app, once user pressed allow / don't allow, it won't popup again.
System Settings UI does not support removing Local Network permission, so I tried this command but not working.
tccutil reset All
There is also a post mentions that it does not work:
https://developer.apple.com/forums/thread/757949
Is there a way to remove this privacy settings? I don't want to reinstall macOS to test it.
I've tried getting LAContext and checking it, but it says it canEvaluatePolicy returns false for any biometric policy.
We use ASWebAuthenticationSession in our app to perform SAML auth on iOS devices. It works fine with Safari. However, if we config other browsers, such as Chrome, as a default browser on iOS device, ASWebAuthenticationSession still load Safari in embedded window and auth cookies is only stored in Safari. Can ASWebAuthenticationSession work with default browser on iOS similar as it works on MacOS?
Thanks,
Ying
I'm developing an SDK that will allow iOS devices (iOS 13+) to connect to AWS IoT Core using Native C. The endpoint requires a mutual TLS handshake to connect. I have been able to successfully import a Certificate and Private Key into the keychain but am unable to generate a SecIdentityRef from them for use in setting up a nw_protocol_options_t. I've looked through other forum posts and have been unable to figure out what's going on (Some are from 5+ years ago and maybe things have changed since then).
After prepping the raw data for the cert and key into expected formats I import the certificate:
const void *add_keys[] = {
kSecClass,
kSecAttrLabel,
kSecAttrSerialNumber,
kSecValueData,
kSecReturnRef };
const void *add_values[] = {
kSecClassCertificate,
label,
serial_data,
cert_data,
kCFBooleanTrue };
attributes = CFDictionaryCreate(
cf_alloc,
add_keys,
add_values,
5,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemAdd(attributes, (CFTypeRef *)out_certificate);
Next I import the private key:
const void *add_keys[] = {
kSecClass,
kSecAttrKeyClass,
kSecAttrKeyType,
kSecAttrApplicationLabel,
kSecAttrLabel,
kSecValueData,
kSecReturnRef };
const void *add_values[] = {
kSecClassKey,
kSecAttrKeyClassPrivate,
key_type,
application_label,
label,
key_data,
kCFBooleanTrue };
attributes = CFDictionaryCreate(
cf_alloc,
add_keys,
add_values,
7,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemAdd(attributes, (CFTypeRef *)out_private_key);
The full code handles duplicate items in which case attributes are updated. Following the successful import of the cert and key to the keychain, I attempt to retrieve the identity with the following:
SecIdentityRef identity = NULL;
CFDictionaryRef query = NULL;
const void *query_keys[] = {
kSecClass,
kSecReturnRef,
// kSecAttrSerialNumber,
// kSecAttrLabel
kSecMatchLimit
};
const void *query_values[] = {
kSecClassIdentity,
kCFBooleanTrue,
// cert_serial_data,
// cert_label_ref
kSecMatchLimitAll
};
query = CFDictionaryCreate(
cf_alloc,
query_keys,
query_values,
3,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
OSStatus identity_status = SecItemCopyMatching(query, (CFTypeRef *)&identity);
I have attempted using various search parameters related to the label and the serial of the certificate. Based on other forum post suggestions I have also tried expanding the search to kSecMatchLimitAll to get back ANY stored kSecClassIdentity and all variations returned OSStatus of -25300 (errSecItemNotFound). Once I am able to retrieve the SecIdentityRef, my understanding is that I can add it to the following during creation of the socket:
nw_protocol_options_t tls_options = nw_tls_create_options();
sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
sec_protocol_options_set_min_tls_protocol_version(sec_options, tls_protocol_version_TLSv12);
sec_protocol_options_set_max_tls_protocol_version(sec_options, tls_protocol_version_TLSv13);
sec_protocol_options_set_local_identity(sec_options, SecIdentityRef);
Am I missing some step that is required to create an identity from the certificate and private key? I have tested the cert/key pair and they connect properly when using the old deprecated SecItemImport and SecIdentityCreateWithCertificate (on our old macOS only implementation).
I will continue to dig through Apple documentation as well as more forum posts but I feel like I'm hitting a wall and missing something very obvious as this seems like a very common networking task. Thanks!
The provided links below are to the full code related to the work in progress iOS import functions:
Link to import function https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L735
Link to private key import: https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L561
Link to certificate import: https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L398