Prioritize user privacy and data security in your app. Discuss best practices for data handling, user consent, and security measures to protect user information.

All subtopics
Posts under Privacy & Security topic

Post

Replies

Boosts

Views

Activity

Group with an existing primary App ID Change
Is it possible to change the Primary App ID set in the Group with an existing primary App ID to another Primary App ID within the same group If there is a change, whether the sub values of the token will be changed upon successful login If an app corresponding to the existing Group Primary App ID is deleted from the app store, ask whether or not other apps in the same group are affected and what effect it will have If anyone knows about the above, please let me know please
0
0
84
Apr ’25
Questions about Apple login authorization data behavior during App transfer
After the App transfer is initiated, will the replacement of the old and new certificates affect user authorization? (Based on some replies from DTS on the forum [Apple login authorization data is generated in combination with the team ID to which the App currently belongs], it is speculated that after the App transfer, during the period when the certificate configuration of the new team ID is not completed, authorization or authentication may not be performed normally, resulting in users being unable to use the Apple login function normally) During the 60-day migration period, if the user authorizes or cancels authorization and then authorizes again in the old app, will the authorized data be different? If so, will transfer_sub be included in the authorization operation?
0
0
102
Mar ’25
Importing a PEM-based RSA Private Key and its Certificate
This post is an extension to Importing Cryptographic Keys that covers one specific common case: importing a PEM-based RSA private key and its certificate to form a digital identity. If you have questions or comments, start a new thread in Privacy & Security > General. Tag your thread with Security so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Importing a PEM-based RSA Private Key and its Certificate I regularly see folks struggle to import an RSA private key and its corresponding certificate. Importing Cryptographic Keys outlines various options for importing keys, but in this post I want to cover one specific case, namely, a PEM-based RSA private key and its corresponding certificate. Together these form a digital identity, represented as a SecIdentity object. IMPORTANT If you can repackage your digital identity as a PKCS#12, please do. It’s easy to import that using SecPKCS12Import. If you can switch to an elliptic curve (EC) private key, please do. It’s generally better and Apple CryptoKit has direct support for importing an EC PEM. Assuming that’s not the case, let’s explore how to import a PEM-base RSA private key and its corresponding certificate to form a digital identity. Note The code below was built with Xcode 16.2 and tested on the iOS 18.2 simulator. It uses the helper routines from Calling Security Framework from Swift. This code assumes the data protection keychain. If you’re targeting macOS, add kSecUseDataProtectionKeychain to all the keychain calls. See TN3137 On Mac keychain APIs and implementations for more background to that. Unwrap the PEM To start, you need to get the data out of the PEM: /// Extracts the data from a PEM. /// /// As PEM files can contain a large range of data types, you must supply the /// expected prefix and suffix strings. For example, for a certificate these /// are `"-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`. /// /// - important: This assumes the simplest possible PEM format. It does not /// handle metadata at the top of the PEM or PEMs with multiple items in them. func dataFromPEM(_ pem: String, _ expectedPrefix: String, _ expectedSuffix: String) -> Data? { let lines = pem.split(separator: "\n") guard let first = lines.first, first == expectedPrefix, let last = lines.last, last == expectedSuffix else { return nil } let base64 = lines.dropFirst().dropLast().joined() guard let data = Data(base64Encoded: base64) else { return nil } return data } IMPORTANT Read the doc comment to learn about some important limitations with this code. Import a Certificate When adding a digital identity to the keychain, it’s best to import the certificate and the key separately and then add them to the keychain. That makes it easier to track down problems you encounter. To import a PEM-based certificate, extract the data from the PEM and call SecCertificateCreateWithData: /// Import a certificate in PEM format. /// /// - important: See ``dataFromPEM(_:_:_:)`` for some important limitations. func importCertificatePEM(_ pem: String) throws -> SecCertificate { guard let data = dataFromPEM(pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----"), let cert = SecCertificateCreateWithData(nil, data as NSData) else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(errSecParam), userInfo: nil) } return cert } Here’s an example that shows this in action: let benjyCertificatePEM = """ -----BEGIN CERTIFICATE----- MIIC4TCCAcmgAwIBAgIBCzANBgkqhkiG9w0BAQsFADAfMRAwDgYDVQQDDAdNb3Vz ZUNBMQswCQYDVQQGEwJHQjAeFw0xOTA5MzAxNDI0NDFaFw0yOTA5MjcxNDI0NDFa MB0xDjAMBgNVBAMMBUJlbmp5MQswCQYDVQQGEwJHQjCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAOQe5ai68FQhTVIgpsDK+UOPIrgKzqJcW+wwLnJRp6GV V9EmifJq7wjrXeqmP1XgcNtu7cVhDx+/ONKl/8hscak54HTQrgwE6mK628RThld9 BmZoOjaWWCkoU5bH7ZIYgrKF1tAO5uTAmVJB9v7DQQvKERwjQ10ZbFOW6v8j2gDL esZQbFIC7f/viDXLsPq8dUZuyyb9BXrpEJpXpFDi/wzCV3C1wmtOUrU27xz4gBzi 3o9O6U4QmaF91xxaTk0Ot+/RLI70mR7TYa+u6q7UW/KK9q1+8LeTVs1x24VA5csx HCAQf+xvMoKlocmUxCDBYkTFkmtyhmGRN52XucHgu0kCAwEAAaMqMCgwDgYDVR0P AQH/BAQDAgWgMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUA A4IBAQAyrArH7+IyHTyEOrv/kZr3s3h4HWczSVeiO9qWD03/fVew84J524DiSBK4 mtAy3V/hqXrzrQEbsfyT7ZhQ6EqB/W0flpVYbku10cSVgoeSfjgBJLqgJRZKFonv OQPjTf9HEDo5A1bQdnUF1y6SwdFaY16lH9mZ5B8AI57mduSg90c6Ao1GvtbAciNk W8y4OTQp4drh18hpHegrgTIbuoWwgy8V4MX6W39XhkCUNhrQUUJk3mEfbC/yqfIG YNds0NRI3QCTJCUbuXvDrLEn4iqRfbzq5cbulQBxBCUtLZFFjKE4M42fJh6D6oRR yZSx4Ac3c+xYqTCjf0UdcUGxaxF/ -----END CERTIFICATE----- """ print(try? importCertificatePEM(benjyCertificatePEM)) If you run this it prints: Optional(<cert(0x11e304c10) s: Benjy i: MouseCA>) Import a Private Key To import a PEM-base RSA private key, extract the data from the PEM and call SecKeyCreateWithData: /// Import an 2048-bit RSA private key in PEM format. /// /// Don’t use this code if: /// /// * If you can switch to an EC key. EC keys are generally better and, for /// this specific case, there’s support for importing them in Apple CryptoKit. /// /// * You can switch to using a PKCS#12. In that case, use the system’s /// `SecPKCS12Import` routine instead. /// /// - important: See ``dataFromPEM(_:_:_:)`` for some important limitations. func importRSA2048PrivateKeyPEM(_ pem: String) throws -> SecKey { // Most private key PEMs are in PKCS#8 format. There’s no way to import // that directly. Instead you need to strip the header to get to the // `RSAPrivateKey` data structure encapsulated within the PKCS#8. Doing that // in the general case is hard. In the specific case of an 2048-bit RSA // key, the following hack works. let rsaPrefix: [UInt8] = [ 0x30, 0x82, 0x04, 0xBE, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 0xA8, ] guard let pkcs8 = dataFromPEM(pem, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----"), pkcs8.starts(with: rsaPrefix) else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(errSecParam), userInfo: nil) } let rsaPrivateKey = pkcs8.dropFirst(rsaPrefix.count) return try secCall { SecKeyCreateWithData(rsaPrivateKey as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPrivate, ] as NSDictionary, $0) } } IMPORTANT This code only works with 2048-bit RSA private keys. The comments explain more about that limitation. Here’s an example that shows this in action: let benjyPrivateKeyPEM = """ -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkHuWouvBUIU1S IKbAyvlDjyK4Cs6iXFvsMC5yUaehlVfRJonyau8I613qpj9V4HDbbu3FYQ8fvzjS pf/IbHGpOeB00K4MBOpiutvEU4ZXfQZmaDo2llgpKFOWx+2SGIKyhdbQDubkwJlS Qfb+w0ELyhEcI0NdGWxTlur/I9oAy3rGUGxSAu3/74g1y7D6vHVGbssm/QV66RCa V6RQ4v8MwldwtcJrTlK1Nu8c+IAc4t6PTulOEJmhfdccWk5NDrfv0SyO9Jke02Gv ruqu1FvyivatfvC3k1bNcduFQOXLMRwgEH/sbzKCpaHJlMQgwWJExZJrcoZhkTed l7nB4LtJAgMBAAECggEBAKOPF6ED776SZgrliEog/dmXrhABB6jXybytyw+CRkuP dXhrRmr+isZ9Y0gTzMN4+dILVgW4EozzoP0/sgZ04oWwDqQS30eU2qzRRzMbo+3k oYsZXeu3nhxcYppwXIDsfAEd/ygMFzaadRPKYhrFykR2rA/dpLYCvW2tfm5SuULp RxnKykFlVi8yVT64AovVm0XGOy/QTO5BBbUdftvZY9QCjGn/IEL8QFEz0rxZsb2L s0HgVMUcB1My38RksZQRKLMWCtqLqWnez3oCnPka+dxFQj5RU//vNtRoVh1ExbmW txHz48v00AKQvaudC4ujIspZlY8+UPdYQT0TNjhsfoUCgYEA+7yEvyCgRtYwUNm6 jHTg67LoSldHwENOry63qGZp3rCkWBkPXle7ulgRtuw+e11g4MoMMAgkIGyIGB/Z 6YvnQGmJCTMw+HHIyw3k/OvL1iz4DM+QlxDuD79Zu2j2UIL4maDG0ZDskiJujVAf sFOy4r36TvYedmd7qgh9pgpsFl8CgYEA5/v8PZDs2I1wSDGllGfTr6aeQcxvw98I p8l/8EV/lYpdKQMFndeFZI+dnJCcTeBbeXMmPNTAdL5gOTwDReXamIAdr93k7/x6 iKMHzBrpQZUMEhepSd8zdR1+vLvyszvUU6lvNXcfjwbu7gJQkwbA6kSoXRN+C1Cv i5/w66t0f1cCgYBt02FWwTUrsmaB33uzq4o1SmhthoaXKsY5R3h4z7WAojAQ/13l GwGb2rBfzdG0oJiTeZK3odWhD7iQTdUUPyU0xNY0XVEQExQ3AmjUr0rOte/CJww9 2/UAicrsKG7N0VYEMFCNPVz4pGz22e35T4rLwXZi3J2NqrgZBntK5WEioQKBgEyx L4ii+sn0qGQVlankUUVGjhcuoNxeRZxCrzsdnrovTfEbAKZX88908yQpYqMUQul5 ufBuXVm6/lCtmF9pR8UWxbm4X9E+5Lt7Oj6tvuNhhOYOUHcNhRN4tsdqUygR5XXr E8rXIOXF4wNoXH7ewrQwEoECyq6u8/ny3FDtE8xtAoGBALNFxRGikbQMXhUXj7FA lLwWlNydCxCc7/YwlHfmekDaJRv59+z7SWAR15azhbjqS9oXWJUQ9uvpKF75opE7 MT0GzblkKAYu/3uhTENCjQg+9RFfu5w37E5RTWHD2hANV0YqXUlmH3d+f5uO0xN7 7bpqwYuYzSv1hBfU/yprDco6 -----END PRIVATE KEY----- """ print(try? importRSA2048PrivateKeyPEM(benjyPrivateKeyPEM)) If you run this it prints: Optional(<SecKeyRef algorithm id: 1, key type: RSAPrivateKey, version: 4, 2048 bits (block size: 256), addr: 0x600000c5ce50>) Form a Digital Identity There are two common ways to form a digital identity: SecPKCSImport SecItemCopyMatching SecPKCSImport is the most flexible because it gives you an in-memory digital identity. You can then choose to add it to the keychain or not. However, it requires a PKCS#12 as input. If you’re starting out with separate private key and certificate PEMs, you have to use SecItemCopyMatching. Note macOS also has SecIdentityCreateWithCertificate, but it has some seriously limitations. First, it’s only available on macOS. Second, it requires the key to be in the keychain. If you’re going to add the key to the keychain anyway, you might as well use SecItemCopyMatching. To form a digital identity from a separate private key and certificate: Add the certificate to the keychain. Add the private key to the keychain. Call SecItemCopyMatching to get back a digital identity. Here’s an example of that in action: /// Imports a digital identity composed of separate certificate and private key PEMs. /// /// - important: See ``dataFromPEM(_:_:_:)`` for some important limitations. /// See ``importRSA2048PrivateKeyPEM(_:)`` for alternative strategies that are /// much easier to deploy. func addRSA2048DigitalIdentityPEMToKeychain(certificate: String, privateKey: String) throws -> SecIdentity { // First import the certificate and private key. This has the advantage in // that it triggers an early failure if the data is in the wrong format. let certificate = try importCertificatePEM(certificate) let privateKey = try importRSA2048PrivateKeyPEM(privateKey) // Check that the private key matches the public key in the certificate. If // not, someone has given you bogus credentials. let certificatePublicKey = try secCall { SecCertificateCopyKey(certificate) } let publicKey = try secCall { SecKeyCopyPublicKey(privateKey) } guard CFEqual(certificatePublicKey, publicKey) else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(errSecPublicKeyInconsistent)) } // Add the certificate first. If that fails — and the most likely error is // `errSecDuplicateItem` — we want to stop immediately. try secCall { SecItemAdd([ kSecValueRef: certificate, ] as NSDictionary, nil) } // The add the private key. do { try secCall { SecItemAdd([ kSecValueRef: privateKey, ] as NSDictionary, nil) } } catch let error as NSError { // We ignore a `errSecDuplicateItem` error when adding the key. It’s // possible to have multiple digital identities that share the same key, // so if you try to add the key and it’s already in the keychain then // that’s fine. guard error.domain == NSOSStatusErrorDomain, error.code == errSecDuplicateItem else { throw error } } // Finally, search for the resulting identity. // // I originally tried querying for the identity based on the certificate’s // attributes — the ones that contribute to uniqueness, namely // `kSecAttrCertificateType`, `kSecAttrIssuer`, and `kSecAttrSerialNumber` — // but that failed for reasons I don't fully understand (r. 144152660). So // now I get all digital identities and find the one with our certificate. let identities = try secCall { SecItemCopyMatching([ kSecClass: kSecClassIdentity, kSecMatchLimit: kSecMatchLimitAll, kSecReturnRef: true, ] as NSDictionary, $0) } as! [SecIdentity] let identityQ = try identities.first { i in try secCall { SecIdentityCopyCertificate(i, $0) } == certificate } return try secCall(Int(errSecItemNotFound)) { identityQ } } IMPORTANT This code is quite subtle. Read the comments for an explanation as to why it works the way it does. Further reading For more information about the APIs and techniques used above, see: Importing Cryptographic Keys On Cryptographic Keys Formats SecItem: Fundamentals SecItem: Pitfalls and Best Practices Calling Security Framework from Swift TN3137 On Mac keychain APIs and implementations Finally, for links to documentation and other resources, see Security Resources. Revision History 2025-02-13 Added code to check for mismatched private key and certificate. 2025-02-04 First posted.
0
0
562
Feb ’25
Questions about Server-to-Server Notifications for “Sign in with Apple” (Starting Jan 1, 2026)
I received Apple’s recent notice about the new requirement to provide a server-to-server notification endpoint when registering or updating a Services ID that uses Sign in with Apple. (Official notice: https://developer.apple.com/news/?id=j9zukcr6 ) We already use Sign in with Apple on our website and app, but only as a login method for pre-registered users, not as a way to create new accounts. That means users already exist in our system, and Apple login is used only for authentication convenience (similar to linking a social account). I have some questions about how to properly implement the required server-to-server notifications in this case: 1. email-enabled / email-disabled: We don’t use or store the email address provided by Apple. Are we still required to handle these events, or can we safely ignore them if the email is not used in our system? 2. consent-revoked: We don’t store Apple access or refresh tokens, we use them only during login and discard them immediately. In this case, do we still need to handle token revocation, or can we simply unlink the Apple login from the user account when receiving this notification? 3. account-delete: If a user deletes their Apple account, we can unlink the Apple login and remove related Apple data, but we cannot delete the user’s primary account in our system (since the account exists independently). Is this acceptable under Apple’s requirements as well? We want to make sure our implementation aligns with Apple’s policy and privacy requirements, while maintaining consistency with our existing account management system. If anyone from Apple or other developers who implemented similar logic could provide guidance or share examples, it would be greatly appreciated. Thank you!
0
0
80
Oct ’25
Receiving Apple SignIn profile info again after deleting account
We are currently trying to fix a bug when using SignIn with Apple. It appears that on some occasions we are not receiving a user's profile info (name, email) when a new account is created. After doing some investigation we believe this bug is due to the same Apple login being used as an already deleted account. ASF only appears to send profile info the very first time an Apple login is used. If that account is deleted and another is created with the same apple login we won't receive the profile info. As a result we are not in compliance with Apple's guidelines requiring that we use the provided profile info with Apple SigIn, and need to prompt users to enter it again. Is there a process in place to properly "clear" a user after their account is deleted in our system, so that the next time a user creates an account with the same Apple login, we receive their profile info again?
0
5
407
Mar ’25
Update ASCredentialIdentityStore for new Autofill PassKey registration
I have an Autofill Passkey Provider working for Safari and Chrome via WebAuthn protocol. Unfortunately, Chrome will not offer my extension as a logon credential provider unless I add the credential to the ASCredentialIdentityStore. I wonder what is the best way to access the ASCredentialIdentityStore from an AutoFill extension? I understand I cannot access it directly from the extension context, so what is the best way to trigger my container app to run, based on a new WebAuthn registration? The best I can think of so far is for the www site to provide an App Link to launch my container app as part of the registration ceremony. Safari will offer my extension even without adding it to the ASCredentialIdentityStore, so I guess I should file a request with Chrome to work this way too, given difficulty of syncing ASCredentialIdentityStore with WebAuthn registration.
0
0
52
Oct ’25
Is there anyway to deny user copy file content
I'm developing a file access control system. In order to protect the file content copied out, I'm finding a way to deny user copy file content to other files. I know there are data transmission between the copied application and pboard service by XPC. But I don't know how to interrupt the data transmission. Or I can do something to stop the copied data send to the Clipboard. So is there any way to prevent the contents of a file being copied?
0
0
500
Dec ’24
Handling ITMS-91061: Missing privacy manifest
An ITMS-91061: Missing privacy manifest rejection email looks as follows: ITMS-91061: Missing privacy manifest- Your app includes "<path/to/SDK>", which includes , an SDK that was identified in the documentation as a privacy-impacting third-party SDK. Starting February 12, 2025, if a new app includes a privacy-impacting SDK, or an app update adds a new privacy-impacting SDK, the SDK must include a privacy manifest file. Please contact the provider of the SDK that includes this file to get an updated SDK version with a privacy manifest. For more details about this policy, including a list of SDKs that are required to include signatures and manifests, visit: https://developer.apple.com/support/third-party-SDK-requirements. Glossary ITMS-91061: Missing privacy manifest: An email that includes the name and path of privacy-impacting SDK(s) with no privacy manifest files in your app bundle. For more information, see https://developer.apple.com/support/third-party-SDK-requirements. : The specified privacy-impacting SDK that doesn't include a privacy manifest file. If you are the developer of the rejected app, gather the name of the SDK from the email you received from Apple, then contact the SDK's provider for an updated version that includes a valid privacy manifest. After receiving an updated version of the SDK, verify the SDK includes a valid privacy manifest file at the expected location. For more information, see Adding a privacy manifest to your app or third-party SDK. If your app includes a privacy manifest file, make sure the file only describes the privacy practices of your app. Do not add the privacy practices of the SDK to your app's privacy manifest. If the email lists multiple SDKs, repeat the above process for all of them. If you are the developer of an SDK listed in the email, publish an updated version of your SDK that includes a privacy manifest file with valid keys and values. Every privacy-impacting SDK must contain a privacy manifest file that only describes its privacy practices. To learn how to add a valid privacy manifest to your SDK, see the Additional resources section below. Additional resources Privacy manifest files Describing data use in privacy manifests Describing use of required reason API Adding a privacy manifest to your app or third-party SDK TN3182: Adding privacy tracking keys to your privacy manifest TN3183: Adding required reason API entries to your privacy manifest TN3184: Adding data collection details to your privacy manifest TN3181: Debugging an invalid privacy manifest
0
0
5.8k
Mar ’25
Why doesn't FinanceKit return transaction location?
Pretty much the headline. the func transactionHistory() needs to return the transaction location. This seems so rudimentary, yet it is missing from the docs. Unless I'm missing something, please add this feature or point me in the right direction. Alternatively, is there a way for my app to get notified of the transaction immediately as it happens? I have to get transactions historically which leaves me with no way to determine where they happened in the past.
0
0
268
Jan ’25
Why can't I remove my app from AppleID?
Hello everybody, in my React Native-Expo-Firebase app, I am trying to integrate Sign in with Apple, along with the related token revocation at user deletion. I did succeed in integrating the login, and the app correctly appears in the Apple Id list (the list of apps currently logged with Apple ID). The problem is that, if I select the app and press "Interrupt Apple login usage for this app", the app simply stays there, nothing happens. If I do the same with another app, this works fine. Either if I do this via my iPhone's settings, or via https://account.apple.com/account/manage -> Sign in with Apple, I get the same result, the app cannot be removed. I hope I managed to explain my situation clearly, I'd be happy to provide more info if necessary. Thank you in advance.
0
0
200
Oct ’25
Gathering required information for troubleshooting Private Email Relay with Sign in with Apple
Hi, Before I begin my investigation, I want to explain our code-level support process for issues related to Sign in with Apple—as the issue you’re reporting may be the result of any of the following: An error in your app or web service request. A configuration issue in your Developer Account. An internal issue in the operation system or Apple ID servers. To ensure the issue is not caused by an error within your Private Email Replay configuration, please review Configuring your environment for Sign in with Apple to learn more about registering your email sources and authenticated domains. To prevent sending sensitive message details in plain text, you should create a report in Feedback Assistant to share the details requested below. Additionally, if I determine the error is caused by an internal issue in the operating system or Apple ID servers, the appropriate engineering teams have access to the same information and can communicate with you directly for more information, if needed. Please follow the instructions below to submit your feedback. Gathering required information for troubleshooting Private Email Relay with Sign in with Apple For issues occurring with your email delivery, ensure your feedback contains the following information: the primary App ID and Services ID the user’s Apple ID and/or email address the email message headers the Private Email Relay Service or Hide My Email message delivery failure, and SMTP error codes Submitting your feedback Before you submit to Feedback Assistant, please confirm the requested information above is included in your feedback. Failure to provide the requested information will only delay my investigation into the reported issue within your Sign in with Apple client. After your submission to Feedback Assistant is complete, please respond in your existing Developer Forums post with the Feedback ID. Once received, I can begin my investigation and determine if this issue is caused by an error within your client, a configuration issue within your developer account, or an underlying system bug. Cheers, Paris X Pinkney |  WWDR | DTS Engineer
0
0
1.2k
Sep ’25
TouchID on the Mac when FaceID is called on iOS when using iPhone Mirroring?
When using Apple's Journal app through iPhone Mirroring, the user is allowed to authenticate via TouchID on the Mac instead of requiring you to unlock your phone, authenticate and then re-lock it to access it again in iPhone Mirroring. Any other app that's using a call to authenticate via FaceID can't do this under iPhone Mirroring. Is there a new API call for this, or is it still a private API for Apple only?
0
0
510
Dec ’24
Persistent "invalid_client" error on backend token exchange (Sign In with Apple)
Hello Apple Developer Community and Support, Our team is encountering a critical and persistent issue with our backend integration of Sign In with Apple, and we are hoping for some insights or assistance. Problem: We consistently receive an "invalid_client" error (HTTP 400 status) when our backend service attempts to exchange the authorization code for tokens at Apple's https://appleid.apple.com/auth/token endpoint. The error message from Apple's response is simply {"error":"invalid_client"}. Our Setup: Client Application: An iOS native application. Backend Service: A Go backend responsible for server-to-server token exchange and user management. Sign In with Apple Flow: The iOS app initiates the Sign In with Apple flow, obtains an authorization code, and then passes this code to our backend for token exchange. Extensive Troubleshooting Performed (No Success): We have meticulously followed all official Apple documentation (including TN3107: Resolving Sign In with Apple Response Errors) and industry best practices. Here's a summary of our verification steps, all of which currently show correct configurations and parameters: Backend client_secret JWT Construction: We generate a client_secret JWT as required for server-to-server communication. We've confirmed the claims in the generated JWT are correct: iss (Issuer): Our Team ID (e.g., XXXXXXXXXX). sub (Subject): Our Service ID (e.g., com.example.service.backendauth). aud (Audience): https://appleid.apple.com. kid (Key ID): The Key ID associated with our .p8 private key (e.g., YYYYYYYYYY). We have performed rigorous verification of the .p8 private key content itself, ensuring no corruption, extra characters, or formatting issues in the environment variable. Our backend logs confirm it's parsing the correct PEM content. Token Exchange Request Parameters: The client_id parameter sent in the POST request to /auth/token is correctly set to our App Bundle ID (e.g., com.example.app.ios), as this is the identifier for which the code was originally issued. The redirect_uri parameter sent in the POST request to /auth/token is precisely matched to a registered "Return URL" in our Apple Developer Portal (e.g., https://api.example.com:port/api/auth/callback?provider=apple). Apple Developer Portal Configuration (Meticulously Verified): App ID: Enabled for "Sign In with Apple". Service ID: Enabled for "Sign In with Apple". Its "Primary App ID" is correctly linked to our App Bundle ID (e.g., com.example.app.ios). Its "Return URLs" exactly match our backend's redirect_uri (e.g., https://api.example.com:port/api/auth/callback?provider=apple). Key: Our .p8 key has "Sign In with Apple" enabled. Crucially, in its configuration panel, the "Primary App ID" is correctly linked to our App Bundle ID (e.g., com.example.app.ios). We've ensured this key is specifically created for "Sign In with Apple" and not other services like APNs. We have performed multiple full revocations and meticulous re-creations of the App ID, Service ID, and Key in the Apple Developer Portal, ensuring correct linkages and using new identifiers to bypass any potential caching issues. Network & System Health Checks: Network connectivity from our backend server to https://appleid.apple.com (port 443) has been confirmed as fully functional via ping and curl -v. The incoming TLS handshake from our iOS client app to our backend server's callback URL (https://api.example.com:port/...) is successful and verified via openssl s_client -connect. There are no longer any TLS handshake errors (EOF). Our backend server's system clock is accurately synchronized via NTP. Request for Assistance: Given that all our visible configurations, environment variables, and request parameters appear to be correct and align with Apple's documentation, and network connectivity is confirmed, we are at a loss for why the invalid_client error persists. Based on TN3107, this error typically implies an issue with the client secret's signature or its validity for the given client_id. However, our logs confirm correct iss, sub, aud, and kid, and the private key content. Has anyone encountered this persistent invalid_client error when all checks pass? Are there any less common configurations or troubleshooting steps we might be missing? Could this indicate a caching or propagation delay on Apple's servers, even after waiting periods? Any insights or guidance would be greatly appreciated. We are prepared to provide detailed, anonymized logs and screenshots to Apple Developer Support privately if requested. Thank you.
0
0
156
May ’25
Backup Eligibility and Backup State has set to true for support hybrid transport with legacy authenticators
My application is supporting hybrid transport on FIDO2 webAuthn specs to create credential and assertion. And it support legacy passkeys which only mean to save to 1 device and not eligible to backup. However In my case, if i set the Backup Eligibility and Backup State flag to false, it fails on the completion of the registrationRequest to save the passkey credential within credential extension, the status is false instead of true. self.extension.completeRegistrationRequest(using: passkeyRegistrationCredential) The attestation and assertion flow only works when both flags set to true. Can advice why its must have to set both to true in this case?
0
0
107
Sep ’25
App Attest API – "DCErrorInvalidKey 3" after App or OS Update
Hi everyone, We are using the App Attest API to securely transition users to our new system. As part of this, we store the Key ID of the attestation key for each user to verify their identity later. However, we’ve noticed that some users are encountering the error “DCErrorInvalidKey 3” when calling generateAssertion. Importantly, the key was previously successfully attested, and generateAssertion has worked before for these users. Our questions: Could this error be caused by an app or iOS update? Is it problematic to link an attestation key's Key ID directly to a user, or are there scenarios where the key might change or become invalid? If there’s a way to mitigate this issue or recover affected users, what best practices would you recommend? Any help or shared experiences would be greatly appreciated! Thanks in advance.
0
3
172
Apr ’25
Sign in with Apple Sync Issues Across Teams
We have 2 developers: Developer A created a Bundle ID and configured Sign in with Apple, but didn't create a corresponding App. This Bundle ID is only used for login on our official website. Developer B created a Bundle ID, configured Sign in with Apple, and has a corresponding App. The issue we're encountering is that because these two Bundle IDs are under different teams, when using the same Apple ID to log into these two applications, different accounts are generated. (We've tested that when creating Service IDs under the same team, logging in with Bundle IDs under the same team generates the same account.) Since Developer A's Bundle ID doesn't have a created app, it cannot be transferred to Developer B. Therefore, we'd like to know if there's any way to make the accounts generated from logging in with the same Apple ID be identical across these two teams?
0
0
373
Feb ’25
Sending to Private Relay Email using amazon ses not working
Hello Developers, I have ran into a problem while sending mail to apple private relay email. We have built a mobile application where user can sign up through apple and they can sign up using hide-my-email feature. Which provides private relay address for us. Now we want to communicate with them using private relay mail address. The technology we are using to send emails are amazon SES, have done SPF, DMIK, DMARC and added domains in apple identity services for mail communication, passed an SPF check as well. But still mail is not getting delivered what am i doing wrong or apple doesn't support third party apps for sending emails to private relay? Is there any other way to achieve this please let me know Using the same body as attached in image is working fine for rest emails.
0
0
312
Sep ’25
App Closes After Apple Sign-In on Vision Pro When Launched Directly
I am experiencing an issue with Apple Sign-In on Vision Pro. When I build and run the app from Xcode, everything works fine—after signing in, the app returns to the foreground as expected. However, when I launch the app directly on Vision Pro (not from Xcode), after completing the sign-in process, the app does not reopen from the background automatically. Instead, it closes, and I have to manually tap the app icon to reopen it. Has anyone else encountered this issue? Is there a way to ensure the app properly resumes after sign-in without requiring manual intervention?
0
0
498
Feb ’25
Background Location Indicator Remains Active Despite "Never" Permission Setting in iOS 18+
Hi everyone, I'm encountering an issue where the background location indicator remains visible on the status bar even though I have set the location permissions to Never for my app in the system settings. Despite taking all the necessary steps to stop location tracking (including stopping updates, geofencing, and other location-related services), the indicator still appears. This seems to be a bug since everything has been turned off on my end. Here’s what I’ve already tried: Setting location permissions to Never in the settings. Stopping startUpdatingLocation(), stopMonitoringSignificantLocationChanges(), and geofencing (using locationManager.stopMonitoringRegions()). Calling locationManager.showsBackgroundLocationIndicator = false. Ensuring that the CLLocationManager is fully invalidated. Despite all of this, the background location indicator still remains in the status bar. I’ve tested it on real devices, as well as in the simulator, with no improvement. Has anyone experienced something similar, or can suggest why this might be happening? Could this be related to an iOS 18+ issue? Any insights or guidance would be greatly appreciated.
0
0
369
Dec ’24