63

I have two applications.

One is declaring permission and having single Activity:

Part of AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:permission="your.namespace.permission.TEST" >
    <activity
        android:name=".DeclaringPermissionActivity"
        android:label="@string/app_name" >

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <intent-filter> 
         <action android:name="android.intent.action.VIEW" /> 
         <category android:name="android.intent.category.DEFAULT" /> 
         <category android:name="android.intent.category.BROWSABLE" /> 
         <data android:scheme="myapp"
             android:host="myapp.mycompany.com" /> 
        </intent-filter> 
    </activity>
</application>

The second declares that is uses permission

Part of AndroidManifest.xml

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="your.namespace.permission.TEST" />

<application

Part of Activity:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("myapp://myapp.mycompany.com/index")));
}

I'm installing the application declaring permission, then I run the second application.

In a result I get security exception:

 01-11 09:46:55.249: E/AndroidRuntime(347): java.lang.RuntimeException: Unable to start activity ComponentInfo{your.namespace2/your.namespace2.UsingPErmissionActivity}: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.VIEW dat=myapp://myapp.mycompany.com/index cmp=your.namespace/.DeclaringPermissionActivity } from ProcessRecord{407842c0 347:your.namespace2/10082} (pid=347, uid=10082) requires your.namespace.permission.TEST
Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
pixel
  • 24,905
  • 36
  • 149
  • 251
  • I just want to point out this vulneralbility: http://commonsware.com/blog/2014/02/12/vulnerabilities-custom-permissions.html – Tobrun Sep 05 '14 at 11:08
  • Concerning the vulnerability comment above, note the changes in Android 5.0 that address this issue: http://developer.android.com/about/versions/android-5.0-changes.html#custom_permissions – Nonos Mar 17 '15 at 14:06
  • https://developer.android.com/guide/topics/permissions/defining – k4dima Jun 20 '19 at 13:03

5 Answers5

108

I created a test code you can use it and test your permissions. There are two applications PermissionTestClient which declares permission and protects its activity with this permission. Here is its manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.testpackage.permissiontestclient"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <permission android:name="com.testpackage.mypermission" android:label="my_permission" android:protectionLevel="dangerous"></permission>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:permission="com.testpackage.mypermission"
            android:name=".PermissionTestClientActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter >
                <action android:name="com.testpackage.permissiontestclient.MyAction" />
                <category android:name="android.intent.category.DEFAULT" />                
            </intent-filter>
        </activity>
    </application>

</manifest>

There is nothing special in Activity file so I will not show it here.

PermissionTestServer application calls activity from PermissionTestClient. Here is its manifest file:

<?xml version="1.0" encoding="utf-8"?>

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="com.testpackage.mypermission"/>

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:name=".PermissionTestServerActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

And Activity:

package com.testpackage.permissiontestserver;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class PermissionTestServerActivity extends Activity {
    private static final String TAG = "PermissionTestServerActivity";

    /** Called when the activity is first created. */
    Button btnTest;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button) findViewById(R.id.btnTest);
        btnTest.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Log.d(TAG, "Button pressed!");
                Intent in = new Intent();
                in.setAction("com.testpackage.permissiontestclient.MyAction");
                in.addCategory("android.intent.category.DEFAULT");
                startActivity(in);
            }
        });
    }
}

To test it just remove uses-permission from Server application. You'll get security violation error.

Yury
  • 20,618
  • 7
  • 58
  • 86
  • 2
    Thanks, my mistake was to put `permission` attribute only to `` element. – pixel Jan 11 '12 at 09:56
  • 1
    This does not work for me when I use android:protectionLevel="signature" in the PermissionTestClient, I use the permission on that apps launcher and get: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=my.package.foobar/.DashboardActivity } from null (pid=4070, uid=2000) requires my.custom.permission.ACCESS_ACTIVITY - so the app fails to launch it's own Activity 0_o – fr1550n Jun 27 '13 at 08:54
  • 4
    Signature level of permission means that your client and server should be signed with the same certificate. Try to launch the code using dangerous level and if everything is ok, then try to launch with signature. One more thing, if you use signature I think you need to export a signed apk files and then install them. – Yury Jun 28 '13 at 07:24
  • I would like to inform everybody about a security vulnerabiity related to using custom permissions. See this commonsware post: http://commonsware.com/blog/2014/02/12/vulnerabilities-custom-permissions.html – Tobrun Jun 05 '14 at 08:21
  • 1
    Don't forget to add `android:description = "string resource"` attribute while defining your custom permission, this will be helpful while explicitly asking for permissions in marshmallow – VIN Oct 05 '16 at 11:44
  • Will this pop a dialog that prompts the user to accept the permission in app B ? If so how do you avoid that, signature level permission? – Mike6679 Mar 03 '20 at 13:43
