I want to authenticate my Android app using pin/password set for device security/lock screen. Is there any way to achieve this? May be, app will launch some system Activity, which will prompt for password. The system Activity should return success/failure.
Began from Android 5.0, you can use KeyguardManager.createConfirmDeviceCredentialIntent()
This method will create an Intent, which can be used to start system authentication (pin / pattern / password).
For more information, refer doc and Confirm Credential sample.
App Start
(Is password already created?) <--check in sharedPreferences(This is a good way to store info)
Yes No
Prompt for pass Prompt for creation
Login if correct Login
To do this you can use SharedPreferences, once you have stored a key you can retrieve it on app start up to decide what to do.
Related
I am trying to require user authentication through Keyguard Manager for an Android app as part of a flow. This means that user must be authenticated to go through the flow. This is accomplished by starting a Keyguard Manager createConfirmDeviceCredentialIntent generated activityForResult and receiving an activityResult from it.
I want to test that flow automatically. This causes a problem because my automated test isn't able to authenticate itself(i.e. enter swipe pattern or enter PIN). How can I get my test to automatically pass this to put the test environment into an authenticated state? Can I mock some function in the Keyguard Manager to automatically pass the authentication check?
Keyguard Manager
createConfirmDeviceCredentialIntent
The solution to this was more abstraction. Previously I had been doing encrpytion and decryption through static methods. I switched to using an Encryptor and Decryptor object which had a field "userAuthenticationRequired", and using a Builder to set that field as part of building an encryptor. This allowed me to test authentication by passing in an Encryptor with userAuthenticationRequired when running the app, and without that field as false when testing the app.
As we know, we have an api in KeyguardManager for authenticatng the user through his device lock. The api is : confirmDeviceCredentialIntent.
The doc for this api says :
Get an intent to prompt the user to confirm credentials (pin, pattern or password) for the current user of the device. The caller is expected to launch this activity using startActivityForResult(Intent, int) and check for RESULT_OK if the user successfully completes the challenge.
Now, my problem is, I want to invoke this flow in a non-activity context. I am using a kv store in my app whose contents would be encrypted by the key that I am storing in android keystore. So when I want to get any value fro that store, I first need to authenticate user so that I get my key and decrypt the content before returning.
Second thing is, I, as a consumer of that kv store, don't want to be aware about how the encryption of the store is done and therefore I shouldn't invoke confirm credentials myself. I just want my value from the store and it's store's (which is non-ui component) responsibility to invoke the authentication flow if it's required.
So mostly, I'd be using the global application context. And this context doesn't provide startActivityForResult api.
Is there any other way by which I can get result of confirm credentials action from user?
I ended up using a Dummy Activity. This activity itself is launched by application context and then it handles invoking confirmCredentials intent for result.
I have an Android app, which the user can link to Spotify, with :
AuthenticationClient.openLoginActivity(getActivity(), SPOTIFY_REQUEST_CODE, request);
The problem is that I want the user to change his Spotify account so I want to logout the user from Spotify to log with another account. But the data of the connection are saved in the cache and when I use this line again :
"AuthenticationClient.openLoginActivity(getActivity(), SPOTIFY_REQUEST_CODE, request);", it does not show the connection dialog because the user is already connected.
In the doc, it says :
"To log out and clear all stored tokens, use the AuthenticationClient#clearCookies method. Both Spotify and Facebook tokens will be removed."
But the method clearCookies does not exist anymore. What can I do to logout the user and allow him to connect on another account ?
I've searched on the net and seems that this code
AuthenticationRequest.Builder builder = new AuthenticationRequest.Builder(CLIENT_ID, type, redirectUri)
.setShowDialog(true)
.setScopes(scopes).build();
took from this post it's your only choice to try to logout a user.
I can't test it, so you should try it yourself and see if works.
The documentation on the Spotify Android SDK is outdated and is not reflecting the new Spotify auth library on GitHub.
Spotify's Android SDK documentation is definitely outdated. My observation is that when you call
AuthorizationClient.clearCookies(context)
directly before starting Spotify's auth activity, it just works fine. But if you call it once and then expect that the user is logged out, when you start the activity later in the future, cached credentials keep messing around.
I do not prefer
builder.setScopes(arrayOf("")).setShowDialog(false).build()
as it shows you a "not you? Click to log out" option. So basically you need to log out on the Spotify UI, cannot do it from code.
In my case, the application saves the logged in user's email (I need that to show on the UI, anyway). When I want to log the user out programmatically, I just delete the saved email from the app and call
clearCookies()
when I start Spotify's Activity if the variable is empty.
A bit late, but you can use this AuthorizationClient.clearCookies(this) as
AuthenticationClient no longer exists
In our Android app we are able to get authentication tokens without any user interaction (for the purpose of knowing that an api call was received from our app, not for the purpose of getting any user info)
We use:
GoogleAuthUtil.getToken(context, anyAccount, "audience:server:client_id:" + MY_CLIENT_ID);
How can we do something similar to authenticate api-calls from a chrome extension?
UPDATE:
This is how we get authentication w/o user interaction on Android:
http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html
Fortunately when calling getAuthToken, you can pass a flag ('interactive': true) or ('interactive': false)
('interactive': true)
If you invoke the API in interactive mode, the user is shown a sign in and/or approval UI when necessary, as shown in the screenshot below:
('interactive': false)
If you invoke the API in silent mode, the API will only return a token if it's possible to produce one without showing any UI. This is useful in cases when an app is doing the flow at app startup, for example, or in general in cases where there is no user gesture involved.
NOTE
The best practice we suggest is to use silent mode when there is no user gesture involved and use interactive mode if there is a user gesture (for example, the user clicked the Sign In button in your app). Note that we do not enforce any gesture requirement.
I was trying to use Android Password expiration feature using
DeviceAdmin. When I call setPasswordExpirationTimeout() API , it only
sends a notification and doesn't actually force the user to change the
password. It only sends a notification after timeout:
V/DevicePolicyManagerService( 662): Sending password expiration
notifications for action
com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION
You have to get the callback in DeviceAdminReceiver in
onPasswordExpired() to force user to change password.
Any specific reason it's been implemented this way (or is it just to
give flexibility to the programmer)?
The only option I could see is starting activity with intent ACTION_SET_NEW_PASSWORD in the callback in DeviceAdminReceiver which the user can overrule by simply pressing 'Cancel' button.
How to 100% enforce the to change password ?
Have you tried looking at the DeviceAdminSample (source code)? The Android SDK comes with all the samples so you can easily add the ApiDemos as an Eclipse project and run it in the simulator.
I originally thought you could call the resetPassword method in the DevicePolicyManager, but you would need the user to have given you their new password to do that, which I assume you don't want to do!