Hi everyone,
I’m encountering an unexpected Keychain behavior in a production environment and would like to confirm whether this is expected or if I’m missing something.
In my app, I store a deviceId in the Keychain based on the classic KeychainItemWrapper implementation. I extended it by explicitly setting:
kSecAttrAccessible = kSecAttrAccessibleAfterFirstUnlock
My understanding is that kSecAttrAccessibleAfterFirstUnlock should allow Keychain access while the app is running in the background, as long as the device has been unlocked at least once after reboot.
However, after the app went live, I observed that when the app performs background execution (e.g., triggered by background tasks / silent push), Keychain read attempts intermittently fail with:
errSecInteractionNotAllowed (-25308)
This seems inconsistent with the documented behavior of kSecAttrAccessibleAfterFirstUnlock.
Additional context:
The issue never occurs in foreground.
The issue does not appear on development devices.
User devices are not freshly rebooted when this happens.
The Keychain item is created successfully; only background reads fail.
Setting the accessibility to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly produces the same result.
Questions:
Under what circumstances can kSecAttrAccessibleAfterFirstUnlock still cause a -25308 error?
Is there any known restriction when accessing Keychain while the app is running in background execution contexts?
Could certain system states (Low Power Mode, Background App Refresh conditions, device lock state, etc.) cause Keychain reads to be blocked unexpectedly?
Any insights or similar experiences would be greatly appreciated. Thank you!
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
I encountered an error with the following message while attempting to make an in-app purchase on iOS:
"Error Domain=SKErrorDomain Code=2 "(null)" UserInfo={NSUnderlyingError=0x281ec3840 {Error Domain=ASDErrorDomain Code=907 "(null)" UserInfo={NSUnderlyingError=0x281ec3720 {Error Domain=AMSErrorDomain Code=6 "Payment Sheet Failed" UserInfo={NSLocalizedDescription=Payment Sheet Failed, AMSURL=https://p41-buy.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008101-001539DC0C8A001E, AMSStatusCode=200, AMSServerPayload={
"cancel-purchase-batch" = 1;
customerMessage = "Sign in with Apple ID";
dialog = {
cancelButtonString = Cancel;
defaultButton = Buy;
explanation = "Enter the password for %%appleId%% to authorise this transaction.";
initialCheckboxValue = 1;
kind = authorization;
"m-allowed" = 0;
message = "Sign in with Apple ID";
okButtonAction = {
buyParams = "";
itemName = "IAP_id_02_1500_product06";
kind = Buy;
};
okButtonString = Buy;
paymentSheetInfo = {
caseControl = true;
confirmationTitle = Pay;
countryCode = ID;
currency = IDR;
designVersion = 2;
flexList = (
{
value = (
{
style = priceMain;
value = "Rp\U00a0249ribu";
},
{
style = priceSub;
value = "One-time charge";
}
);
},
{
style = account;
value = "Account: %%appleId%%";
}
);
images = (
{
type = itunesgames;
value = "17+";
}
);
price = 249000;
requestor = AppStore;
salableIcon = "";
salableIconType = app;
salableInfo = ();
styles = (
{
bold = true;
name = priceMain;
size = large;
},
{
color = gray;
name = priceSub;
},
{
color = gray;
name = account;
}
);
suppressPrice = true;
title = {
type = text;
value = "App\U00a0Store";
};
};
};
failureType = "";
"m-allowed" = 0;
metrics = {
actionUrl = "p41-buy.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy";
dialogId = "MZCommerceInAppBuy.ConfirmationNeededForBuyOneItem.CPS.Auth";
eventType = dialog;
message = "Sign in with Apple ID";
mtEventTime = "2023-07-11 12:38:00 Etc/GMT";
mtTopic = "xp_its_main";
osloTitleType = text;
osloTitleValue = "AbstractSalableInfoModule.AppStore";
topic = "xp_its_main";
};
pings = (
"https://xp.apple.com/report/2/xp_its_main?code=MZCommerceInAppBuy.ConfirmationNeededForBuyOneItem.CPS.Auth&buttons=Buy%3ACancel&baseVersion=1&dsId=8381620277&eventVersion=1&storeFrontHeader=143476-2%2C29&eventTime=1689079082059&eventType=dialog&message=Sign%20in%20with%20Apple%20ID"
);
"tid-dialog" = {
cancelButtonString = Cancel;
explanation = "MZCommerceInAppBuy.ConfirmationNeededForBuyOneItem.CPS.Auth.TID_explanation";
kind = authorization;
message = "MZCommerceInAppBuy.ConfirmationNeededForBuyOneItem.CPS.Auth.TID_message";
paymentSheetInfo = {
caseControl = true;
confirmationTitle = Pay;
countryCode = ID;
currency = IDR;
designVersion = 2;
flexList = (
{
value = (
{
style = priceMain;
value = "Rp\U00a0249ribu";
},
{
style = priceSub;
value = "One-time charge";
}
);
},
{
style = account;
value = "Account: %%appleId%%";
}
);
images = (
{
type = itunesgames;
value = "17+";
}
);
price = 249000;
requestor = AppStore;
salableIcon = "";
salableIconType = app;
salableInfo = ( );
styles = (
{
bold = true;
name = priceMain;
size = large;
},
{
color = gray;
name = priceSub;
},
{
color = gray;
name = account;
}
);
suppressPrice = true;
title = {
type = text;
value = "App\U00a0Store";
};
};
touchIDButtonAction = {
buyParams = "";
itemName = "IAP_id_02_1500_product06";
kind = Buy;
};
};
}, NSLocalizedFailureReason=Payment sheet dismissed with neither an error nor a result}}}}}".
I would like assistance in understanding and resolving this issue.