16 Replies
      Latest reply on Feb 19, 2016 8:45 AM by frios
      GeorgeH Level 1 Level 1 (0 points)

        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?

        • Re: How can I avoid repeating account permission requests in El Capitan?
          eskimo Apple Staff Apple Staff (11,835 points)

          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"

          • Re: How can I avoid repeating account permission requests in El Capitan?
            iQser_Developer Level 1 Level 1 (0 points)

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

            • Re: How can I avoid repeating account permission requests in El Capitan?
              Dejal Level 1 Level 1 (0 points)

              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.

              • Re: How can I avoid repeating account permission requests in El Capitan?
                trauts Level 1 Level 1 (0 points)

                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.

                  • Re: How can I avoid repeating account permission requests in El Capitan?
                    svelur Level 1 Level 1 (0 points)

                    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?

                  • Re: How can I avoid repeating account permission requests in El Capitan?
                    spicyapps Level 1 Level 1 (0 points)

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

                      • Re: How can I avoid repeating account permission requests in El Capitan?
                        floschliep Level 1 Level 1 (0 points)

                        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).

                          • Re: How can I avoid repeating account permission requests in El Capitan?
                            frios Level 1 Level 1 (0 points)

                            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)
                                            }
                                        }
                                    })
                                }
                            }
                            
                            • Re: How can I avoid repeating account permission requests in El Capitan?
                              floschliep Level 1 Level 1 (0 points)

                              I found the reason my code only worked in some cases. Apparently the account type can be different on different accounts (even on the same Mac). To get the desired account type, just get the value of Z_PK from the ZACCOUNTTYPE table where the ZIDENTIFIER matches your desired network, e.g. "com.apple.twitter", "com.apple.facebook" or "com.apple.sinaweibo". Then use the value for the insertion into the ZACCOUNTTYPE table.