I tried to search for this particular case but didn't find anything yet. Sharing data between two applications is possible with ContentProvider and you can set protectionLevel to signature, so applications with that signature can access the data (same publisher).
But what if the scenario is following:
Developer A and B publishes application.
Me, A and B decide to do some co-work together. I am to provide my own application, but I need to access both A and B private information.
Is this possible? A and B would need to grant my application to access their let's say ContentProvider
Thanks.
Setting protectionLevel to signature will only allow to access data between applications signed with the same key (in this case A, B and you should agree on using the same key to sign your published applications).
If this is not the case, then A and B should export their ContentProvider and (optionally) provide permissions to read/write data. If they define permissions, then your client application should specify this permission in the manifest.
References:
http://developer.android.com/guide/topics/manifest/provider-element.html
http://developer.android.com/training/articles/security-tips.html
Related
How can we ensure that certain applications are not able to access my data stored in content provider where in certain other applications can access that? Basically I need to allow some application of my interest to access my data stored in Content Provider but I do not want all the applications to be able to access that data. How can I achieve this?
Thanks.
The easiest way is to protect the content provider with a permission you define. Make it a signature a permission so only apps signed with your certificate are allowed to get it.
See:
http://developer.android.com/guide/topics/security/security.html
http://developer.android.com/reference/android/R.styleable.html#AndroidManifestProvider
http://developer.android.com/guide/topics/manifest/provider-element.html
If doing this based on certificates is not sufficient, you will need to write the permission checks yourself. This is done by calling Binder.getCallingUid() for incoming calls to your applications, and deciding whether the given uid has permission to access your provider. Actually implementing a different policy that is actually secure requires a lot of careful thought and design, though.
In the AndroidManifest.xml, at the screen with the properties of your ContentProvider, you have two fields:
Read Permission
WritePermission
So, you can define secure strings (also it may be path to some file) that are permissions for acces to your ContentProvider.
Applications that want to access your content provider must have that ones added in their UsesPermission elements.
I am writing an application where, after successfull login and based on the user profile, the user can only see certain activities. For instance, if user has profilA, he can only see Activities A, B, C. If he has profilB, he can only sees Activities D,F,G.
Note that I could write 2 applications and my problem is solved easily but the requirements are the app should manage profileA and profileB.
I was thinking about custom permissions to implement this. Where each activity will be restricted with a custom permissions. For instance, Activities A,B and C would be restricted with com.myapp.permissions.profilA. And Activities D,F and G would be restricted with com.myapp.permissions.profilB.
While searching again, I have found the permission-tree element and the PackageManager.addPermission(PermissionInfo info).
The javadoc of addPermissionsays :
Add a new dynamic permission to the system. For this to work, your package must have defined a permission tree through the tag in its manifest. A package can only add permissions to trees that were defined by either its own package or another with the same user id; a permission is in a tree if it matches the name of the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree "com.foo".
The idea that I have is, define a permission-tree, after successfull login, based on the user profile, "sets the custom permissions" of the application. I don't know if it's possible.
It's a similar feature when certain apps hide some admins features to their users. I am thinking of similar functionality.
Is it possible to achieve this functionality? Or do I need to think for another solution?
I am open to all propositions.
There is an easier way to go about about. In your API, create a user_code for each user so that after a successful login, you can get the user_code for the currently logged in user. Once you get the code say in the Home/Dashboard Activity, you can check if the user is allowed to access a certain activity and if they are not allowed, you can probably return an alert dialog telling them that they don't have the rights.
It seems that defining custom permissions to restrict access to certain activities is not exactly what you need. Seems to me that you're going on the wrong direction...as the documentation states...creating custom permissions is relatively uncommon...I mean permissions were designed to reduce security issues and sandbox applications from each other....the latter doesn't seem to be your case.
Anyway, it is extremely uncommon...IMHO, to create custom permissions for the mere purpose to restrict access to certain activities. Especially, because the same way you login a user and the same way you determine what a specific user is allowed to do...it's exactly the same way you can determine when to restrict access to a specific part of your app
Not really sure why you would need to rely on the permission system to do this. What I'm thinking is that you can just create logic to disable whatever features that would lead to those Activities from being launched based on the logged in profile.
If your activities don't have any filters that would allow them to be launched implicitly by another intent, then that means your app complete control over when they're launched.
Use the login result to control what you display to the user. If you wanted to, you could create two separate XML layout files. One that has buttons for A, B, and C, and the other that has buttons for D, E, and F.
Just because an Activity exists doesn't mean it's automatically displayed to the user as an "entry point". You're doing that through what you display in other activities.
I've googled enough, but couldn't find this case. I want to write a custom Content Provider that is shared/accessible to only specific apps.
I've this scenario:
Have multiple apps on Google Play. Say A, B and C.
Want to write a Content Provider, say Z that could only be accessed by A, B and C. I'm thinking to publish Content Provider 'Z' as its own apk.
When Z is installed on device; A, B and C can access Z. If Z is not installed, then first app will direct to Google Play to install Z.
Now my question is:
Is it possible at all to write such Content Provider at all, which is only shared among specific apps? android:exported="false" makes it inaccessible by any other external app. android:grantUriPermissions="true" doesn't work when android:exported is set to false, and setting android:exported to true makes it public accessible.
Please feel free to share other solutions too, if they seem more appropriate to my requirements of sharing info among multiple apps.
android:grantUriPermissions="true" doesn't work when android:exported is set to false
Yes, it does.
However, android:grantUriPermissions may not be relevant for your use case, particularly if Z is its own standalone app. Z would have to be the one calling into A/B/C using an Intent with the FLAG_GRANT* flag, and I am guessing that this would not fit your plan.
If, as I suspect, A/B/C need to access Z independently of Z telling them that it can be accessed and granting the Uri-specific permissions, the standard approach would be to use a custom signature-level <permission>. You would then defend export the provider and defend it with that permission using android:permission in the <provider>. The theory is that only your app suite can hold that permission, because only your app suite will be signed by that signing key and therefore have a signature match.
(I say "in theory" because there are issues with this approach)
I have multiple apps that have some sort of in-app currency (i.e gold).
The gold (Integer value) should be accessable through all of my apps. All of my own apps should be able to read/write the value.
It is important that only my apps are able to write the value, it doesn't matter if anyone else can read it.
It's also important that I do not know which of my apps is installed. There is no 'main'-app at all. It should be irrelevant which of my apps is installed and in which order.
The value does not have to be shared between the apps during runtime, I rather thought of something like sharedPreferences or an SQL database.
Where/How should I store this value?
Which is the preferred solution to this problem (if there is any)?
If you need to share data between two (or more) apps, you can set to them the same android:sharedUserId (in AndroidManifest.xml) so the other app can read/write in the private data of the other app.
android:sharedUserId
The name of a Linux user ID that will be shared
with other applications. By default, Android assigns each application
its own unique user ID. However, if this attribute is set to the same
value for two or more applications, they will all share the same ID —
provided that they are also signed by the same certificate.
Application with the same user ID can access each other's data and, if
desired, run in the same process.
Doc here.
I have an application, say ApplicationProvider, which holds a provider and a receiver.
Another application, say ApplicationCreator, creates an element on the provider through an intent. The ApplicationProvider get the intent and creates the element accordingly.
Now I would like ApplicationCreator to be the only one to hold the rights to access that element. So if another application tries to access that element, this generates some kind of error.
What is the best way to do so? I came up with two possible solutions, but I don't like any of them.
1) ApplicationProvider denies any direct access to the provider, instead uses the receiver to get the intents which are sent through intentForResult, so the receiver can check the caller, verify that is the original caller who created the element and grant access. Other applications would get denied because they hold a different uid. Since there is no easy way to forge the uid, this system works.
2) Any application can send intents to the provider but in the manifest i specify all the path-level permission to the single uris that are created. I manually issue an update to the application every time someone wants so create a new element.
=========================================
Additional information:
It would be ideal if different applications could put different elements and be able to retain the rights to modify those elements they created and also grant permission on those elements to whom requested said permission.
A---> +--------+ A creates content
| pro | <---B B asks permission
A<----| vid | the provider forward permission
A---->| er | A grant permission
| | --->B B is given permission and can access A's stuff
+--------+
Here are my thoughts on this topic. No code is provided, since I did not implement anything. Also, I'm not entirely sure that this solution is entirely secure.
First, authentication.
Every client who wants to use your content provider needs a key. Each client fetches one key from your application (maybe implement a content provider for that). A random sequence of letters / numbers should be fine. This key is stored within your application and the clients application, somewhere where noone else has access, i.e. a private database / preference property.
This key is used to authenticate a client application with your content provider. On each request, this key (maybe a hash of the key) is included within the request uri (much like API keys when using REST web services). Your application checks whether the provided key was previously generated. If that is the case, authentication is successful.
Next, authorization.
Each element in your database has a field ownerKey. When creating new elements, this field is filled with the key provided with the request. When accessing / modifying / deleting elements, your content provider should check whether the stored key matches the submitted key. Only perform the operation if the keys match.
Additional thoughts.
The whole point is that the random keys generated by your application stay private. I'm not sure whether it is possible for a third party to intercept interaction between a client application and a content provider. You might want to investigate this before writing any code.
Specifying a key on each request could be optional. When omitting a key during element creation, those elements do not have an ownerKey and thus are allowed to be accessed and modified by anyone without authentication/authorization.
I hope this helps somewhat.
I would suggest the uid approach, but there is no reason for this to go indirectly through a receiver. Just store the owning uid for each row in your database, and on incoming calls to the content provider use Binder.getCallingUid() to retrieve the uid of the current caller which you can validate against the row they are operating on.