I've got a few questions about device check, and would be grateful if anybody knows the answers:
why is DC not reset when the device transfers between users?
The canonical example of why an app might use DC is if it offers a promotion and to stop user's from getting that promotion multiple times.
However, using the same example scenario yes you've stopped the first user from getting multiple promotions but then if that device is transferred to another user you've stopped them from getting any promotions at all?
how can you test things when the bits can't be reset? If once you've set the bits on a device then you can no longer ever use that device again to test the apps behavior in the situation when the bits are unset.
does the app have complete freedom to set the timestamp to whatever it wants? For example, could the app set a bit with a timestamp of epoch?
if the bits are shared between all apps from the same developer, then supposing that developer have more apps in the App Store then there are bits? If they have 5 apps offering a promotion and a device has previously had 4 apps installed, then the user wants to install a 5th app, but with all 4 bits now then the user will be able to abuse the promotion on the 5th app because the app has no way of recording if the promo has been used or not as the collective bits have been used up?
Security Interface
RSS for tagThe Security Interface framework is a set of Objective-C classes that provide user interface elements for programs that implement security features.
Posts under Security Interface tag
16 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
When we enable 3rd party authentication plugin using SFAuthorization window, and during unlock the screen, we have observed the widgets are not showing the content.
Attaching the screenshot for reference.
We are noticing this behavior from macOS 14.7.1 and macOS 15
Hi everyone,
I’m working on building a passwordless login system on macOS using the NameAndPassword module. As part of the implementation, I’m verifying if the password provided by the user is correct before passing it to the macOS login window.
Here’s the code snippet I’m using for authentication:
// Create Authorization reference
AuthorizationRef authorization = NULL;
// Define Authorization items
AuthorizationItem items[2];
items[0].name = kAuthorizationEnvironmentPassword;
items[0].value = (void *)password;
items[0].valueLength = (password != NULL) ? strlen(password) : 0;
items[0].flags = 0;
items[1].name = kAuthorizationEnvironmentUsername;
items[1].value = (void *)userName;
items[1].valueLength = (userName != NULL) ? strlen(userName) : 0;
items[1].flags = 0;
// Prepare AuthorizationRights and AuthorizationEnvironment
AuthorizationRights rights = {2, items};
AuthorizationEnvironment environment = {2, items};
// Create the authorization reference
[Logger debug:@"Authorization creation start"];
OSStatus createStatus = AuthorizationCreate(NULL, &environment, kAuthorizationFlagDefaults, &authorization);
if (createStatus != errAuthorizationSuccess) {
[Logger debug:@"Authorization creation failed"];
return false;
}
// Set authorization flags (disable interaction)
AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights;
// Attempt to copy rights
OSStatus status = AuthorizationCopyRights(authorization, &rights, &environment, flags, NULL);
// Free the authorization reference
if (authorization) {
AuthorizationFree(authorization, kAuthorizationFlagDefaults);
}
// Log the result and return
if (status == errAuthorizationSuccess) {
[Logger debug:@"Authentication passed"];
return true;
} else {
[Logger debug:@"Authentication failed"];
return false;
}
}
This implementation works perfectly when the password is correct. However, if the password is incorrect, it tries to re-call the macOS login window, which is already open. even i though i did not used the kAuthorizationFlagInteractionAllowed flag. This causes the process to get stuck and makes it impossible to proceed.
I’ve tried logging the flow to debug where things go wrong, but I haven’t been able to figure out how to stop the system from re-calling the login window.
Does anyone know how to prevent this looping behavior or gracefully handle an incorrect password in this scenario? I’d appreciate any advice or suggestions to resolve this issue.
Thanks in advance for your help!
Hello developers,
I'm currently working on an authorization plugin for macOS. I have a custom UI implemented using SFAuthorizationPluginView, which prompts the user to input their password. The plugin is running in non-privileged mode, and I want to store the password securely in the system keychain.
However, I came across an article that states the system keychain can only be accessed in privileged mode. At the same time, I read that custom UIs, like mine, cannot be displayed in privileged mode.
This presents a dilemma:
In non-privileged mode: I can show my custom UI but can't access the system keychain.
In privileged mode: I can access the system keychain but can't display my custom UI.
Is there any workaround to achieve both? Can I securely store the password in the system keychain while still using my custom UI, or am I missing something here?
Any advice or suggestions are highly appreciated!
Thanks in advance! 😊
Hi,
I have a certificate, how can I display the certificate content in my Mac app just like Keychain Access app does. Can I popup the certificate content dialog just like Keychain Access app?
Hi ,
I did The MFA(2FA) of Email OTP For MacOS Login Screen using, Authorization Plugin, Using This git hub project. It is working For Login Screen , Im trying to Add The Same plugin for LockScreen but it is not working at lock Screen , Below is the reffrense theard For The issue ,
https://developer.apple.com/forums/thread/127614,
please Share The Code that should Present the NSwindow at Screen Saver (Lock Screen) MacOS .
I'm developing an SDK that will allow iOS devices (iOS 13+) to connect to AWS IoT Core using Native C. The endpoint requires a mutual TLS handshake to connect. I have been able to successfully import a Certificate and Private Key into the keychain but am unable to generate a SecIdentityRef from them for use in setting up a nw_protocol_options_t. I've looked through other forum posts and have been unable to figure out what's going on (Some are from 5+ years ago and maybe things have changed since then).
After prepping the raw data for the cert and key into expected formats I import the certificate:
const void *add_keys[] = {
kSecClass,
kSecAttrLabel,
kSecAttrSerialNumber,
kSecValueData,
kSecReturnRef };
const void *add_values[] = {
kSecClassCertificate,
label,
serial_data,
cert_data,
kCFBooleanTrue };
attributes = CFDictionaryCreate(
cf_alloc,
add_keys,
add_values,
5,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemAdd(attributes, (CFTypeRef *)out_certificate);
Next I import the private key:
const void *add_keys[] = {
kSecClass,
kSecAttrKeyClass,
kSecAttrKeyType,
kSecAttrApplicationLabel,
kSecAttrLabel,
kSecValueData,
kSecReturnRef };
const void *add_values[] = {
kSecClassKey,
kSecAttrKeyClassPrivate,
key_type,
application_label,
label,
key_data,
kCFBooleanTrue };
attributes = CFDictionaryCreate(
cf_alloc,
add_keys,
add_values,
7,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
status = SecItemAdd(attributes, (CFTypeRef *)out_private_key);
The full code handles duplicate items in which case attributes are updated. Following the successful import of the cert and key to the keychain, I attempt to retrieve the identity with the following:
SecIdentityRef identity = NULL;
CFDictionaryRef query = NULL;
const void *query_keys[] = {
kSecClass,
kSecReturnRef,
// kSecAttrSerialNumber,
// kSecAttrLabel
kSecMatchLimit
};
const void *query_values[] = {
kSecClassIdentity,
kCFBooleanTrue,
// cert_serial_data,
// cert_label_ref
kSecMatchLimitAll
};
query = CFDictionaryCreate(
cf_alloc,
query_keys,
query_values,
3,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
OSStatus identity_status = SecItemCopyMatching(query, (CFTypeRef *)&identity);
I have attempted using various search parameters related to the label and the serial of the certificate. Based on other forum post suggestions I have also tried expanding the search to kSecMatchLimitAll to get back ANY stored kSecClassIdentity and all variations returned OSStatus of -25300 (errSecItemNotFound). Once I am able to retrieve the SecIdentityRef, my understanding is that I can add it to the following during creation of the socket:
nw_protocol_options_t tls_options = nw_tls_create_options();
sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
sec_protocol_options_set_min_tls_protocol_version(sec_options, tls_protocol_version_TLSv12);
sec_protocol_options_set_max_tls_protocol_version(sec_options, tls_protocol_version_TLSv13);
sec_protocol_options_set_local_identity(sec_options, SecIdentityRef);
Am I missing some step that is required to create an identity from the certificate and private key? I have tested the cert/key pair and they connect properly when using the old deprecated SecItemImport and SecIdentityCreateWithCertificate (on our old macOS only implementation).
I will continue to dig through Apple documentation as well as more forum posts but I feel like I'm hitting a wall and missing something very obvious as this seems like a very common networking task. Thanks!
The provided links below are to the full code related to the work in progress iOS import functions:
Link to import function https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L735
Link to private key import: https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L561
Link to certificate import: https://github.com/awslabs/aws-c-io/blob/cad8639ef0ea08ba3cc74b72cfc1c9866adbb7e5/source/darwin/darwin_pki_utils.c#L398
SecKeychain API has been declared deprecated a long time ago.
Do people from Apple or developers have a rough idea when this API will be definitely removed?
One year from now? More? Less?
Hello Folks
I have a Custom UrlSessionDeleagte which is checking server authentication by overriding method
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
let serverTrust = challenge.protectionSpace.serverTrust
// Applying additional validations.
if(validated)
{
completionHandler(.useCredential, URLCredential(trust:serverTrust))
}
}
else
{
completionHandler(.performDefaultHandling, nil)
}
Initialized URL Session as below and reusing it in subsequent requests.
if(urlSession != nil)
{
urlSession = URLSession(configuration: URLSessionConfiguration.Default, delegate: customURLSessionDelegate, delegateQueue : nil)
}
Now the issue is the uncertainty in response time
First request - say took approx 11 secs.
Second request if send immediately (< 2 secs difference from last call) - took only 0.2 secs or 1.2 secs.
Third request if send after >20 secs - took again 12 secs.
I want to know whether it is an implementation issue, or iOS behavior of handling the Server trust Authentication process in this way? Because the time it took after initializing a DataTask to checking server Auth differes. Also when call is sent immdiately it does not checkk Authentication again, but when send a after ~20 secs debugger fall on the Authentication method again, even if the URlsession instance was same.
Issue happens with system.login.screensaver.
After my SFAuthorizationPluginView sets a result allowing login, my view remains on screen for about eight seconds.
What makes my view disappear?
I notice that my plugin mechanism just gets a destroy call.
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 ?
Hi Devs,
i have a question concerning the security set-key-partition-list -S command. I want to use it to enable a code signing certificate being used by codesign and productbuild to sign without sudo or a password prompt. Some sources indicate i need to add codesign: as partition but some don't even mention this. So my question is what partitions are even possible to add? What does partitions in this context mean? How can i find out which i need for productbuild and codesign?
Thanks in advance
Paul
Does Apple allow extensions to Face ID?
I have a problem with the way it often reacts.
I also have a simple solution.
But does Apple allow extensions to Face ID?
If someone in Apple WWDR sees this, please take the feedback to heart and report it up the chain:
When you announce that a technology is being deprecated — such as CGDisplayStream — and also publish WWDC sessions about the intended replacement — ScreenCaptureKit — then you also need to give third-party developers a clear deadline by which this technology will be deprecated so that they can plan engineering efforts around implementing the new feature, and have ample time to communicate this to their customers. If it's important for third-party developers to get on board with this change, you should use every available means to communicate this to them, including multiple email alerts to their registered email address.
Additionally, if you plan to make a BREAKING change in a framework that results in a wildly different user experience, you should probably hold that off until the summer release for the next major OS.
What you should definitely NOT do is roll out a new privacy prompt in a mid-year release of macOS; or give your developers, customers, and AppleSeed program participants zero advance notice that this alert is coming, ignore your own Human Interface Guidelines when designing said prompt, and perform no user experience design testing (aka "putting on your customer hat") during a presumed internal alpha testing cycle to refine the experience and still find the most effective and least annoying way to present this additional prompt and spur change with your third-party developers.
Oh, wait, you've done exactly all those things the wrong way with respect to ScreenCaptureKit.
Right now, a host of Apple device administrators and client platform engineers are sending mountains of feedback to you, and they're also scrambling to contact third-party developers to let them know this is coming. Most of the vendors being discussed in private forums are said to be caught off guard by this change.
We anticipate that users are not going to like this, and there is no way we can manage it with MDM or configuration profiles. In short, the current experience is a ghastly mess. WE, the administrators, will get blamed for this, not the third-party developers. WE will have to explain to our leadership why this experience is terrible and cannot be managed.
Engineers need deadlines to help plan their work and prioritize tasks. In this case, vendors have had no firm deadline for this effort. There's already precedence for Apple announcing estimated deadlines for deprecations and feature removals. You do your developers and customers a great disservice by not communicating schedules to them.
Please do better.
P.S.: Feedback filed as FB13619326.
On recent macOS versions(Sonoma or previous), if system.login.screensaver is updated to use “authenticate-session-owner-or-admin” then fancy screensaver is not coming up, instead we are seeing only black screensaver ( black screen).
Note: Observed we are getting fancy screensavers with this setting on macOS BigSur.
Can you please let us know if this is an intentional change from macOS or we have any settings to enable to get fancy screensavers with recent macOS versions?
Thanks & Regards,
Tata Chaitanya
Hi there,
I’m having issue using Apple’s API. I can’t initialize SFAuthorizationPluginView using Swift.
I’ve done numerous google searches, but haven’t found any examples/tutorials of anyone using Swift for SFAuthorizationPluginView / AuthorizationPluginCreate.
I managed to get the AuthorizationPlugin and AuthorizationMechanism up, but simply creating the SFAuthorizationPluginView fails the failable initiator.
https://developer.apple.com/documentation/securityinterface/sfauthorizationpluginview
Here are some log messages I wrote:
error 16:08:33.689244-0800 kernel Library Validation failed: Rejecting '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (Team ID: 7X6364JT77, platform: no) for process 'SecurityAgentHel(2689)' (Team ID: N/A, platform: yes), reason: mapping process is a platform binary, but mapped file is not
error 16:08:33.689501-0800 SecurityAgentHelper-arm64 Error loading /Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent (78): dlopen(/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent, 0x0106): tried: '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (code signature in <BFF0D7BA-5CF8-3F2F-A604-DCC235499234> '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' not valid for use in process: mapping process is a platform binary, but mapped file is not), '/System/Volumes/Preboot/Cryptexes/OS/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (no such file), '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (code signature in <BFF0D7BA-5CF8-3F2F-A604-DCC235499234> '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' not valid for use in process: mapping process is a platform binary, but mapped file is not)
default 16:08:33.760679-0800 SecurityAgentHelper-arm64 callbacks: Optional(0x00000001001b1f88)
default 16:08:33.760710-0800 SecurityAgentHelper-arm64 andEngineRef: Optional(0x0000000156f384d0)
error 16:08:33.762404-0800 SecurityAgentHelper-arm64 Test API call result: OSStatus 0 i.e. No error.
error 16:08:33.763298-0800 SecurityAgentHelper-arm64 Failed to create Authorization Plugin Adapter
default 16:08:33.763524-0800 authd engine 66: running mechanism XXXAgent:XXXAgentMechanism (1 of 1)
Here is the calling code with the error message:
class AuthorizationMechanismXXX : AuthorizationMechanism
{
let mLogger = …
let mAuthorizationPluginView : AuthorizationPluginViewAdapter?
override init(inPlugin: UnsafeMutablePointer<AuthorizationPlugin>,
inEngine: AuthorizationEngineRef,
inMechanismId: AuthorizationMechanismId)
{
…
let pCallbacks : UnsafePointer<AuthorizationCallbacks> = inPlugin.pointee.EngineCallback()
self.mAuthorizationPluginView = AuthorizationPluginViewAdapter(callbacks: pCallbacks, andEngineRef: inEngine)
if (self.mAuthorizationPluginView == nil)
{
mLogger.error("Failed to create Authorization Plugin Adapter")
}
super.init(inPlugin: inPlugin, inEngine: inEngine, inMechanismId: inMechanismId)
}
Here is the class:
class AuthorizationPluginViewAdapter : SFAuthorizationPluginView
{
let mLogger = …
let mLoginView = NSHostingView(rootView: LoginView())
override init!(callbacks: UnsafePointer<AuthorizationCallbacks>!, andEngineRef engineRef: AuthorizationEngineRef!)
{
mLogger.notice("callbacks: \(callbacks.debugDescription, privacy: .public)")
mLogger.notice("andEngineRef: \(engineRef.debugDescription, privacy: .public)")
var sessionId: UnsafeMutablePointer<AuthorizationSessionId?>?
let result = callbacks.pointee.GetSessionId(engineRef, sessionId)
LogSecurityOSStatus(logger: mLogger, osStatus: result, message: "Test API call result")
super.init(callbacks: callbacks, andEngineRef: engineRef)
mLogger.notice("Never gets here")
}
override func buttonPressed(_ inButtonType: SFButtonType)
{
if (inButtonType == SFButtonTypeOK)
{
let osStatus = callbacks().pointee.SetResult(engineRef(), AuthorizationResult.allow)
if (osStatus != errSecSuccess)
{
LogSecurityOSStatus(logger: mLogger, osStatus: osStatus, message: "Error setting authorization result")
}
}
else if (inButtonType == SFButtonTypeCancel)
{
let osStatus = callbacks().pointee.SetResult(engineRef(), AuthorizationResult.deny)
if osStatus != errSecSuccess
{
LogSecurityOSStatus(logger: mLogger, osStatus: osStatus, message: "Error setting authorization result")
}
}
else
{
mLogger.error("Invalid buttonType.")
}
}
override func view(for inType: SFViewType) -> NSView!
{
if (inType == SFViewTypeIdentityAndCredentials)
{
mLogger.debug("Identity and credentials")
}
else if (inType == SFViewTypeCredentials)
{
mLogger.debug("Credentials only")
}
else
{
mLogger.error("Invalid buttonType.")
}
return mLoginView
}
}
Here is the view:
import SwiftUI
struct LoginView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
#Preview {
LoginView()
}