We have implemented a Notification Service Extension in our app to handle remote notification and access keychain to get certificate and identity to refresh network relay configuration. Using SecItemCopyMatching to get SecIdentityRef works when device is unlocked. Whenever push notification arrives and device is locked, our notification service extension failed to access keychain to get identity reference with error code -25308 errSecInteractionNotAllowed.
It looks like keychain is locked when device is locked. Is there a way to make keychain unlocked?
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
Hello,
I am creating CryptotokenKit persistent token extension for macOS using Xcode on Sonoma. The goal is to support external crypto provider over network (with API calls).
I created a bare minimum app and a new target “Persistent Token Extension”. Before I go into specific implementation, I wanted to check if my extension/token initialises correctly. My understanding is that once the host app is started and the extension is registered by the OS, future queries for digital identities should check with it as well.
I tried is accessing mTLS website with Safari and Firefox that require client certificates, as well running custom application using SecItemCopyMatching to query the keychain for identities.
However, Token / TokenDriver seem to not initialize (logging never executes). Am I missing something here?
pluginkit sees the extension:
$ pluginkit -vvvvmi demo.TokenApp.TokenExt
demo.TokenApp.TokenExt(1.0)
Path = /Users/alexander/Library/Developer/Xcode/DerivedData/TokenApp-dzulesgoanwnacguirprimnipibk/Build/Intermediates.noindex/Previews/TokenApp/Products/Debug/TokenApp.app/Contents/PlugIns/TokenExt.appex
UUID = 617526E8-987A-493F-A9E3-6295FF5AB00D
Timestamp = 2024-01-19 13:13:35 +0000
SDK = com.apple.ctk-tokens
Parent Bundle = /Users/alexander/Library/Developer/Xcode/DerivedData/TokenApp-dzulesgoanwnacguirprimnipibk/Build/Intermediates.noindex/Previews/TokenApp/Products/Debug/TokenApp.app
Display Name = TokenExt
Short Name = TokenExt
Parent Name = TokenApp
Platform = macOS
Token.swift:
import CryptoTokenKit
import OSLog
class Token: TKToken, TKTokenDelegate {
private let log = Logger(subsystem: "demo.tokenapp", category: "Token");
func createSession(_ token: TKToken) throws -> TKTokenSession {
log.log(level: .info, "Token.createSession")
return TokenSession(token:self)
}
}
TokenDriver.swift:
import CryptoTokenKit
import OSLog
class TokenDriver: TKTokenDriver, TKTokenDriverDelegate {
private let log = Logger(subsystem: "demo.tokenapp", category: "TokenDriver");
func tokenDriver(_ driver: TKTokenDriver, tokenFor configuration: TKToken.Configuration) throws -> TKToken {
log.log(level: .info, "TokenDriver.tokenDriver")
return Token(tokenDriver: self, instanceID: configuration.instanceID)
}
}
My goal is:
Generate a public and private key pair
Add the private key to the keychain and protect it with the secure enclave
Create a self-signed certificate with the public key and send it to a server
Add the certificate to the keychain
When I communicate with the server I want to create a SecIdentity during the client challenge which is basically a SecCertificate + SecKey combo.
For the certificate generation I would like to use the swift-certificates library to not have to compose manually the certificate fields and signature.
My problem is that the swift-certificates during the Certificate initialisation needs a SecureEnclave.P256.Signing.PrivateKey private key and to add a key to the keychain we need a SecKey object. And unfortunately there is no clean way to create from one of them the other one. I read several threads here about this, but I haven't found a clean solution for it.
I tried to approach the problem from two directions:
First:
Create the key with the SecKeyCreateRandomKey, mark in the attributes that I want to protect the key with secure enclave and also mark that I want the private key to be kSecAttrIsPermanent so it is automatically saved in the keychain
The SecKeyCreateRandomKey returns a SecKey which is a reference to the private key from the keychain
(!) Unfortunately I haven't found a clean way to convert a SecKey to a -> SecureEnclave.P256.Signing.PrivateKey
There is a workaround to SecKeyCopyAttributes of the private key and to extract the bytes from the attributes["toid"], but I guess it's not safe to use an undocumented key ("toid") if there is no constant defined to it (the name could be changed in future releases)
Second approach:
Create a SecureEnclave.P256.Signing.PrivateKey
Create the Certificate using the swift-certificates
The created private key is protected by the secure enclave but it's not added automatically to the keychain so we should add it to can query after that the SecIdentity
(!) Unfortunately I haven't found a way to convert the SecureEnclave.P256.Signing.PrivateKey to -> SecKey.
There are threads which say that the SecKeyCreateWithData(...) helps us, but unfortunately if we set the kSecAttrTokenIDSecureEnclave in the attribute dictionary, the method creates a brand new key for us, regardless the passed data. So the initial key will never be the same as the newly created SecKey. This we can see in the method's implementation.
So I got stuck with both approaches because seemingly there is no clean way to switch between SecureEnclave.P256.Signing.PrivateKey and SecKey.
One solution would be to compose manually the certificate, without swift-certificates because like that we would not need a SecureEnclave.P256.Signing.PrivateKey object. But I would like to avoid the manual composition and signature calculation...
Anybody has any idea?
Hi, I want to support client certifcate authentication for a URL loaded in WKWebView. Certificate is in the smartcard that is connected to iOS device through lightning port smart card reader. For USB-C type reader, iOS supports this out of the box. But for the lightning port reader, I thought of writing a CTK extension to access smartcard and read the certificate. I have a smart card sdk to access the smartcard. Could you please let me know which is the extension that should be used for this purpose. There are 2 types of extensions available in Xcode. Smartcard extension and Persistent Token extension. Which one should be used for this case? When I tried persistent token extension, it seems to hit sign function inside Tokensession class but with smartcard extension it is not getting called when I try to access the URL in WKWebView after certificate selection. Also the smartcard sdk has EAAccessory framework dependency. Is EAAccessory allowed to be used in CTK extension? https://developer.apple.com/forums/thread/111691?answerId=342707022 says EAAccessory is not working inside app extension. Thanks in advance.
// Example configuration: com.apple.configuration.security.passkey.attestation
{
"Type": "com.apple.configuration.security.passkey.attestation",
"Identifier": "B1DC0125-D380-433C-913A-89D98D68BA9C",
"ServerToken": "8EAB1785-6FC4-4B4D-BD63-1D1D2A085106",
"Payload": {
"AttestationIdentityAssetReference": "88999A94-B8D6-481A-8323-BF2F029F4EF9",
"RelyingParties": [
"www.example.com"
]
}
}
I have an app that is getting rejected from TestFlight because of this error:
ITMS-90683: Missing purpose string in Info.plist - Your app’s code references one or more APIs that access sensitive user data, or the app has one or more entitlements that permit such access. The Info.plist file for the “TurtleTuner.app” bundle should contain a NSCameraUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. If you’re using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. For details, visit: https://developer.apple.com/documentation/uikit/protecting_the_user_s_privacy/requesting_access_to_protected_resources.
The app does not use the camera, only the microphone. I cannot find references to the camera in any of the third party libraries I'm using.
What are some ways to troubleshoot this beyond looking for "camera" in the few dependencies?
For context, this commit allows the app to get through successfully to TestFlight: https://github.com/tsargent/turtle-tuner/commit/67d4a52e62839ad6c2a49848bea9c408d983f17a
While this following commit, which reverts the commit, fails on TestFlight with the mentioned camera permission error: https://github.com/tsargent/turtle-tuner/commit/c95b0b16c4e85d77e625d36b816ed53faa826cf5
Hello Everyone,
Is there any method or callback event to obtain the current time and date mode (Automatic or Manual) in Swift?
In Android, Settings.Global.AUTO_TIME is used for the same.
Could anyone advise on the equivalent functionality or approach for iOS development?
Thanks in advance!
Hello, according to this doc Apple will begin blocking app store submissions in Spring 2024 when an application or one of its 3rd-party SDKs calls certain iOS/iPadOS system APIs without declaring a reason for doing so via a privacy manifest.
It seems that for framework and app targets, adding a privacy manifest is relatively straightforward: Add the xcprivacy file to the project and make it a member of the appropriate build target. For apps and fameworks, this will cause the privacy manifest to be copied into the root directory of the .app or .framework bundle at build time.
I work on a SDK which ships to application developers as a static library (.a) bundled within a xcframework. It seems that Xcode will not allow a privacy manifest file to be added as a member of a static library target. Which I assume is because when compiled, a static library build target does not produce a bundle like a ".app" or ".framework" which you'd get when compiling an app or framework target. Just a standalone (.a) file. What is the recommended way for developers of static libraries to provide application developers with a privacy manifest for their SDK? Is there a mechanism for including the privacy manifest somewhere within the xcframework bundle at the time it is created for the static lib, so that it automatically gets copied into an application which may link to it? If not, can the privacy manifest be included in a resource bundle which we already provide to our partners along with the static lib? Or does the manifest need to exist within the root directory of the application bundle since the contents of the static lib will ultimately get embedded into the app binary? If that is the case, do we need to provide our app partners with a separate standalone xcprivacy file, which they would need to incorporate into their project?
Current situation.
I'm using third-party sdk make by myself with my app.
my app use UserDefaults api, and My sdk(framework) too
Recently,
apple store policy changed, apple says If you use "Userdefaults API", Include Privacy Manifest.
As a result My app including two Privacy manifest
If I create 10 SDKs, and all of these SDKs use "Userdefaults API", and one app itself also uses the "Userdefaults API", is it correct to include 11 "Privacy manifests" in this app?
Hello,
I am developing a smartcard CTK extension for macOS.
I have trouble to smartcard logon the first time after a reboot or a logout (e.g. when there is the text "Your password is required to enable touch id"). Trouble = I'm not asked for the PIN.
But time to time after a logout (from whatever account), I can login with the smartcard. After a lockscreen I can always login with the smartcard.
Is there an easy way to debug the logon process ?
Regards,
++dom
Hi!
In the team I work with, we develop an sdk for iOS which has support for two internal variations, one with basic capabilities and another with full ones, embedded in the same xcframework.
The thing is with the privacy manifest change in the horizon, we are wondering if the sdk in the basic version can have a manifest with some values and the manifest in the sdk full version can have a different value, since the capabilities enabled in one may have different nutrition label types values than the other.
Is that scenario feasible, or there is a different way for this situation?
Thanks
What is the difference between ASPasskeyCredentialIdentity.userName and ASPasskeyCredentialIdentity.user ?
From https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialuserentity-displayname there should be only displayName.
I'm trying to set up Sign In With Apple on my .NET 7 Web App (Not sure how many people here use this). I followed the guide by Scott Brady here: https://www.scottbrady91.com/openid-connect/implementing-sign-in-with-apple-in-aspnet-core
It reaches Apple Sign In OK, authenticates, and passes back to my server, but the callback responds with this error.
OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null'.
Googling hasn't helped much, other than I saw a post saying to wait 48 hours, which I have now done (not that that makes sense anyway).
Any idea whats been done wrong? Code below, replacing sensitive data.
Startup.cs
.AddOpenIdConnect("apple", async options =>
{
options.Authority = "https://appleid.apple.com"; // disco doc: https://appleid.apple.com/.well-known/openid-configuration
options.ClientId = "com.rackemapp.applelogin"; // Service ID
options.CallbackPath = "/signin-apple"; // corresponding to your redirect URI
options.ResponseType = "code id_token"; // hybrid flow due to lack of PKCE support
options.ResponseMode = "form_post"; // form post due to prevent PII in the URL
options.UsePkce = false; // apple does not currently support PKCE (April 2021)
options.DisableTelemetry = true;
options.Scope.Clear(); // apple does not support the profile scope
options.Scope.Add("openid");
options.Scope.Add("email");
options.Scope.Add("name");
options.Events.OnAuthorizationCodeReceived = context =>
{
context.TokenEndpointRequest.ClientSecret = AppleTokenGenerator.CreateNewToken();
return Task.CompletedTask;
};
});
Apple Token Generator
public static class AppleTokenGenerator
{
public static string CreateNewToken()
{
const string iss = "[MyTeamId]"; // your account's team ID found in the dev portal
const string aud = "https://appleid.apple.com";
const string sub = "com.rackemapp.applelogin"; // same as client_id
var now = DateTime.UtcNow;
// contents of your .p8 file
const string privateKey = "[MyKey]";
var ecdsa = ECDsa.Create();
ecdsa?.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey), out _);
var handler = new JsonWebTokenHandler();
return handler.CreateToken(new SecurityTokenDescriptor
{
Issuer = iss,
Audience = aud,
Claims = new Dictionary<string, object> { { "sub", sub } },
Expires = now.AddMinutes(5), // expiry can be a maximum of 6 months - generate one per request or re-use until expiration
IssuedAt = now,
NotBefore = now,
SigningCredentials = new SigningCredentials(new ECDsaSecurityKey(ecdsa), SecurityAlgorithms.EcdsaSha256)
});
}
}
Also attached, images of my keys and setp in developer portal
We are trying to integrate "Sign in with Apple" and are facing an issue where all users who chose to use Apple's private relay with the hide my email feature are unable to receive any mail sent by us.
We have added our domain, mail from domain & email address to https://developer.apple.com/account/resources/services/configure and also verified the SPF. We also have DKIM setup.
We use SES as our email provider and have added its SPF as recommended aswell.
I have attached a sample delivery log from SES below.
{"notificationType":"Delivery","mail":{"timestamp":"2024-01-17T10:20:07.592Z","source":"\"Redacted\" <admin@redacted>","sourceArn":"arn:aws:ses:ap-south-1:redacted:identity/redacted","sourceIp":"34.redacted","callerIdentity":"redacted-ses","sendingAccountId":"redacted","messageId":"redacted","destination":["redacted@privaterelay.appleid.com"]},"delivery":{"timestamp":"2024-01-17T10:20:12.385Z","processingTimeMillis":4793,"recipients":["redacted@privaterelay.appleid.com"],"smtpResponse":"250 2.0.0 Ok: queued as redacted","remoteMtaIp":"redacted","reportingMTA":"redacted.smtp-out.ap-south-1.amazonses.com"}}
Hello,
we implemented Apple Sign-In in our website long ago, and it worked well.
Recently we have found a strange behaviour.
The first time we make the request to the /auth/token endpoint we get an invalid_client error.
Our client id is com.spicysparks.service.id
If we make a request another time with exactly the same data it works fine.
We noticed we get this error only when we try a newly generated client secret for the first time.
The sign in with Apple prereqs state that:
you must have an existing app in the App Store that uses Sign in with Apple
If you want to support sign in with apple on a website but do not need an iOS app specifically for that website is possible to have a "dummy" app that isn't released to the app store but will serve to support sign in with Apple?
For a security product, I wonder if security extension has a capability to catch a file during copy operation (I guess it's composed out of multiple basic ops like file read and file write).
I'd like to store the file in some quarantined temporal (let's say when someone copy file from external file system like usb/network location and copy it back once the file has properly scanned.
So far, i've used the authorization capabilities of the security extension. I wonder if there's also an option to change the target location of a file being copied ?
Thanks.
We have a game that provides a mechanism to log into the game with Sign in with Apple in a direct integration between the game and Apple (first mechanism). We also provide a mechanism to log into the game using OpenID connect with authorization from Apple but using a server in the middle that drives the process (second mechanism). It is important to mention that both mechanisms use the same oauth client.
We have been able to switch from the first mechanism to the second successfully, but there is a problem with id_token.
In the second mechanism we request the scopes "email", "openid" and "name", but in the retrieved id_token there is no information about the email. It happens for all users who previously signed in with Apple using the first mechanism (therefore there is a current link between the game and the user in AppleId). It does not happen with users who had no link between the game and the user and use the second mechanism, in this case we can retrieve the user information in the callback of the first call and the email in the id_token, as stated in the documentation.
However, if users who had a link between the game and the AppleId delete the app and then log back in using the second mechanism, then we can get the email information with the exact same request.
The request we use to obtain the authorized endpoint information (https://appleid.apple.com/auth/authorize) has these parameters:
response_mode: query
scope: email openid profile
nonce: ...
state: ...
response_type: code
Then we get the authentication code and get an id_token like this:
{
"iss":"https://appleid.apple.com",
"aud":"{aud}",
"exp":1705584621,
"iat":1705498221,
"sub":"{sub}",
"nonce":"7f-PqBoXgxeDMOEu5Ysov0FjE9GvSYfq",
"at_hash":"3kLcPBlwZP6aj_mscww5zA",
"authentication_time":1705498218,
"nonce_supported":true
}
Is there a way to retrieve the email for users who had the link and don't want to delete it or log back into the app? In the official Apple documentation it is stated that the id_token should have the email but this is not the case.
https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773
Hey all, so I currently have a passkey provider application on iOS that works for every RP except for google.
I found this post here saying the AttestationObject needs to be an ordered dictionary and can confirm on https://webauthn.me/debugger that my object is an ordered dictionary in the correct format.
However, google fails to create the key every time saying generically the passkey can't be saved at this time.
I'm just curious if there is something unique about google, like are they maybe whitelisting providers? Or do they require something extra that I need to send?
I can't find any other information for why google wouldn't work while everyone else does.
Thanks in advance for any help!
We develop SDKs that are distributed as XCFramework to our clients. We seek clarification regarding the necessity of attaching a Privacy Manifest, especially in instances where our SDK does not interact with data that would typically be covered under such a manifest.
Additionally, in the scenario where our SDK's primary function is the transmission and reception of data, which may potentially include personal data, are we required to declare in the Privacy Manifest that we handle personal information? This query persists even when all personal data processing is executed on the server side.
From our current understanding, based on the information available at https://developer.apple.com/support/third-party-SDK-requirements/, it appears that SDKs are only obligated to have a signature, and incorporating a Privacy Manifest may not be compulsory. We would appreciate further insight or confirmation on this matter.