HomeGuidesReferenceLearn
ArchiveExpo SnackDiscord and ForumsNewsletter

Permissions

Learn about configuring and adding permissions in an app config file.


When developing a native app that requires access to potentially sensitive information on a user's device, such as their location or contacts, the app must request the user's permission first. For example, to access the user's media library, the app will need to run MediaLibrary.requestPermissionsAsync().

Permissions in standalone and development builds require native build-time configuration before they can be requested using runtime JavaScript code. This is not required when testing projects in the Expo Go app.

If you don't configure or explain the native permissions properly it may result in your app getting rejected or pulled from the stores.

Android

Permissions are configured with the expo.android.permissions and expo.android.blockedPermissions keys in your app config (app.json, app.config.js).

Most permissions are added automatically by libraries that you use in your app either with config plugins or with a package-level AndroidManifest.xml, so you won't often need to use android.permissions to add additional permissions.

The only way to remove permissions that are added by package-level AndroidManifest.xml files is to block them with the expo.android.blockedPermissions property. To do this, specify the full permission name; for example, if you want to remove the audio recording permissions added by expo-av:

app.json
{
  "expo": {
    "android": {
      "blockedPermissions": ["android.permission.RECORD_AUDIO"]
    }
  }
}
Are you using this library in a bare React Native app?

Modify AndroidManifest.xml to exclude specific permissions: add the tools:node="remove" attribute to a <use-permission> tag to ensure it is removed, even if it's included in a library AndroidManifest.xml.

<manifest xmlns:tools="http://schemas.android.com/tools">
  <uses-permission tools:node="remove" android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

You have to define the xmlns:tools attribute on <manifest> before you can use the tools:node attribute on permissions.

iOS

Your iOS app can ask for system permissions from the user. For example, to use the device's camera, or access photos, Apple requires an explanation for how your app makes use of that data. Most packages will automatically provide a boilerplate reason for a given permission with config plugins. These default messages will most likely need to be tailored to your specific use case in order for your app to be accepted by the App Store.

To set permission messages, use the expo.ios.infoPlist key in your app config (app.json, app.config.js), for example:

app.json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "This app uses the camera to scan barcodes on event tickets."
      }
    }
  }
}

Many of these properties are also directly configurable using the config plugin properties associated with the library that adds them. For example, with expo-media-library you can configure photo permission messages like this:

app.json
{
  "expo": {
    "plugins": [
      [
        "expo-media-library",
        {
          "photosPermission": "Allow $(PRODUCT_NAME) to access your photos.",
          "savePhotosPermission": "Allow $(PRODUCT_NAME) to save photos."
        }
      ]
    ]
  }
}
Are you using this library in a bare React Native app?

Add and modify the permission message values in Info.plist file directly. We recommend doing this directly in Xcode for autocompletion.

Web

On the web, permissions like the Camera and Location can only be requested from a secure context. For example, using https:// or http://localhost. This limitation is similar to Android's manifest permissions and iOS's infoPlist usage messages and enforced to increase privacy.

Resetting permissions

Often you want to be able to test what happens when a user rejects permissions, to ensure your app reacts gracefully. An operating-system level restriction on both Android and iOS prohibits an app from asking for the same permission more than once (you can imagine how this could be annoying for the user to be repeatedly prompted for permissions after rejecting them). To test different flows involving permissions in development, you may need to uninstall and reinstall the native app.

When testing in Expo Go, you can delete the app and reinstall it by running npx expo start and pressing i or a in the Expo CLI Terminal UI.