35

You need to create a permission in your base app's manifest by declaring it exclusively. For example:

<permission android:name="your.namespace.permission.TEST"
    android:protectionLevel="normal" android:label="This is my custom  permission" />

And later make use of it in your desired app as:

<uses-permission android:name="your.namespace.permission.TEST" />

Note: It is vital to maintain the order in which you install your applications with custom permissions. i.e You must need to install that app first which declares the permission and later install the one which makes use of it. Any disruption in this order may break the usage of custom. permissions.

waqaslam
  • 67,549
  • 16
  • 165
  • 178
  • Concise and short and it works. Top voted answer is better but this is exactly what was asked in the question. One note thou, this is ALL you need to use custom permissions, becouse security manager takes care of the rest. – Igor Čordaš Aug 04 '14 at 14:41
  • I cannot get this to work, even when I declare uses-permission in the app that created the permission. It throws security exception at the start – Anshu Dec 23 '14 at 12:42
  • 3
    As long as I remember correctly, the order in which you install the apps matter too. First install the app which declares custom permission and then install the app which uses that custom permission. – waqaslam Dec 23 '14 at 12:48
  • 1
    Can we use the custom permission within the application which created the permission? – Bharath Booshan Mar 26 '15 at 19:16
  • @BharathBooshan Yes, you can do that – waqaslam Mar 26 '15 at 19:48
  • Put custom permission in both applications and then you do not have to worry about which application is installed first. – Sanchit Aug 23 '16 at 17:53
  • 1
    Is this still true? I can't reproduce the installation order bug. I have put the permission definition () in just one app. No matter in which order I install the apps (I have uninstalled both for each test run first) it always works - at least for "signature" protected permissions... – ToBe Mar 30 '17 at 08:42
  • for signature level, the order doesn't matter. – waqaslam Aug 12 '19 at 14:42
7

As mentioned in the answers, you should also take into account the order you install the apps.

this is important because:

if the App that requests the permission (App B) is installed before the App that defines the permission (App A), then there will be no such defined permission in the specific device so the OS won't ask for the permission at all.

later on, when you install the App A and try to run App B, the latter will fail to access the secure component.

One workaround would be to define the same custom permission in both Apps, A and B in order to make sure that the permission exists in the device regardless of which App is installed first, so when the App A is installed, the permission will be already granted to App B.

In that case though, you should make sure that the protection level is the same in both declarations because this can lead to security risk.

(note here that from android 5.0 and on you cannot define the same permission in more than one App, except when those Apps are signed with the same signature key).

Adam
  • 91
  • 3
  • 5
3

The accepted answer shows the correct flow to create custom permissions. I have some note to decide which permission and permission name after my testing

android:protectionLevel="normal" // don't need user confirmation to grant, similar to some low-risk permission like android.permission.INTERNET

android:protectionLevel="dangerous" // need user confirmation to grant // similar to some high-risk permission like android.permission.CAMERA

android:protectionLevel="signature" // both app need to sign with the same signature

On Android < 6, user grant dangerous permission when install or update app. Android do it for us, we don't need to code
Android >= 6, user grant dangerous permission when using app (Runtime Permission). We need to code to request runtime permission

Android dangerous permission name need to has 2 parts (test on Android 10, Pixel 4XL), label, description, icon is not required to make permission work

<permission
        android:name="my.MyCustomPermission" // work well
        android:name="MyCustomPermission" // not work, the runtime permission dialog won't show
        android:label="" // don't required
        android:description="" // don't required
        android:icon="" // don't required
Linh
  • 57,942
  • 23
  • 262
  • 279
1

Defining custom permission is done using <Permission> tag.. Please follow the link below to use user defined permissions in application:

Declaring and Enforcing Permissions

Lavakush
  • 1,910
  • 2
  • 11
  • 14