Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android one time password (OTP) user registration/opening account

I want to implement OTP functionality in my android application. In this application, after signup user will receive one time password key. After verifying OTP, user will be able to register/open account successfully by using that OTP. What i need to do achieve this?

like image 571
sachin110011 Avatar asked Mar 14 '14 08:03

sachin110011


People also ask

How the OTP is generated?

Values for one-time passwords are generated using the Hashed Message Authentication Code (HMAC) algorithm and a moving factor, such as time-based information (TOTP) or an event counter (HOTP). The OTP values have minute or second timestamps for greater security.

What is a one-time password code?

What does OTP mean? One-time password (OTP) systems provide a mechanism for logging on to a network or service using a unique password that can only be used once, as the name suggests. The static password is the most common authentication method and the least secure.

Can I create my own OTP?

There are two ways to create OTPs. One way is through the use of smartphone apps like Google Authenticator, Authy, and Duo. The other way is to generate one-time passwords online using websites such as TOTP Generator.


1 Answers

As @Vipin mentioned, the best way would be implementing it your self:

First, you have to generate a 4-digit(or whatever you want) pin code, for example:

int range = 9;  // to generate a single number with this range, by default its 0..9
int length = 4; // by default length is 4

public int generateRandomNumber() {
    int randomNumber;

    SecureRandom secureRandom = new SecureRandom();
    String s = "";
    for (int i = 0; i < length; i++) {
        int number = secureRandom.nextInt(range);
        if (number == 0 && i == 0) { // to prevent the Zero to be the first number as then it will reduce the length of generated pin to three or even more if the second or third number came as zeros
            i = -1;
            continue;
        }
        s = s + number;
    }

    randomNumber = Integer.parseInt(s);

    return randomNumber;
}

Then, you have to save this number somewhere save, for example in your preferences:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("OTP_PIN", randomNumber);
editor.commit();

The next step, would be using a proper SMS gateway to send that OTP to the corresponding phone number, for me I'm using clickATell with our php server to send the message, the api documentation is pretty clear. And if you want to send the message directly from the application, may be SMSgateway can help.

The final step, is to verify the code received by SMS is the one stored in device preferences, this is pretty easy and straight forward, all you have to do is to provide an EditText for the user allowing him to enter the code received by his phone, if the code matches the OTP saved in device preferences, make him go through the app, otherwise, display a proper error message.


a classy move: Not mandatory but preferably, as a lot of applications doing you can provide SMS listener to listen to the upcoming messages, getting the code from the received message, display it in the code verification editText, verify it, if true, go through the app.

in manifest.xml:

<receiver
    android:name=".Services.SmsListener"
    android:exported="true"
    android:permission="android.permission.BROADCAST_SMS">
    <intent-filter android:priority="999">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

the listener:

public class SmsListener extends BroadcastReceiver {

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("messageBody", intent.getAction());
        if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
            try {
                String messageBody = "";
                for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
                    messageBody = smsMessage.getMessageBody();
                }
                Intent messageReceived = new Intent(SVPreferences.SMS_RECEIVED);
                messageReceived.putExtra("sms", messageBody);
                context.sendBroadcast(messageReceived); // when receiving it somewhere in your app, subString the additional text and leave only the code, then place it in the editText and do your verification
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

the receiver:

BroadcastReceiver receiveSMS = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            String smsBody = intent.getStringExtra("sms");
            String pin = smsBody.replace(getResources().getString(R.string.your_extra_text), "").trim();
            editText_confirm_pin.setText(pin);
            if (validatePin(pin))
                // go through the app
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
};
like image 88
Muhammed Refaat Avatar answered Sep 27 '22 17:09

Muhammed Refaat