Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Defining Custom App Permissions

Tech 1

This document describes how app developers can use Android's security features to define their own permissions. By defining custom permissions, apps can share their resources and functionality with other apps. For more details, see the Permissions Overview.

Background

Android is a permission-separated operating system where each app runs with a different system identity (Linux user ID and group ID). Parts of the system are also separated into different identities. Thus, Linux can isolate apps from each other and from the system.

Apps can define permissions that other apps can request to access their functionality. They can also define permissions that are automatically granted to any app signed with the same certificate.

App Signing

All APKs must be signed with a certificate whose private key is held by the developer. This certificate identifies the app creator. The certificate does not need to be signed by a certificate authority; Android apps can (and commonly do) use self-signed certificates. Certificates in Android are used to distinguish app creators. This allows the system to grant or deny signature-level permissions and to grant or deny requests for the same Linux identity as another app.

User IDs and File Access

During installation, Android assigns each package a distinct Linux user ID. This identity remains constant for the duration of the package's life on that device. The same package may have a different UID on another device; what matters is that each package has a unique UID on a given device.

Since security is enforced at the process level, code from two packages cannot normally run in the same process because they would need to run as different Linux users. You can use the sharedUserId attribute in the AndroidManifest.xml <manifest> tag to assign the same user ID to multiple packages. When you do this, the system treats them as the same app with the same user ID and file permissions for security purposes. However, only two apps signed with the same certificate (and requesting the same sharedUserId) can obtain the same user ID.

All data stored by an app is assigned that app's user ID, and other packages cannot normally access that data.

For more information on Android's security model, see the Android Security Overview.

Defining and Enforcing Permissions

To enforce your own permissions, you must first declare them in your AndroidManifest.xml using one or more <permission> elements.

For example, an app that wants to control who can start its Activity can declare a permission for that operation as follows:

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <permission
        android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
        android:label="@string/permlab_deadlyActivity"
        android:description="@string/permdesc_deadlyActivity"
        android:permissionGroup="android.permission-group.COST_MONEY"
        android:protectionLevel="dangerous" />
    ...
</manifest>

Note: The system does not allow multiple packages to declare a permission with the same name unless all packages are signed with the same certificate. If a package declares a permission, the system will not allow the user to install other packages with the same permission name unless those packages are signed with the same certificate as the first package. When naming custom permissions, we recommend using reverse domain name notation to avoid naming conflicts, e.g., com.example.myapp.ENGAGE_HYPERSPACE.

The protectionLevel attribute is required and tells the system how to inform the user about which apps are requesting or can obtain the permission, as described in the linked documentation.

The android:permissionGroup attribute is optional and only helps the system display permissions to the user. In most cases, you should set this to a standard system group (listed in android.Manifest.permission_group), though you can also define your own group. Using existing groups is better because it simplifies the permission UI for the user.

You must provide a label and description for the permission. These are string resources that users see when viewing a permission list (android:label) or details about a single permission (android:description). The label should be short and describe the key functionality protected by the permission. The description should consist of a few sentences describing what the permission allows the holder to do. We typically use a two-sentence description: the first sentence describes the permission; the second reminds the user what kinds of issues might occur if the permission is granted to an app.

Here's an example of the label and description for the CALL_PHONE permission:

<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call
    phone numbers without your intervention. Malicious apps may
    cause unexpected calls on your phone bill. Note that this does not
    allow the app to call emergency numbers.</string>

Creating Permission Groups

As shown in the previous section, you can use the android:permissionGroup attribute to help the system describe permissions to the user. In most cases, it's good to set this attribute to a standard system group (listed in android.Manifest.permission_group), but you can also define your own group using a <permission-group> element.

The <permission-group> element defines a label for a group of permissions, including those declared in the manifest via <permission> and those declared elsewhere. This only affects how the permissions are grouped when displayed to the user. The <permission-group> element does not specify which permissions belong to the group; it only provides a name for the group.

Assigning the group name to the permissionGroup attribute of a <permission> element places the permission in that group.

A <permission-tree> element declares a namespace for a set of permissions defined in code.

Custom Permission Recommendations

Apps can define their own custom permissions and can also request custom permissions from other apps by defining <uses-permission> elements. However, you should carefully evaluate whether your app needs to do this.

  • If you are designing a suite of apps that expose functionality to each other, try to design them so that each permission is defined only once. This is necessary if not all apps are signed with the same certificate. Even if all apps are signed with the same certificate, defining each permission only once is best practice.
  • If the functionality is only available to apps signed with the same certificate as the app providing it, you can use a signature check instead of defining a custom permission. If one of your apps makes a request to another, the receiving app checks whether both are signed with the same certificate and only honors the request if they are.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.