Adding or removing the pre-authorize flag on main app doesn't change the behaviour.
I added the whole workflows that work or fails to provide more context :
// This workflow (lets call it 'A') succeeds:
// - user is prompted for admin password in main app
// - rights are forwarded to helper tool through XPC (based on 'EBAS' sample code)
// - SystemConfiguration is used to change machine name
// - Other privileged API can be used (e.g CFPreferences for /Library prefs)
//
// Main app
AuthorizationItem oneRight = { NULL, 0, NULL, 0 };
AuthorizationRights rights = { 1, &oneRight };
oneRight.name = "system.services.systemconfiguration.network";
AuthorizationExternalForm extForm;
OSStatus status = AuthorizationCreate(&rights, NULL, kAuthorizationFlagPreAuthorize | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, &self->_authRef);
if (status == errAuthorizationSuccess) {
// At this stage the user has been prompted and entered a valid admin password
status = AuthorizationMakeExternalForm(self->_authRef, &extForm);
}
if (status == errAuthorizationSuccess) {
authData = [[NSData alloc] initWithBytes:&extForm length:sizeof(extForm)];
}
// Helper tool through XPC
AuthorizationItem oneRight = { NULL, 0, NULL, 0 };
AuthorizationRights rights = { 1, &oneRight };
oneRight.name = "system.services.systemconfiguration.network";
OSStatus status = AuthorizationCreateFromExternalForm([authData bytes], &authRef);
if (status == errAuthorizationSuccess) {
status = AuthorizationCopyRights(authRef, &rights, NULL, kAuthorizationFlagExtendRights, NULL);
}
if (status == errAuthorizationSuccess) {
// This code is granted rights for System Configuration after user prompt from main app
SCPreferencesRef prefs = SCPreferencesCreateWithAuthorization(NULL, (CFStringRef)processName, NULL, authRef);
if (SCPreferencesLock(prefs, YES)) {
SCPreferencesSetComputerName(prefs, (CFStringRef)hostname, kCFStringEncodingUTF8);
SCPreferencesCommitChanges(prefs);
SCPreferencesUnlock(prefs);
}
}
// This code always succeed from helper tool regardless of authorizations from Security.framework
CFStringRef suite = CFSTR("com.company.sample");
CFPreferencesSetValue(CFSTR("myKey"), (__bridge CFStringRef)(myValue), suite, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
CFPreferencesSynchronize(suite, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
// This workflow (lets call it 'B') succeeds:
// - main app is launched with root user (e.g using xCode 'root' setup in debug scheme)
// - main app authorize implicitly with no UI (inherit rights from root)
// - helper tool get rights with no prompt UI
//
// Main app
AuthorizationItem oneRight = { NULL, 0, NULL, 0 };
AuthorizationRights rights = { 1, &oneRight };
oneRight.name = "system.services.systemconfiguration.network";
AuthorizationExternalForm extForm;
OSStatus status = AuthorizationCreate(&rights, NULL, kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights, &self->_authRef);
if (status == errAuthorizationSuccess) {
status = AuthorizationMakeExternalForm(self->_authRef, &extForm);
}
// Helper tool through XPC
AuthorizationItem oneRight = { NULL, 0, NULL, 0 };
AuthorizationRights rights = { 1, &oneRight };
oneRight.name = "system.services.systemconfiguration.network";
OSStatus status = AuthorizationCreateFromExternalForm([authData bytes], &authRef);
if (status == errAuthorizationSuccess) {
status = AuthorizationCopyRights(authRef, &rights, NULL, kAuthorizationFlagExtendRights, NULL);
}
if (status == errAuthorizationSuccess) {
// This code is granted rights for System Configuration without any prompt
SCPreferencesRef prefs = SCPreferencesCreateWithAuthorization(NULL, (CFStringRef)processName, NULL, authRef);
if (SCPreferencesLock(prefs, YES)) {
SCPreferencesSetComputerName(prefs, (CFStringRef)hostname, kCFStringEncodingUTF8);
SCPreferencesCommitChanges(prefs);
SCPreferencesUnlock(prefs);
}
}
// This code always succeed from helper tool regardless of authorizations from Security.framework
CFStringRef suite = CFSTR("com.company.sample");
CFPreferencesSetValue(CFSTR("myKey"), (__bridge CFStringRef)(myValue), suite, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
CFPreferencesSynchronize(suite, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
// This workflow (lets call it 'C') fails:
// - main app doesn't authorize nor pre-authorize
// - helper tool get rights with no prompt UI
//
// Main app
AuthorizationExternalForm extForm;
OSStatus status = AuthorizationCreate(NULL, NULL, 0, &self->_authRef);
if (status == errAuthorizationSuccess) {
status = AuthorizationMakeExternalForm(self->_authRef, &extForm);
}
if (status == errAuthorizationSuccess) {
authData = [[NSData alloc] initWithBytes:&extForm length:sizeof(extForm)];
}
// Helper tool through XPC
AuthorizationItem oneRight = { NULL, 0, NULL, 0 };
AuthorizationRights rights = { 1, &oneRight };
oneRight.name = "system.services.systemconfiguration.network";
OSStatus status = AuthorizationCreateFromExternalForm([authData bytes], &authRef);
if (status == errAuthorizationSuccess) {
status = AuthorizationCopyRights(authRef, &rights, NULL, kAuthorizationFlagExtendRights, NULL);
// At this stage errAuthorizationInteractionNotAllowed is returned
}
if (status == errAuthorizationSuccess) {
// Going ahead regardless of previous error will prompt an authentication request
SCPreferencesRef prefs = SCPreferencesCreateWithAuthorization(NULL, (CFStringRef)processName, NULL, authRef);
if (SCPreferencesLock(prefs, YES)) {
SCPreferencesSetComputerName(prefs, (CFStringRef)hostname, kCFStringEncodingUTF8);
SCPreferencesCommitChanges(prefs);
SCPreferencesUnlock(prefs);
}
}
// This code always succeed from helper tool regardless of authorizations from Security.framework
CFStringRef suite = CFSTR("com.company.sample");
CFPreferencesSetValue(CFSTR("myKey"), (__bridge CFStringRef)(myValue), suite, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
CFPreferencesSynchronize(suite, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);