OTP based user registration using AWS Cognito and Android
Amazon Cognito is a simple user identity and data synchronization service that helps you securely manage and synchronize app data for your users across their mobile devices. Amazon Cognito Federated Identities is a web service that delivers scoped temporary credentials to mobile devices and other untrusted environments.
I will briefly describe you how to integrate the Amplify Cognito User pool in android for User Management.
We need to add some configurations in our system for using Amplify Framework. Follow below steps
- Install Node Js or NPM using belowlink
https://nodejs.org/en/download/ - Install CLI using below command (Make sure you are in root directory)
npm install -g @aws-amplify/cli
3. Run the following command in the project root directory to initialize the amplify in the project then do the basic setup.
amplify init
Select options as per the above screenshot.
Then run the “amplify add auth” command to set up the Authentication with CLI.
After that, run the command “amplify push” to push all the changes in the backend AWS Console. This command creates the user pool on the AWS Console to save all the users.
If you now navigate to AWS Cognito User Pool, it will show below
At this point we have setup user pool in Cognito, now we will work on creating our Android Project
Open Android Studio and create new project with Empty Activity
Click on Next will open up below screen where you need to enter name of your project and other details related to project/language and minimum SDK
Click on Finish after which it will open up project as below
Expand Gradle Scripts and open file build.gradle for module
Add below lines in build.gradle file at bottom
dependencies {
def multidex_version = "2.0.1"
implementation "androidx.multidex:multidex:$multidex_version"
}
dependencies {
implementation 'com.amplifyframework:aws-auth-cognito:1.16.11'
}
Once you save this file, build process will take place.
Open activity_main.xml under res/layout folder and add below
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="186dp"
tools:layout_editor_absoluteY="174dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal">
<TextView android:text = "Signup" android:layout_width="wrap_content"
android:layout_height = "wrap_content"
android:id = "@+id/textview"
android:textSize = "35dp"
android:layout_alignParentTop = "true"
android:layout_centerHorizontal = "true" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal">
<EditText
android:id="@+id/txtEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textEmailAddress"
tools:layout_editor_absoluteX="100dp"
tools:layout_editor_absoluteY="217dp"
android:hint="Email Address"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal">
<EditText
android:id="@+id/txtPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword"
tools:layout_editor_absoluteX="100dp"
tools:layout_editor_absoluteY="284dp"
android:hint="Password"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal">
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sign Up"
tools:layout_editor_absoluteX="168dp"
tools:layout_editor_absoluteY="375dp"
android:onClick="registerUser"/>
</TableRow>
</TableLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
We are creating a table layout and adding two textboxes with label and a button as below screenshot
Next we will add logic for SignUp button click in MainActivity.java file
package com.demo.filebox;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.amplifyframework.AmplifyException;
import com.amplifyframework.auth.AuthException;
import com.amplifyframework.auth.AuthUserAttributeKey;
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin;
import com.amplifyframework.auth.options.AuthSignUpOptions;
import com.amplifyframework.core.Amplify;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
// Add this line, to include the Auth plugin.
Amplify.addPlugin(new AWSCognitoAuthPlugin());
Amplify.configure(getApplicationContext());
Log.i("MyAmplifyApp", "Initialized Amplify");
} catch (AmplifyException error) {
Log.e("MyAmplifyApp", "Could not initialize Amplify", error);
}
}
public void registerUser(View view) {
EditText password = (EditText)findViewById(R.id.txtPassword);
EditText email = (EditText)findViewById(R.id.txtEmail);
try {
Amplify.Auth.signUp(
email.getText().toString(),
password.getText().toString(),
AuthSignUpOptions.builder().userAttribute(AuthUserAttributeKey.email(), email.getText().toString()).build(),
result -> { runOnUiThread(() -> {
Toast.makeText(getApplicationContext(), "Signup successful", Toast.LENGTH_SHORT).show();
Intent i = new Intent(this, OtpActivity.class);
Bundle b = new Bundle();
b.putString("USERNAME", email.getText().toString());
i.putExtras(b);
startActivity(i);
} ); },
error -> { runOnUiThread(() -> {
if(error instanceof AuthException.UsernameExistsException) {
Toast.makeText(getApplicationContext(), "Signup failed because username exists.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Signup failed for a different reason.", Toast.LENGTH_SHORT).show();
}
} ); }
);
}catch(Exception e)
{
Log.e("test", "error in main ",e);
}
}
}
In above code, we are creating a RegisterUser method where in we are invoking Amplify Framework’s signup method which takes username and password as parameters, it will check user in UserPool of Cognito using Amplify Framework. If user exists then it will show a message else it will create user in pool, send out an email for OTP and redirect to OTP Screen.
Next task is to create an OTP Screen in android where user has to enter OTP received in email.
We will create an activity_otp.xml file under res/layout folder and add below
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".OtpActivity">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="186dp"
tools:layout_editor_absoluteY="174dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal">
<TextView android:text = "Verify OTP" android:layout_width="wrap_content"
android:layout_height = "wrap_content"
android:id = "@+id/textview"
android:textSize = "35dp"
android:layout_alignParentTop = "true"
android:layout_centerHorizontal = "true" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal">
<EditText
android:id="@+id/txtOtp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="text|number"
tools:layout_editor_absoluteX="100dp"
tools:layout_editor_absoluteY="284dp"
android:hint="Enter OTP here"/>
<Button
android:id="@+id/validateOtp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Verify OTP"
tools:layout_editor_absoluteX="168dp"
tools:layout_editor_absoluteY="375dp"
android:onClick="validateOtp"/>
</TableRow>
</TableLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
This will create an OTP screen layout as below
Next we will create java file called OtpActivity.java as below
package com.demo.filebox;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.amplifyframework.core.Amplify;
public class OtpActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_otp);
}
public void validateOtp(View view) {
Bundle bundle = getIntent().getExtras();
String user= bundle.getString("USERNAME");
EditText otp = (EditText)findViewById(R.id.txtOtp);
Amplify.Auth.confirmSignUp(
user,
otp.getText().toString(),
result -> Log.i("AuthQuickstart", result.isSignUpComplete() ? "Confirm signUp succeeded" : "Confirm sign up not complete"),
error -> Log.e("AuthQuickstart", error.toString())
);
}
}
This will invoke confirmSignUp method from Amplify framework which will take parameter of username (i.e. email address) and OTP. Once it is validated, we show up a message in logger that signup is successful
When user clicks on SignUp button, an OTP gets sent as below:
This message is completely customizable from UserPool section of AWS Cognito Console.
So that’s it, this is the complete guide on creating Android app that connects with Cognito using Amplify framework for Registering and Authenticating users. I am planning to create a dropbox style app which will store files in AWS. Will write up a next blog soon for this.
Hope you liked the article. Please like and share.
Please post your questions in comments section.