• Stars
    star
    175
  • Rank 218,059 (Top 5 %)
  • Language Objective-C++
  • License
    MIT License
  • Created about 5 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A native node module to manage system permissions on macOS.

MIT license PRs Welcome Actions Status

node-mac-permissions

Table of Contents

Overview

$ npm i node-mac-permissions

This native Node.js module allows you to manage an app's access to:

  • Accessibility
  • Calendar
  • Camera
  • Contacts
  • Full Disk Access
  • Input Monitoring
  • Location
  • Microphone
  • Photos
  • Protected Folders
  • Reminders
  • Screen Capture
  • Speech Recognition

If you need to ask for permissions, your app must be allowed to ask for permission :

  • For a Nodejs script/app, you can use a terminal app such as iTerm2 (it won't work on macOS Terminal.app)
  • For an Electron app (or equivalent), you'll have to update Info.plist to include a usage description key like NSMicrophoneUsageDescription for microphone permission.

If you're using macOS 12.3 or newer, you'll need to ensure you have Python installed on your system, as macOS does not bundle it anymore.

API

permissions.getAuthStatus(type)

  • type String - The type of system component to which you are requesting access. Can be one of accessibility, bluetooth, calendar, camera, contacts, full-disk-access, input-monitoring, location, microphone,photos, reminders, screen, or speech-recognition.

Returns String - Can be one of not determined, denied, authorized, or restricted.

Checks the authorization status of the application to access type on macOS.

Return Value Descriptions:

  • not determined - The user has not yet made a choice regarding whether the application may access type data.
  • restricted - The application is not authorized to access type data. The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place.
  • denied - The user explicitly denied access to type data for the application.
  • authorized - The application is authorized to access type data.
  • limited - The application is authorized for limited access to type data. Currently only applicable to the photos type.

Notes:

  • Access to bluetooth will always return a status of authorized prior to macOS 10.15, as the underlying API was not introduced until that version.
  • Access to camera and microphone will always return a status of authorized prior to macOS 10.14, as the underlying API was not introduced until that version.
  • Access to input-monitoring will always return a status of authorized prior to macOS 10.15, as the underlying API was not introduced until that version.
  • Access to music-library will always return a status of authorized prior to macOS 11.0, as the underlying API was not introduced until that version.
  • Access to screen will always return a status of authorized prior to macOS 10.15, as the underlying API was not introduced until that version.
  • Access to speech-recognition will always return a status of authorized prior to macOS 10.15, as the underlying API was not introduced until that version.

Example:

const types = [
  'accessibility',
  'bluetooth',
  'calendar',
  'camera',
  'contacts',
  'full-disk-access',
  'input-monitoring',
  'location',
  'microphone',
  'music-library',
  'photos-add-only',
  'photos-read-write',
  'reminders',
  'speech-recognition',
  'screen',
]

for (const type of types) {
  const status = getAuthStatus(type)
  console.log(`Access to ${type} is ${status}`)
}

permissions.askForContactsAccess()

Returns Promise<String> - Whether or not the request succeeded or failed; can be authorized or denied.

Your app’s Info.plist file must provide a value for the NSContactsUsageDescription key that explains to the user why your app is requesting Contacts access.

<key>NSContactsUsageDescription</key>
<string>Your reason for wanting to access the Contact store</string>

Example:

const { askForContactsAccess } = require('node-mac-permissions')

askForContactsAccess().then(status => {
  console.log(`Access to Contacts is ${status}`)
})

permissions.askForCalendarAccess()

Returns Promise<String> - Whether or not the request succeeded or failed; can be authorized or denied.

Example:

const { askForCalendarAccess } = require('node-mac-permissions')

askForCalendarAccess().then(status => {
  console.log(`Access to Calendar is ${status}`)
})

permissions.askForSpeechRecognitionAccess()

Returns Promise<String> - Whether or not the request succeeded or failed; can be authorized, denied, or restricted.

Checks the authorization status for Speech Recognition access. If the status check returns:

  • not determined - The Speech Recognition access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either authorized or denied.
  • denied - The Security & Privacy System Preferences window is opened with the Speech Recognition privacy key highlighted. On open of the Security & Privacy window, the Promise is resolved as denied.
  • restricted - The Promise is resolved as restricted.

Your app must provide an explanation for its use of Speech Recognition using the NSSpeechRecognitionUsageDescription Info.plist key;

<key>NSSpeechRecognitionUsageDescription</key>
<string>Your reason for wanting to access Speech Recognition</string>

Example:

const { askForSpeechRecognitionAccess } = require('node-mac-permissions')

askForSpeechRecognitionAccess().then(status => {
  console.log(`Access to Speech Recognition is ${status}`)
})

Note: status will be resolved back as authorized prior to macOS 10.15, as the underlying API was not introduced until that version.

permissions.askForRemindersAccess()

Returns Promise<String> - Whether or not the request succeeded or failed; can be authorized or denied.

Example:

const { askForRemindersAccess } = require('node-mac-permissions')

askForRemindersAccess().then(status => {
  console.log(`Access to Reminders is ${status}`)
})

permissions.askForFoldersAccess(folder)

  • type String - The folder to which you are requesting access. Can be one of desktop, documents, or downloads.

Returns Promise<String> - Whether or not the request succeeded or failed; can be authorized or denied.

Example:

const { askForFoldersAccess } = require('node-mac-permissions')

askForFoldersAccess('desktop').then(status => {
  console.log(`Access to Desktop is ${status}`)
})
<key>NSDesktopFolderUsageDescription</key>
<string>Your reason for wanting to access the Desktop folder</string>
<key>NSDocumentsFolderUsageDescription</key>
<string>Your reason for wanting to access the Documents folder</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>Your reason for wanting to access the Downloads folder</string>

permissions.askForFullDiskAccess()

There is no API for programmatically requesting Full Disk Access on macOS at this time, and so calling this method will trigger opening of System Preferences at the Full Disk pane of Security and Privacy.

Example:

const { askForFullDiskAccess } = require('node-mac-permissions')

askForFullDiskAccess()

If you would like your app to pop up a dialog requesting full disk access when your app attempts to access protected resources, you should add the NSSystemAdministrationUsageDescription key to your Info.plist:

<key>NSSystemAdministrationUsageDescription</key>
<string>Your reason for wanting Full Disk Access</string>

permissions.askForCameraAccess()

Returns Promise<String> - Current permission status; can be authorized, denied, or restricted.

Checks the authorization status for camera access. If the status check returns:

  • not determined - The camera access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either authorized or denied.
  • denied - The Security & Privacy System Preferences window is opened with the Camera privacy key highlighted. On open of the Security & Privacy window, the Promise is resolved as denied.
  • restricted - The Promise is resolved as restricted.

Your app must provide an explanation for its use of capture devices using the NSCameraUsageDescription Info.plist key; Calling this method or attempting to start a capture session without a usage description raises an exception.

<key>NSCameraUsageDescription</key>
<string>Your reason for wanting to access the Camera</string>

Note:

  • status will be resolved back as authorized prior to macOS 10.14, as the underlying API was not introduced until that version.

Example:

const { askForCameraAccess } = require('node-mac-permissions')

askForCameraAccess().then(status => {
  console.log(`Access to Camera is ${status}`)
})

permissions.askForInputMonitoringAccess()

Returns Promise<String> - Current permission status; can be authorized or denied.

Checks the authorization status for input monitoring access. If the status check returns:

  • not determined - A dialog will be displayed directing the user to the Security & Privacy System Preferences window , where the user can approve your app to monitor keyboard events in the background. The Promise is resolved as denied.
  • denied - The Security & Privacy System Preferences window is opened with the Input Monitoring privacy key highlighted. On open of the Security & Privacy window, the Promise is resolved as denied.

Note:

  • status will be resolved back as authorized prior to macOS 10.15, as the underlying API was not introduced until that version.

Example:

const { askForInputMonitoringAccess } = require('node-mac-permissions')

askForInputMonitoringAccess().then(status => {
  console.log(`Access to Input Monitoring is ${status}`)
})

permissions.askForMicrophoneAccess()

Returns Promise<String> - Current permission status; can be authorized, denied, or restricted.

Checks the authorization status for microphone access. If the status check returns:

  • not determined - The microphone access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either authorized or denied.
  • denied - The Security & Privacy System Preferences window is opened with the Microphone privacy key highlighted. On open of the Security & Privacy window, the Promise is resolved as denied.
  • restricted - The Promise is resolved as restricted.

Your app must provide an explanation for its use of capture devices using the NSMicrophoneUsageDescription Info.plist key; Calling this method or attempting to start a capture session without a usage description raises an exception.

<key>NSMicrophoneUsageDescription</key>
<string>Your reason for wanting to access the Microphone</string>

Note:

  • status will be resolved back as authorized prior to macOS 10.14, as the underlying API was not introduced until that version.

Example:

const { askForMicrophoneAccess } = require('node-mac-permissions')

askForMicrophoneAccess().then(status => {
  console.log(`Access to Microphone is ${status}`)
})

permissions.askForMusicLibraryAccess()

Returns Promise<String> - Whether or not the request succeeded or failed; can be authorized, denied, or restricted.

  • not determined - The Music Library access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either authorized or denied.
  • denied - The Security & Privacy System Preferences window is opened with the Music Library privacy key highlighted. On open of the Security & Privacy window, the Promise is resolved as denied.
  • restricted - The Promise is resolved as restricted.

Your app must provide an explanation for its use of the music library using the NSAppleMusicUsageDescription Info.plist key.

<key>NSAppleMusicUsageDescription</key>
<string>Your reason for wanting to access the user’s media library.</string>

Note:

  • status will be resolved back as authorized prior to macOS 11.0, as the underlying API was not introduced until that version.

Example:

const { askForMusicLibraryAccess } = require('node-mac-permissions')

askForMusicLibraryAccess().then(status => {
  console.log(`Access to Apple Music Library is ${status}`)
})

permissions.askForPhotosAccess([accessLevel])

  • accessLevel String (optional) - The access level being requested of Photos. Can be either add-only or read-write. Only available on macOS 11 or higher.

Returns Promise<String> - Current permission status; can be authorized, denied, or restricted.

Checks the authorization status for Photos access. If the status check returns:

  • not determined - The Photos access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either authorized or denied.
  • denied - The Security & Privacy System Preferences window is opened with the Photos privacy key highlighted. On open of the Security & Privacy window, the Promise is resolved as denied.
  • restricted - The Promise is resolved as restricted.

Your app must provide an explanation for its use of the photo library using either the NSPhotoLibraryUsageDescription or the NSPhotoLibraryAddUsageDescription Info.plist key.

For requesting add-only access to the user’s photo library:

<key>NSPhotoLibraryAddUsageDescription</key>
<string>Your reason for wanting to access Photos</string>

For requesting read/write access to the user’s photo library:

<key>NSPhotoLibraryUsageDescription</key>
<string>Your reason for wanting to access Photos</string>

Note:

You should add the PHPhotoLibraryPreventAutomaticLimitedAccessAlert key with a Boolean value of YES to your app’s Info.plist file to prevent the system from automatically presenting the limited library selection prompt. See PHAuthorizationStatusLimited for more information.

Example:

const { askForPhotosAccess } = require('node-mac-permissions')

askForPhotosAccess().then(status => {
  console.log(`Access to Photos is ${status}`)
})

permissions.askForScreenCaptureAccess([openPreferences])

  • openPreferences Boolean (optional) - Whether to open System Preferences if the request to authorize Screen Capture fails or is denied by the user.

Calling this method for the first time within an app session will trigger a permission modal. If this modal is denied, there is no API for programmatically requesting Screen Capture on macOS at this time. Calling this method after denial with openPreferences = true will trigger opening of System Preferences at the Screen Capture pane of Security and Privacy.

Example:

const { askForScreenCaptureAccess } = require('node-mac-permissions')

askForScreenCaptureAccess()

permissions.askForAccessibilityAccess()

There is no API for programmatically requesting Accessibility access on macOS at this time, and so calling this method will trigger opening of System Preferences at the Accessibility pane of Security and Privacy.

Example:

const { askForAccessibilityAccess } = require('node-mac-permissions')

askForAccessibilityAccess()

FAQ

Q. I'm seeing an error like the following when using webpack:

App threw an error during load
TypeError: Cannot read property 'indexOf' of undefined
    at Function.getFileName (webpack-internal:///./node_modules/bindings/bindings.js:178:16)

A. This error means that webpack packed this module, which it should not. To fix this, you should configure webpack to use this module externally, e.g explicitly not pack it.


Q. I've authorized access to a particular system component and want to reset it. How do I do that?

A. You can use tccutil to do this!

The tccutil command manages the privacy database, which stores decisions the user has made about whether apps may access personal data.

Examples:

# Reset all app permissions
$ tccutil reset All

# Reset Accessibility access permissions
$ tccutil reset Accessibility

# Reset Reminders access permissions
$ tccutil reset Reminders

# Reset Calendar access permissions
$ tccutil reset Calendar

# Reset Camera access permissions
$ tccutil reset Camera

# Reset Microphone access permissions
$ tccutil reset Microphone

# Reset Photos access permissions
$ tccutil reset Photos

# Reset Screen Capture access permissions
$ tccutil reset ScreenCapture

# Reset Full Disk Access permissions
$ tccutil reset SystemPolicyAllFiles

# Reset Contacts permissions
$ tccutil reset AddressBook

# Reset Desktop folder access
$ tccutil reset SystemPolicyDesktopFolder <bundleID>

# Reset Documents folder access
$ tccutil reset SystemPolicyDocumentsFolder <bundleID>

# Reset Downloads folder access
$ tccutil reset SystemPolicyDownloadsFolder <bundleID>

More Repositories

1

so-you-want-an-internship

for those seeking software engineering internships
1,035
star
2

codebytere.github.io

personal website
JavaScript
512
star
3

node-mac-contacts

Create, read, update, and delete contacts from users' contacts databases on macOS.
Objective-C++
71
star
4

node-mac-swift-addon

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.
Swift
52
star
5

nodemessage

interact with your local iMessage database
JavaScript
42
star
6

dotify

command line dotfile installation and maintenance tool
Shell
33
star
7

node-mac-auth

handle and query for biometric auth on macOS!
Objective-C++
25
star
8

ViziMessage

Visualize your iMessage history and interactions.
TypeScript
21
star
9

electron-font-manager

Create native cross-platform font dialogs!
Objective-C++
21
star
10

talks

talks i've given about things in places
JavaScript
16
star
11

node-mac-userdefaults

A native Node.js module that provides an interface to the user’s defaults database on macOS.
Objective-C++
16
star
12

git-fns

My personal collection of custom git functions.
Shell
15
star
13

emoji-mashup-convert

Convert images from tweets into Slack-worthy emojis.
JavaScript
14
star
14

node-mac-displays

A native Node.js module for enumerating over macOS system display information
JavaScript
13
star
15

sentinel

Integrated CI testing as a service.
JavaScript
7
star
16

electron-prices

Simple Electron application that shows the current price of oil, gold, and silver using the STOOQ API.
HTML
7
star
17

dotfiles

codebytere does dotfiles
Shell
7
star
18

codebytere

6
star
19

chromium-codesearch-extension

Chromium search tools in the Omnibox
JavaScript
6
star
20

node-mac-notch

A native Node.js module to fetch information about the new camera notch at the top of some MacBooks
Objective-C++
6
star
21

electron-build-tools-autocomplete

Fig autocomplete extension for https://github.com/electron/build-tools
TypeScript
5
star
22

native-kde-file-open

open native file dialog on kde plasma desktop
JavaScript
5
star
23

github-issue-parser

parse github issue templates
JavaScript
4
star
24

hackerrank

algo implementation practice
Python
4
star
25

unicode-cli-converter

A CLI tool to automatically convert text between different Unicode styles.
JavaScript
4
star
26

slack-automation

automate signups to a slack team
JavaScript
3
star
27

gist-audit-maker

track and update Node audit log gists
JavaScript
3
star
28

npm-card

JavaScript
3
star
29

sentinel-oss

JavaScript
3
star
30

set-test-platform

Set the platform used for GitHub Actions CI testing
JavaScript
3
star
31

export-to-icns

Create and export .icns files from Sketch to a location of your choosing.
JavaScript
3
star
32

intro-to-git

3
star
33

nodejs-backport-auditor

3
star
34

resume

codebytere makes a resume
TeX
3
star
35

probot-test

2
star
36

node-mac-notify

Objective-C++
2
star
37

governance-check

Check Electron governance membership status and casing.
JavaScript
2
star
38

personal-map

personalized map location visualization app
JavaScript
2
star
39

sentinel-client

Client for the Sentinel Service used to run Electron apps against new versions of Electron in order to see early warning signs for breakages.
JavaScript
2
star
40

node-mac-location

1
star
41

node-backport-auditor

1
star
42

DiningHallSeating

Java
1
star