Showing posts with label Authentication. Show all posts
Showing posts with label Authentication. Show all posts

Sunday, 15 January 2017

HB Blog 127: Creating A Custom Account Type.

So far we've talked about accessing Google APIs, which use accounts and users defined by Google. If you have your own online service, though, it won't have Google accounts or users, so what do you do? It turns out to be relatively straightforward to install new account types on a user's device. This tutorial explains how to create a custom account type that works the same way as the built-in accounts do.
The first thing you'll need is a way to get credentials from the user. This may be as simple as a dialog box that asks for a name and a password. Or it may be a more exotic procedure like a one-time password or a biometric scan. Either way, it's your responsibility to implement the code that:
  1. Collects credentials from the user
  2. Authenticates the credentials with the server
  3. Stores the credentials on the device
Refer the below link for complete sample code:-

Download Sample Code

You need to setup multiple components to be able to create an account programmatically. You need:
  •     an AccountAuthenticator
  •     a Service to provide access to the AccountAuthenticator
  •     some permissions
The Authenticator
The authenticator is an object that will make the mapping between the account type and the autority (i.e. the linux-user) that have rights to manage it.

Declaring an authenticator
is done in xml :
create a file res/xml/authenticator.xml with the following content :
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.example.harshalbenake.accountsetting.DEMOACCOUNT"
    android:icon="@drawable/ic_launcher"
    android:smallIcon="@drawable/ic_launcher"
android:label="@string/app_name"/>
Note the accountType : it must be reused in code when you create the Account. The icons and label will be used by the "Settings" app to display the accounts of that type.

Implementing the AccountAuthenticator
You must extends AbstractAccountAuthenticator to do that. This will be use by third party app to access Account data.
The following sample don't allow any access to 3rd-party app and so the implementation of each method is trivial.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.NetworkErrorException;
import android.content.Context;
import android.os.Bundle;

public class CustomAuthenticator extends AbstractAccountAuthenticator {

    public CustomAuthenticator(Context context) {
        super(context);
    }

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse, String s, String s2, String[] strings, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String getAuthTokenLabel(String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }
}

The Service exposing the Account Type

Create a Service to manipulate the Accounts of that type :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class AuthenticatorService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        CustomAuthenticator authenticator = new CustomAuthenticator(this);
        return authenticator.getIBinder();
    }
}

Declare the service in your manifest :
1
2
3
4
5
6
7
8
  <service android:name=".AuthenticatorService" android:exported="false">
  <intent-filter>
  <action android:name="android.accounts.AccountAuthenticator"/>
  </intent-filter>
  <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator"/>
</service>
Here, the filter and the meta-data referring to the xml resource declaring the authenticator are the key points.

The permissions
In your manifest be sure to declare the following permissions
1
2
3
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
(not all required for the sample code presented in this post, but you will probably have some more code about account management and at the end all of them will be useful)

Create an account in code
Now that everything is ready you create an account with the following code. Note the boolean returned by addAccountExplicitly informing you about the success or failure.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import android.accounts.Account;
import android.accounts.AccountManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AccountManager accountManager = AccountManager.get(this);
        Account account = new Account("HBAccount","com.example.harshalbenake.accountsetting.DEMOACCOUNT");
        boolean success = accountManager.addAccountExplicitly(account,"password",null);
        if(success){
            Toast.makeText(MainActivity.this,"Account created",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(MainActivity.this,"Account creation failed. Look at previous logs to investigate",Toast.LENGTH_SHORT).show();
        }

        Account[] accounts = AccountManager.get(this).getAccounts();
        for (Account account1 : accounts) {
            Toast.makeText(MainActivity.this, "Name: " + account1.name+" Type: " + account1.type,Toast.LENGTH_SHORT).show();
        }
    }
}

Wednesday, 3 June 2015

HB Blog 76: Android M With Fingerprint Authentication.

Authentication is the act of confirming the truth of an attribute of a single piece of data (datum) or entity. Fingerprint recognition or fingerprint authentication refers to the automated method of verifying a match between two human fingerprints. Fingerprints are one of many forms of biometrics used to identify individuals and verify their identity.

Authentication
Android M Developer Preview offers new APIs to let you authenticate users by using their fingerprint scans on supported devices, and check how recently the user was last authenticated using a device unlocking mechanism (such as a lockscreen password). Use these APIs in conjunction with the Android Keystore system. The Android Keystore system lets you store private keys in a container to make it more difficult to extract from the device. Once keys are in the keystore, they can be used for cryptographic operations with the private key material remaining non-exportable.
Fingerprint Authentication
To authenticate users via fingerprint scan, get an instance of the new android.hardware.fingerprint. FingerprintManager class and call the FingerprintManager.authenticate() method. Your app must be running on a compatible device with a fingerprint sensor. You must implement the user interface for the fingerprint authentication flow on your app, and use the standard Android fingerprint icon in your UI. If you are developing multiple apps that use fingerprint authentication, note that each app must authenticate the user’s fingerprint independently.

Use KeyGenerator to create a symmetric key in the Android Key Store which can be only be used after the user has authenticated with fingerprint and pass a KeyGeneratorSpec.

Use KeyGeneratorSpec.Builder.setUserAuthenticationRequired to permit the use of the key only after the user authenticate it including when authenticated with the user's fingerprint.

Use FingerprintManager.authenticate to tart listening to a fingerprint on the fingerprint sensor with a Cipher initialized with the symmetric key created.

Use FingerprintManager.AuthenticationCallback#onAuthenticationSucceeded() callback after the fingerprint (or password) is verified.

To use this feature in your app, add the USE_FINGERPRINT permission in your manifest.

1
2
<uses-permission
        android:name="android.permission.USE_FINGERPRINT" />
If you are testing this feature, follow these steps:
  1. Install Android SDK Tools Revision 24.3, if you have not done so.
  2. Enroll a new fingerprint in the emulator by going to Settings > Security > Fingerprint, then follow the enrollment instructions.
  3. Use an emulator to emulate fingerprint touch events with the following command. Use the same command to emulate fingerprint touch events on the lockscreen or in your app. 
adb -e emu finger touch <finger_id>
Confirm Credential
Your app can authenticate users based on how recently they last unlocked their device. This feature frees users from having to remember additional app-specific passwords, and avoids the need for you to implement your own authentication user interface. Your app should use this feature in conjunction with a public or secret key implementation for user authentication.
To set the timeout duration for which the same key can be re-used after a user is successfully authenticated, call the new android.security.keystore.KeyGenParameterSpec.setUserAuthenticationValidityDurationSeconds() method when you set up a KeyGenerator or KeyPairGenerator. This feature currently works for symmetric cryptographic operations.
Avoid showing the re-authentication dialog excessively -- your apps should try using the cryptographic object first and if the the timeout expires, use the createConfirmDeviceCredentialIntent() method to re-authenticate the user within your app.