Hi,
I am currently trying to develop an authorization plugin using SFAuthorizationPluginView. My objective is to display a webView to the user for authentication purposes. I have based my work on the updated NameandPassword example : https://github.com/antoinebell/NameAndPassword.
I have seen that the header for the SFAuthorizationPluginView class exists in Swift. However, I have not found any implementation examples of an authorization plugin in Swift. I have attempted to implement this on my own but am encountering difficulties displaying my embedded view within a ViewController.
Is it possible to create an authorization plug-in in Swift ?
Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello,
I saw that, in IOS 18 + FaceTime + SharePlay, we can take the control of another device (for support an user for example).
I would like to block the use of SharePlay on my application.
My application does not include Capabilites "Group Activities", but I do not know whether this is sufficient to block the use of SharePlay.
What do you think ?
Thanks in advance for your returns.
In our App, we store identity in keychain in a specific path
var keychain: SecKeychain?
let status = SecKeychainCreate(path, UInt32(password.count), password, false, nil, &keychain)
guard status == errSecSuccess else {
logger.error("Error in creating keychain: \(String(describing: SecCopyErrorMessageString(status, nil)))")
throw KeychainError.keychainCreationError
}
Then later whenever process needs it. it open keychain, import it and uses it.
status = SecPKCS12Import(identityData as CFData, [kSecImportExportPassphrase : password, kSecImportExportKeychain: keychain] as CFDictionary, &identityItems)
authlog.info("Import status: \(status)")
guard status == errSecSuccess else {
authlog.error("Error in exporting identity : \(status) \(String(describing:SecCopyErrorMessageString(status, nil)))")
throw ClientAuthError.identityFormationError
}
This worked well till sequoia beta 2.
In Sequoia beta 3 and 4, this fails to import with error -25300 : The specified item could not be found in the keychain.
one thing I noticed is import succeeds if the keychain is freshly created.
when tried to reuse existing keychain it fails in import error.
Is this a bug in beta or it any changes made in keychain level by Apple itself.
Please help with the solution
Log trace:
[ 24-07-2024 12:39:15:192 ] [INFO] Challenge delegate received [ 24-07-2024 12:39:15:192 ] [INFO] Client authentication challenge [ 2024-07-24 12:39:15 ] [INFO] retcode of "/bin/chmod -R 777 "/Library/<path>/data/agent-resource"" ::: 0 [ 24-07-2024 12:39:15:237 ] [INFO] Opening keychain... [ 24-07-2024 12:39:15:240 ] [NOTICE] Keychain open status: -25294 [ 24-07-2024 12:39:15:241 ] [ERROR] Keychain error: Optional(The specified keychain could not be found.) [ 24-07-2024 12:39:15:241 ] [INFO] Creating keychain.. [ 24-07-2024 12:39:15:448 ] [INFO] Import status: 0 [ 24-07-2024 12:39:15:448 ] [INFO] Identity: <SecIdentity 0x7ff3ec1f7df0 [0x7ff85540e9a0]> [ 24-07-2024 12:39:15:448 ] [INFO] Credential sent [ 24-07-2024 12:39:15:581 ] [INFO] Upload request completed.. [ 24-07-2024 12:39:15:583 ] [INFO] Status code: 200
[ 25-07-2024 12:24:55:300 ] [INFO] Client authentication challenge [ 25-07-2024 12:24:55:300 ] [INFO] Opening keychain... [ 25-07-2024 12:24:55:305 ] [NOTICE] Keychain open status: 0 [ 25-07-2024 12:24:55:439 ] [INFO] Import status: -25300 [ 25-07-2024 12:24:55:440 ] [ERROR] Error in exporting identity : -25300 Optional(The specified item could not be found in the keychain.) [ 25-07-2024 12:24:55:440 ] [CRITICAL] Error in getting identity: identityFormationError [ 25-07-2024 12:24:55:441 ] [ERROR] Error in obtaining identity [ 25-07-2024 12:24:55:513 ] [INFO] Download request complete... [ 25-07-2024 12:24:55:515 ] [INFO] Status code: 200
A client asked why we can't detect other apps installed on a device without an MDM profile, we explained this isn't possible due to privacy and security restrictions on iOS. A regular app cannot find other apps that are installed unless part of the same group.
The client then told us to download SpyBuster (on the App Store) which somehow is collecting a list of Bundle IDs or names of all installed apps somehow.
We were skeptical, but sure enough, the app showed us a list of apps we had installed. How is it doing this?!?! No MDM profile associated with the app. No special permissions requested. No access to anything shown in privacy & security in settings.
Is there a special entitlement we're not aware of?
Just seems like they must be using a private API call to get this info but that would of course mean it should be pulled from the App Store. We'd love to have this capability in our apps if it's legit and accepted by App Store review.
Thanks!
I am currently running the beta version of macOS Sequoia on my MacBook Pro. Are there any approved or recommended antivirus softwares I can install on this MacBook? I would greatly appreciate if anyone could point me towards some resources for this.
Thanks!
Starting with macOS Sequoia Beta, a new "Local Network Privacy” feature was introduced, which had previously been present in iOS. Unfortunately, there is little information about this topic on the Apple developer website, especially for the macOS platform. I conducted some experiments to understand the new feature, but was confused by the results. Firstly, I noticed that the type of application accessing the local network in macOS matters - bundled or command-line (CLI) applications. The TCC subsystem does not restrict access to the local network for CLI applications at all, regardless of how they are launched - as a launchd daemon with root privileges, or through a terminal with standard user privileges. At the same time, access to the local network for bundled applications is controlled by the TCC subsystem at most cases. Upon the first request, the system will display an alert to the user explaining the purpose of using the local network. Then, communication with local network devices will be allowed or restricted based on whether consent has been granted or revoked. Secondly, it's worth noting that if the bundled application supports CLI mode (launched through the terminal without a GUI), it will be able to access the local network in that mode regardless of the “Local Network Access” consent state if it has been granted at least once. However, if the same application is in GUI mode, its access to the local network will be limited by the current consent. Is this behaviour correct and likely to remain the same in future releases of macOS Sequoia? Or is there something described here that is incorrect and will be fixed in the upcoming betas?
Also, I have posted FB14581221 on this topic with the results of my experiments.
I currently do FaceID validation in my apps but it looks like Apple is offering FaceID ad the App level. Does this mean we still need to or can code for it in iOS 18 apps? Right now I've been working on migrating to iOS 18 using beta but my swift code just returns an "unknown error". From a developer perspective I can't find any examples or guidance on how handle FaceID currently in iOS 18 or going forward.
Anyone have any insights or resources.
This is the code that used to work but now under iOS 18 returns the error. Maybe the simulator and swift have not caught up but I don't think so given that it's been two beta release that I know of where this has not worked.
class biometric {
class func authenticateUser() async -> (Bool, Error?) {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let biometryType = context.biometryType
var reason = "Authenticate with \(biometryType)"
if biometryType == .faceID {
reason = "Authenticate with Face ID"
} else if biometryType == .touchID {
reason = "Authenticate with Touch ID"
}
do {
let success = try await context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason)
LogEvent.print(module: "Authentication.biometric.authenticateUser", message: "Biometric authentication. success: \"\(success)\".")
return (success, nil)
} catch let evaluationError as LAError {
LogEvent.print(module: "Authentication.biometric.authenticateUser", message: "Biometric authentication failed. evaluationError: \"\(evaluationError.localizedDescription)\"")
handleEvaluationError(evaluationError)
I do get past the .canEvaluatePolicy but fail on the .evaluatePolicy
One of my apps, Default Folder X, is an unconventional user of screen recording (and now ScreenCaptureKit). Part of its functionality is to add navigation controls to the Open and Save dialogs of other applications. It does this via the Accessibility API, and because of the limitations of that API, it sometimes has to actually pop up a menu in the target app's file dialog. To hide this from the user, it takes a screenshot of the Open or Save dialog and displays it in front of the dialog as a façade while it does its menu manipulation.
Here's an example without the use of a captured image: https://www.stclairsoft.com/blog/wp-content/uploads/2024/08/EmptyFolderBehindTheCurtain.mov
And an example with the façade: https://www.stclairsoft.com/blog/wp-content/uploads/2024/08/EmptyFolderWithScreenshot.mov
This use case prevents me from using SCContentSharingPicker, as it's not a user-driven screen capture. Moreover, Sequoia b5's weekly screen recording reminders are popping up while the user is interacting with an Open or Save dialog, severely impacting his / her workflow.
It appears that the Persistent Content Capture entitlement may prevent Sequoia from putting up the weekly warnings, though there's no documentation of the entitlement other than it being listed here: https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_persistent-content-capture.
So my questions:
Is that what the Persistent Content Capture entitlement does?
Where is the form to request this entitlement?
Without the entitlement, I can't see continuing the use of screen captures. And eliminating that will compromise the UI in my app in the way I've described above. It will also make Default Folder X unable to tailor its UI to match the Open and Save dialogs of the app it's enhancing (there's no API for it to use to get the light / dark mode of the window of another app, so it currently captures an image of the target file dialog to determine its UI mode).
Thanks - Jon
Hey guys, I have recently started with developing an extension to support PSSO, I am at a very initial stage and trying out device registration. I am trying to fetch the registration token in my MDM profile but when running in debug mode I don't see the token , and also when I see the console log I see errors like
error 14:44:00.465847+0530 AppSSODaemon Error Domain=com.apple.PlatformSSO Code=-1004 "no device configuration data to load" UserInfo={NSLocalizedDescription=no device configuration data to load}
error 14:44:00.466434+0530 AppSSOAgent Error Domain=com.apple.PlatformSSO Code=-1004 "no device configuration" UserInfo={NSLocalizedDescription=no device configuration}, user
default 14:44:00.466145+0530 AppSSODaemon -[PODaemonProcess deviceConfigurationForIdentifer:completion:] identifer = 96DBA2E4-6DB8-4937-85A8-69F7632B8717 on <private>
error 14:44:00.466773+0530 SSO extension Error Domain=com.apple.PlatformSSO Code=-1001 "failed to retrieve SecKeyProxyEndpoint for key" UserInfo={NSLocalizedDescription=failed to retrieve SecKeyProxyEndpoint for key, NSUnderlyingError=0x14b608820 {Error Domain=com.apple.PlatformSSO Code=-1001 "Failed to receive key proxy endpoint." UserInfo={NSLocalizedDescription=Failed to receive key proxy endpoint.}}}
I think due to some reason the PSSO process is not able to get the token from my configuration.
And this is how my configuration profile looks like
<?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>PayloadContent</key>
<array>
<dict>
<key>ExtensionIdentifier</key>
<string>com.test.PSSO.SSO-extension</string>
<key>PayloadDisplayName</key>
<string>ingle Sign-On Extensions</string>
<key>PayloadIdentifier</key>
<string>com.apple.extensiblesso.96DBA2E4-6DB8-4937-85A8-69F7632B8717</string>
<key>PayloadType</key>
<string>com.apple.extensiblesso</string>
<key>PayloadUUID</key>
<string>CDC67F3E-0687-4796-95B0-A61EF6F3F9A7</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TeamIdentifier</key>
<string>my_team_identifier</string>
<key>Type</key>
<string>Redirect</string>
<key>RegistrationToken</key>
<string>dummy_token_123</string>
<key>PlatformSSO</key>
<dict>
<key>AuthenticationMethod</key>
<string>Password</string>
<key>EnableAuthorization</key>
<true/>
<key>EnableCreateUserAtLogin</key>
<true/>
<key>NewUserAuthorizationMode</key>
<string>Standard</string>
<key>UseSharedDeviceKeys</key>
<true/>
<key>UserAuthorizationMode</key>
<string>Standard</string>
</dict>
<key>URLs</key>
<array>
<string>my_url</string>
</array>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>SSOE</string>
<key>PayloadIdentifier</key>
<string>com.test.psso.configuration</string>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>0DC6670F-F853-49CB-91B3-1C5ECB5D3F46</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
Hello,
I have been testing my app with iOS 18 beta and noticing an issue with the triggering of Local Network privacy prompt.
My app uses this permission to make a request to a local network address. Prior to iOS upgrade to 18 beta, the privacy prompt used to get triggered upon making the request and only after tapping on 'Allow', the subsequent requests used to succeed. If the user turned off the toggle for 'Local Network' in the app settings, then this functionality used to break as expected.
Issues observed with 18 beta:
The privacy prompt is not getting triggered upon making the request to local network and the request is succeeding. The app already seems to have this access granted but I do not see the permission toggle in the app settings.
Upon device restart, the prompt got triggered but even on disallowing the access (tapping Don't Allow), the app is able to make requests to the local network. The permission toggle appears in the app settings, but its state does not impact the app's functionality.
Has something changes in this flow? Can someone please help with what might be causing this behaviour?
We recently did an app transfer of our app from one account to a parent company's account. Because we have Sign In With Apple, we need to transfer the users. We're following this doc: https://developer.apple.com/documentation/sign_in_with_apple/bringing_new_apps_and_users_into_your_team
We have about 118,000 users, and were successful in generating the transfer identifier for the majority. We assume some users have revoked access.
When we try to call to exchange identifiers, we are successful for about 50k users, but for the remaining 68k users we are receiving 'invalid_request' with no other information
I don't understand why we would have a transfer identifier, and then receive 'invalid_request.' If it was a configuration problem I would expect that error for all users, or invalid_client. I've already gone through this doc: https://developer.apple.com/documentation/technotes/tn3107-resolving-sign-in-with-apple-response-errors
We've tried using a Node.js script, bash, Postman, with the same result. If an API call to exchange identifiers has an error, that user has an error every time. If a call is successful, it's successful every time.
Other forum posts are dead ends with no resolution. Has anybody seen this behavior and found a fix for it?
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?
Topic:
Privacy & Security
SubTopic:
General
Tags:
Mac Catalyst
Authentication Services
Passkeys in iCloud Keychain
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?
Topic:
Privacy & Security
SubTopic:
General
Tags:
Authentication Services
Passkeys in iCloud Keychain
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
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;
}
"Sign in with Apple" logo - how to make personalized for MacOS using my customized logo for the specific application?
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!
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!
Hello. I recently transferred an app from my dev account to a different one. I'm trying to follow these instructions to generate transfer IDs, and am stuck on Step 1 (creating an access token).
I keep getting {'error': 'invalid_client'}. Here's the python script I'm using to generate the access token:
TEAM_ID = "..."
KEY_ID = "..."
KEY_FILE = "key.p8"
CLIENT_ID = "com.myapp.bundle"
def get_access_token() -> str:
client_secret = get_client_secret()
print(f"client secret: {client_secret}")
url = "https://appleid.apple.com/auth/token"
req_headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {
"grant_type": "client_credentials",
"scope": "user.migration",
"client_id": CLIENT_ID,
"client_secret": client_secret,
}
response = requests.post(url, headers=req_headers, data=data)
json = response.json()
return json["access_token"]
def get_client_secret() -> str:
payload = {
"iss": TEAM_ID,
"iat": int(time.time()),
"exp": int(time.time() + 86400 * 7), # 7 days
"aud": "https://appleid.apple.com",
"sub": CLIENT_ID,
}
key = open(KEY_FILE, "r").read()
print(f"Key: {key}")
headers = {"alg": "ES256", "kid": KEY_ID}
return jwt.encode(payload, key, algorithm="ES256", headers=headers)
print(get_access_token())
The app was transferred about 2 weeks ago, so well within the 60 day period. And the script actually briefly got an access token for about 30 minutes yesterday, but is no longer working.
Any ideas? Thanks in advance.
Apple provides a way for the app developer to migrate app data from previous locations to the Mac App Store app container folder, see Migrating your app’s files to its App Sandbox container.
My question is, it seems this feature only allows us to migrate or move the existing app files into the sandbox folder, however, I'd like to "copy" these files instead of "move" them.
Instead of using the "Move" key in the plist file, I have already tried "Copy" key and it didn't work.