macOS get SSID changes?

I've had a little personal utility running for several versions of macOS that uses

let client = CWWiFiClient.shared()
if let ssid_name = client.interface()?.ssid() 

to get the current SSID name and prints it (along with a bunch of other active network details.

With the most recent Sonoma Beta 2 and Xcode beta 2, this always returns nil. Doing the same thing in a playground works as expected.
Is this a purposeful change or a bug I should file?

Answered by DTS Engineer in 758611022

I asked the CoreWLAN folks about this, and it looks like this was a deliberate change: Accessing the ssid property now requires the location privilege (r. 108641482).

We called this out in the header doc comments, where <CoreWLAN/CWInterface.h> now says:

SSID information is not available unless Location Services is enabled and the user has authorized the calling app to use location services.

I’d appreciate you filing a bug requested that the official docs be updated with that info.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I've had a little personal utility

Is this a command-line tool? Or an app?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Same issue here, my app uses CWWiFiClient.shared() to retrieve SSID name and it currently returns nil on macOS Sonoma beta 2

Putting this in a command line macOS app and a playground yield different results. The app prints unavailable, the playground prints the SSID name.

import Foundation
import CoreWLAN

let client = CWWiFiClient.shared()
let ssid_name = client.interface()?.ssid() ?? "unavailable"

print(ssid_name)

Same issue still here in Sonoma beta3.

I asked the CoreWLAN folks about this, and it looks like this was a deliberate change: Accessing the ssid property now requires the location privilege (r. 108641482).

We called this out in the header doc comments, where <CoreWLAN/CWInterface.h> now says:

SSID information is not available unless Location Services is enabled and the user has authorized the calling app to use location services.

I’d appreciate you filing a bug requested that the official docs be updated with that info.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Is this problem solved? After I tried to get the location permission, it also return nil.

getting null even after adding the "com.apple.security.personal-information.location" entitlement, is there anything else to add in the entitlements. I have the below <key>com.apple.security.personal-information.location</key> <true/> <key>com.apple.security.network.client</key> <true/>

but still no luck.

Yes, I got it working with Location Services. I added a file for a LocationController and then in my main view added an onAppear(perform: { if LocationServices.shared.locationManager.authorizationStatus == .authorizedAlways { LocationServices.shared.userLocationDelegate = self } else { LocationServices.shared.locationManager.requestAlwaysAuthorization() } }) My code is up at https://github.com/ehemmete/NetworkView

Im still so confused on how to simply get a network SSID for a background application running DotNet Core on macOS now. Before, I could just call CWifiClient.networkInterfaces, now the value returns null. What steps do I need to take to enable this application which is signed with its own embedded provisioning profile? Do I detect if authorization is required, then request the prompt?

#if _UNIX

using System; using CoreWlan; using CoreLocation; //??? using ThreadNetwork;

namespace Amazon.PersistUserService.Controllers.NetworkController.NetworkChangeManager;

public class MacNetworkChangeManager: INetworkChangeManager { private readonly CoreWlan.CWWiFiClient networkClient; private CLLocationManager locationManager; //???

public MacNetworkChangeManager()
{
    networkClient = CWWiFiClient.SharedWiFiClient;
}

public string? GetConnectedSsid()
{
    //What do I add here to request authorization?
    
    foreach (var @interface in networkClient.Interfaces) // you can have multiple wifi devices connected at once
    {
        return @interface.Ssid;
    }
    return null;
}

} #endif

how to simply get a network SSID for a background application

What do you mean by “background application”? How is your program started?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hello @eskimo , my program is written in DotNet 6, and I use Xamarin.Mac SDK: https://learn.microsoft.com/en-us/dotnet/api/?view=xamarin-mac-sdk-14 Before as in my code, i was able to get the connected SSID without any issue. Now it returns null. Do I need to add an entitlement and prompt the user using Core Location? I'm not sure how to use it with Xamarin.Mac SDK in a dotnet application from the instructions here: https://developer.apple.com/documentation/corelocation/configuring_your_app_to_use_location_services

A launchd agent should be able to get this info. Is the agent associated with a standard GUI app? For example, you might be installing the agent from that app using SMAppService? Or is the agent a standalone thing?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How do I use NSLocationAlwaysAndWhenInUseUsageDescription on macOS so that users know why I am requesting location?

Sorry, one more issue @eskimo : https://learn.microsoft.com/en-us/dotnet/api/corelocation.cllocationmanager?view=xamarin-ios-sdk-12 Corelocation API is only available for xamarin.ios is there an equivalent for macOS to use? I used @ehemmete approach to get my GUI to enable location information, but the launch agent is not able to fetch location information

The agent is associated with a standard GUI app

Cool. How do you install the the agent? SMAppService? Or something else?

CoreLocation API is only available for xamarin.ios is there an equivalent for macOS to use?

Core Location is supported on all our platforms. See the pills at the top of its main doc page. If that’s not reflected in your third-party tooling, I recommend that you raise this via its support channel.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi @eskimo Because we needed compatibility with macOS 12, we were unable to onboard our launch agents with SMAppService Our login item is instantiated with SMLoginItemSetEnabled, but our launch agent plist files are populated in the post install script of our pkg: /bin/launchctl bootstrap gui/"$CURRENT_UID" "/Library/LaunchAgents/agentName.plist" which loads the agent with the appropriate configs. Essentially what's happening right now is that I codesign the .app with the location entitlement, but unless i explicitly click on the app and it runs in the foreground the locationmanager.requestAlwaysAuthorization() never prompts. Would love to setup a quick consultation with you if you are available. "ajdali" + "@" + "amazon.com"

Perhaps, the location string in the info.plist is required in order to access the protected resource?

As everyone else I am too unable to get the SSID information with Sonoma but it is still not clear to me if when using the location service it should finally work.

ajdali wrote:

Would love to setup a quick consultation

To be clear, DevForums is not a formal support channel. See tip 3 in Quinn’s Top Ten DevForums Tips.

Because we needed compatibility with macOS 12, we were unable to onboard our launch agents with SMAppService

OK, but you don’t have this problem on macOS 12 either. So, installing your agent using SMAppService resolves this problem, you have a path to a solution (use SMAppService where it’s available, use SMLoginItemSetEnabled on older systems). I recommend that you try that.

Our login item is instantiated with SMLoginItemSetEnabled, but our launch agent plist files are populated in the post install script of our pkg: /bin/launchctl bootstrap gui/"$CURRENT_UID" "/Library/LaunchAgents/agentName.plist" which loads the agent with the appropriate configs.

OK, mixing SMLoginItemSetEnabled and a launchctl is less than ideal. However, that doesn’t really matter if you can use SMAppService moving forward. You can just disable this stuff on newer systems and remove it when you drop macOS 12 support.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@eskimo Can you please confirm if just using the SMAppService will resolve the problem of obtaining SSID information? Or do I need some additional entitlements or need to make adjustments to Location Services?

I am currently experiencing the same issue with obtaining SSID. Here is the code example I use:

CWWiFiClient *client = [CWWiFiClient sharedWiFiClient];
CWInterface *interface = [client interface];
NSString *ssid = [interface ssid];

It returns nil on Sonoma.
This code is part of a LaunchDaemon with a plist file located in /Library/LaunchDaemons, which was registered using SMJobBless(). I understand that this method is now considered obsolete, but it was working fine before the Sonoma release.

Thanks in advance.

Update: Installing a daemon using SMAppService does not fix the issue (even with 'com.apple.security.personal-information.location' in entitlements).
Does anybody have a clear solution on how to make it work for background daemons on Sonoma?

Can you please confirm if just using the SMAppService will resolve the problem of obtaining SSID information?

SMAppService will let you install an agent and an agent can get the Core Location privilege, but it’s not a solution to this overall problem.

For more on this, see my response here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

This seems like a really breaking change. To say that any application configured as a launch agent or daemon cannot simply get the connected SSID then what should we expect in the future? How can one single SSID value fingerprint a user or compromise their location? Seems like apple is going down the deep end with all these privacy controls. I'm truly baffled how they connected the dots from a user's connected SSID and their location.

It's still not clear how to request Location Services permissions for a non-UI app.

@eskimo I would greatly appreciate it if you could clarify a few points:

  1. There is no way to obtain location permissions for non-UI apps, like simple console apps. Is that correct?

  2. As far as I understood your previous comments, LaunchAgent installed by SMAppService() can obtain Location permissions and retrieve SSID info. What are the requirements for this? Should SMAppService() be called by the UI app (let's call it the 'installer'), or can a console app also invoke SMAppService()? It's also unclear which app should possess the com.apple.security.personal-information.location entitlement and the NSLocationAlwaysUsageDescription definition: the 'installer' or the LaunchAgent?

Thanks in advance.

ajdali wrote:

To say that any application configured as a launch agent or daemon cannot simply get the connected SSID

Hmmm, that’s not what I said. Rather, there’s a agent vs daemon split here:

  • I think it’s feasible for a launchd agent to get the location privilege and thus get access to this info. See below.

  • In contrast, as things currently stand I don’t think it’s feasible for a daemon to do this.

then what should we expect in the future?

Realistically, more of the same |-: There was a great quote about this way back at WWDC 2017, which I highlighted in a footnote on this post.


stenya wrote:

There is no way to obtain location permissions for non-UI apps, like simple console apps. Is that correct?

There’s no way to answer that as written because the term “console app” isn’t one I use. You’re talking about a Mach-O executable here, but its behaviour depends on the context in which it’s run. For example, whether it’s:

  • Run by the user in Terminal

  • Run by the user over SSH

  • Run by an app as a ‘helper tool’

  • Run by launchd as an agent

  • Run by launchd as a daemon

As far as I understood your previous comments, LaunchAgent installed by SMAppService can obtain Location permissions and retrieve SSID info. What are the requirements for this?

Lemme explain the backstory here…

Most privileges like this are managed by TCC and it has a good understanding of the concept of responsible code [1]. So, if your launchd agent has a GUI app as its responsible code then granting the TCC privilege to the GUI app also grants it to your agent. I’ve tested this numerous times and it works reasonably well.

The tricky part here is Core Location, which doesn’t use the standard TCC infrastructure to manage its privilege [2]. I’ve not actually sat down to test the launchd agent to responsible GUI app path for the location privilege.

If you want to try this out, create a GUI app that acquires both a standard TCC privilege, like Input Monitoring, and the location privilege. Then use that to install an agent and see if it ‘inherits’ those privileges from the responsible GUI app. I know that’ll work for Input Monitoring [3]. Does it work for the location privilege?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] I define that term in On File System Permissions.

[2] Because a) Core Location needs more flexibility than most TCC-managed privileges, and b) Core Location was one of the first privileges like this.

[3] Ah, um, it worked the last time I tested it, on macOS 13. I haven’t tried this on macOS 14 yet. AFAIK nothing has changed there but… *shrug*

macOS get SSID changes?
 
 
Q