How can I avoid repeating account permission requests in El Capitan?

On El Capitan my app shows repeating popups for account permission requests like calender or Twitter account access. I can reproduce this behaviour only on El Capitan but not on Yosemite or Mavericks. The permission does not appear in the security system settings either. Has the API changed for El Capitan? Or is this a Beta Bug?

Replies

Can you post a screen shot of one of these dialogs?

IMPORTANT DevForums doesn’t let you post images, so you’ll have to put the screen shot elsewhere and post a link. That will, in turn, require moderator approval, although that won’t be a problem. We are well aware of how clumsy this is (r. 22028729). Sorry.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I have the same urgent problem and posted a similar message on this board. I found out, that the TCC database update fails.

Hello Eskimo,


First the app promts the permission request, that is provided by the operation system:

https://www.dropbox.com/s/il6yoxe45nu4euq/Bildschirmfoto%202015-10-02%20um%2022.01.04.png?dl=0


Then the tcc database is not updated, although the user confirms the permission:

https://www.dropbox.com/s/2end0tdmbdpccll/Bildschirmfoto%202015-10-02%20um%2022.01.32.png?dl=0


The system log show the following entry:

... Access to Twitter Accounts not granted: Setting TCC failed.

Thanks for the screen shots. As iQser_Developer suggested, these are TCC (transparency, consent, control) dialogs.

Is this behaviour specific to your app? Do other apps on the system have the same problem?

Have you tried reproducing this on a clean install of 10.11?

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello Eskimo,


Thanks for your response. It is an urgent problem, because the app is offered in the AppStore.


Yes, I can reproduce the problem with a simple text app, that I have written. An I have checked the behaviour on a fresh insalled OS X 10.11 release and the current OS X 10.11.1 beta release. The app works on my current developer machine, because the permission was set before the El Capitan ipdate.


Here is the link to the zipped test app:

https://www.dropbox.com/s/mk3dy0gnc8otfqw/TwitterAccountCheck.zip?dl=0


And here is the link to the zipped test project:

https://www.dropbox.com/s/2wku3iznokqlp2j/TwitterAccountCheckProject.zip?dl=0


Herre is the relevant code snipped:


-(IBAction)checkTwitterAccount:(id)sender {
    _accountStore = [[ACAccountStore alloc] init];
  
    ACAccountType *accountType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
  
    [_accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
        if (granted) {
            _accounts = [_accountStore accountsWithAccountType:accountType];
        } else {
            NSLog(@"Access to Twitter Accounts not granted: %@", error.localizedDescription);
        }
    }];
}


The behaviour is the same: The permission dialog pops up, the user confirms the permission and the update of the tcc database fails.


Maybe El Capitan needs an extended application plist like for URL requests?

Yes, I can reproduce the problem with a simple text app, that I have written. [And] I have checked the behaviour on a fresh insalled OS X 10.11 release and the current OS X 10.11.1 beta release.

I don’t know what’s going on here, sorry, but if you can reproduce it with a simple test app on a clean install of 10.11 then that’s clearly a bug and you should file it as such.

Once you’ve filed you bug, please post the number here.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

We have filed the bug with the ID 22869928. Hopefully, it will be fixed soon or we will find a workaround for the current release.

I've encountered this issue too, for a new app. I can't get access to Twitter. Any solution yet?


Edit: duplicated the bug report as #23114308, and submitted a DTS incident to see if there's a workaround.

I'm also suffering this issue and logged it on 26th September - bug 22869649


If my users were previously authorised (i.e. OS upgrade or migrated across), then it's all fine, but if the TCC database is new then no go.

I've run in to the same issue too. This seems to happen for Twitter and Facebook when requesting access to ACAccountStore using the method,

requestAccessToAccountsWithType:(ACAccountType *)accountType

options:(NSDictionary *)options

completion:(ACAccountStoreRequestAccessCompletionHandler)completion


I get the "Setting TCC failed" error only on Mac OS El Capitan. The same code works just fine on Mac OS Yosemite.

We have sandbox enabled in our Mac App.


Has anyone found a workaround for this issue?

Same issue here exactly as GeorgeH described. Has anyone found a workaround for this issue?

There's a Core Data database in ~/Library/Accounts which is responsible for managing account access.

If your app is not sandboxed (I created an separate helper app), it is possible to manually modify the database using sqlite3.

