# Location permission distinguishes between always/when-in-use/never

- **Pattern:** `ab-001897` (`mobile-permissions-privacy.permission-requests.location-granularity`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001897
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001897)

## Why it matters

Requesting always-on background location when only foreground location is needed is one of the most common grounds for App Store rejection and a clear GDPR Art. 5(1)(c) data-minimisation violation. Apple's location always permission (`NSLocationAlwaysAndWhenInUseUsageDescription`) triggers a two-step authorization flow that explicitly warns users their location is tracked in the background — users decline this at far higher rates than when-in-use. On Android 10+, background location requires an additional `ACCESS_BACKGROUND_LOCATION` permission that triggers a separate, more alarming system dialog. Apps requesting always-on location for features like map display or restaurant search — where when-in-use is sufficient — face Google Play policy strikes and user complaints.

## Severity rationale

High because requesting always-on location for features that only need foreground location violates GDPR Art. 5(1)(c), triggers heightened Apple and Google review scrutiny, and causes significantly higher permission denial rates.

## Remediation

Default to `LOCATION_WHEN_IN_USE` for all location features. Only escalate to `LOCATION_ALWAYS` when a documented background feature (fitness tracking, delivery tracking, geofencing) specifically requires it.

```typescript
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions'

// Default: request when-in-use
const foregroundResult = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE)

// Only if a background feature genuinely exists:
if (userEnablesBackgroundTracking) {
  const backgroundResult = await request(PERMISSIONS.IOS.LOCATION_ALWAYS)
}
```

In `app.json`, only add `NSLocationAlwaysAndWhenInUseUsageDescription` if your app has an active background location feature. Remove the key entirely if the app only needs foreground location — its presence alone triggers additional scrutiny during App Store review.

## Detection

- **ID:** `location-granularity`
- **Severity:** `high`
- **What to look for:** Count all location permission request calls. For each, quote the actual permission constant used (e.g., `PERMISSIONS.IOS.LOCATION_WHEN_IN_USE` vs `PERMISSIONS.IOS.LOCATION_ALWAYS`). Check iOS `Info.plist` for `NSLocationWhenInUseUsageDescription` vs `NSLocationAlwaysAndWhenInUseUsageDescription`. On Android, check `ACCESS_FINE_LOCATION` vs background location.
- **Pass criteria:** If the app needs location, it requests at minimum `when-in-use` and only escalates to `always` if genuinely needed for background location features. At least 1 location permission request uses the granular when-in-use API. User is not forced into always-on location.
- **Fail criteria:** App requests always-on location for features that only need when-in-use location. OR app provides no distinction between permission levels. Do NOT pass when the app requests `LOCATION_ALWAYS` but has no background location feature.
- **Skip (N/A) when:** App does not use location (no location permission requests or declarations found).
- **Detail on fail:** Quote the actual permission constant. `"App requests location 'always' permission but primary feature (map display) only needs when-in-use access"` or `"Location permission offers no distinction between levels — user cannot choose when-in-use only"`
- **Remediation:** Minimize location access scope. For most features, when-in-use location is sufficient. Only request always-on location if your app genuinely needs background location (e.g., fitness tracking, delivery tracking):

  ```typescript
  // iOS: Distinguish permission levels
  const iosConfig = {
    NSLocationWhenInUseUsageDescription: 'We use your location to show nearby content while the app is open',
    NSLocationAlwaysAndWhenInUseUsageDescription: 'We need background location for fitness tracking'
  }

  // Request when-in-use by default
  const result = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE)
  ```

---

## External references

- cwe CWE-272
- gdpr Art. 5(1)(c)
- external apple-location-always — https://developer.apple.com/documentation/corelocation/requesting_authorization_for_location_services

Taxons: privacy-consent, access-control

HTML version: https://auditbuffet.com/patterns/ab-001897