- (void)enableForNetwork:(NSInteger)network {
  NSURL *libraryURL = [[NSFileManager defaultManager] URLForDirectory:NSLibraryDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
  NSURL *databaseURL = [libraryURL URLByAppendingPathComponent:@"Accounts/Accounts3.sqlite"];

  NSString *permissions = (network == 12) ? @"public_profile" : @"";
  NSString *command = [NSString stringWithFormat:@"sqlite3 %@ \"insert into ZAUTHORIZATION (Z_ENT, Z_OPT, ZACCOUNTTYPE, ZBUNDLEID, ZGRANTEDPERMISSIONS) values (5, 1, %li, 'BUNDLE_ID_HERE', '%@')\"", databaseURL.path, network, permissions];

  NSTask *task = [NSTask new];
  task.launchPath = @"/bin/sh";
  task.arguments = @[ @"-c", command ];
  [task launch];
}

I found that account type 10 is Twitter, 12 is Facebook and 8 is Sina Weibo. Facebook requires a comma-separated list of permissions, the others don't.

This solution worked for me with my existing OS X user accounts (on two different machines). For testing purposes I created a blank user and the insertion worked, but my app didn't show up in the system preferences (and didn't get access though it is in the database).

This problem is still occurring in 10.11.3. As requested by DTS, I've just submitted a new bug report for it: #24442853.


This is a critical bug that is blocking me from releasing a Twitter integration feature in a new app, and affecting users of an existing app.

Bottom line is Apple needs to fix this - my bug has just been closed and marked as a duplicate of yours after I updated it to say the problem still happens in 10.11.3. (Apple says it can't reproduce it - really????).


I have no idea what Apple is doing here, but this is getting truly ridiculous!

Thanks for the code. i tried this for Twitter, the record was created in the database, but it did not help my situation. I still get

requestAccessToAccountsWithType

returning granted = false and so my code doesn't execute. If I try to bypass the test for granted, then the call to

account.accountsWithAccountType(accountType)

returns nil


Has anyone had any sucess finding a workaround for this problem on El Capitan?


Here is my code:


    func loadTweets() {
        let account = ACAccountStore()
        let accountType = account.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
        account.requestAccessToAccountsWithType(accountType, options: nil, completion: {granted, error in
            if granted {
                let arrayOfAccounts = account.accountsWithAccountType(accountType)
                if arrayOfAccounts.count > 0 {
                    let twitterAccount = arrayOfAccounts[0]
                    let urlString = "https://api.twitter.com/1.1/search/tweets.json"
                    let requestURL = NSURL (string: urlString)
                    let parameters = ["count": "20", "result_type":"recent", "q":"%23PowerShell%20OR%20PowerShell%20OR%20%23PrimalScript%20OR%20PrimalScript%20OR%20%40SAPIENTech%20OR%20%23PowerShellStudio%20OR%20PowerShellStudio%20OR%20%23iPowerShell%20OR%20iPowerShell"]
                    let postRequest = SLRequest.init(forServiceType: SLServiceTypeTwitter, requestMethod: SLRequestMethod.GET, URL: requestURL, parameters: parameters)
                    postRequest.account = twitterAccount as! ACAccount
                    postRequest.performRequestWithHandler({(responseData : NSData!, urlResponse: NSHTTPURLResponse!, error: NSError!) -> Void in
                        do {
                            let JSONData = try NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.MutableLeaves) as! NSDictionary
                            self.results = NSArray(array: JSONData.objectForKey("statuses") as! NSArray!)
                            if self.results.count != 0 {
                                for aResult in self.results {
                                    let aUser = aResult["user"] as! NSDictionary
                                    let imageURLString  = aUser["profile_image_url"]
                                    let secureImageURLString = imageURLString!.stringByReplacingOccurrencesOfString ("http:", withString: "https:")
                                    let imageURL = NSURL (string: secureImageURLString)
                                    let imageData = NSData (contentsOfURL: imageURL!)
                                    if let theImage = NSImage (data: imageData!) {
                                        self.userImages.append(theImage)
                                    } else {
                                        self.userImages.append(NSImage (named: "icon")!)
                                    }
                                    dispatch_async(dispatch_get_main_queue()) {
                                        //update UI
                                        self.collectionView.reloadData()
                                    }
                                }
                            }
                        } catch {
                            dispatch_async(dispatch_get_main_queue()) {
                                Utils.errorAlert (self.view.window!, errorMessage: "Error", errorDescription: "No tweets.")
                            }
                        }
                    })
                }
            } else {
                dispatch_async(dispatch_get_main_queue()) {
                    Utils.errorAlert (self.view.window!, errorMessage: "Error", errorDescription: "Account access not granted.")
                    print(error)
                }
            }
        })
    }
}