Login With Amazon using AWS Amplify Auth
Tags: android, java, aws, codenewbie
Published: 2020-08-02 03:33:58

In this tutorial you will learn how use AWS Amplify authentication service to enable Login With Amazon in an Android application. The App experience will look like below

&nbsp;

<img class="aligncenter wp-image-683 size-full" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/08/2.gif" alt="" width="285" height="587" />

&nbsp;
<ul>
 	<li>Create a new Android Studio project using the Empty Activity template</li>
</ul>
<img class="aligncenter" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-28_at_12.21.53_PM.png" alt="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-28_at_12.21.53_PM.png" />
<ul>
 	<li>We are going to use MyAuthApplication for the name field</li>
</ul>
<img class="aligncenter" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-30_at_3.56.43_PM.png" alt="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/creen_Shot_2020-07-30_at_3.56.43_PM.png" />
<ul>
 	<li>Update build.gradle (Project: MyAuthApplication) as below</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
        // ******* Add this line *******
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.0.1"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()

        // ******* Add this line *******
        mavenCentral()

    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
</pre>
<ul>
 	<li>Update build.gradle (Module:app) as below</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">apply plugin: 'com.android.application'

android {
    compileSdkVersion 29

    defaultConfig {
        applicationId "com.offlineprogrammer.myauthapplication"
        minSdkVersion 23
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    // ******* Add these lines *******
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    // ******* Add these lines *******
    implementation 'com.amplifyframework:core:1.1.1'
    implementation 'com.amplifyframework:aws-auth-cognito:1.1.1'

}
</pre>
<ul>
 	<li>Make sure to run Gradle Sync</li>
 	<li>Run the command below on Android Studio Terminal</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">amplify init
</pre>
<ul>
 	<li>You will prompted for few details as below</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">? Enter a name for the project MyAuthApplication
? Enter a name for the environment amplify
? Choose your default editor: None
? Choose the type of app that you're building android
Please tell us about your project
? Where is your Res directory:  app/src/main/res
Using default provider  awscloudformation

For more information on AWS Profiles, see:
&lt;https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html&gt;

? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use default
Adding backend environment amplify to AWS Amplify Console app: d2yvhmdiprhhlh

</pre>
<ul>
 	<li>Once complete you will get the confirmation below</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">Your project has been successfully initialized and connected to the cloud!</pre>
<ul>
 	<li>Create a new class and name it MyAuthApplication</li>
 	<li>We will use this class to initialize Amplify as below - note how the class extends from Application</li>
</ul>
<pre><code class="language-java">public class MyAuthApplication  extends Application {
    private static final String TAG = "MyAuthApplication";

    @Override
    public void onCreate() {
        super.onCreate();

        try {
            Amplify.addPlugin(new AWSCognitoAuthPlugin());

            Amplify.configure(getApplicationContext());

            Log.i(TAG, "Initialized Amplify");
        } catch (AmplifyException error) {
            Log.e(TAG, "Could not initialize Amplify", error);
        }

    }
}
</code></pre>
<ul>
 	<li>Update AndroidManifest.xml to add a <code>android:name</code> attribute with the value of <code>.MyAuthApplication</code> as below</li>
</ul>
<pre class="lang:xhtml decode:true">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.offlineprogrammer.loginwithamazon"&gt;

    &lt;application
        android:name=".MyAuthApplication"
				....</pre>
<ul>
 	<li>Login <a href="https://developer.amazon.com/loginwithamazon/console/site/lwa/overview.html">here</a> using your Amazon developer account to create a Security Profile</li>
</ul>
<img class="aligncenter" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-28_at_4.10.12_PM.png" alt="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-28_at_4.10.12_PM.png" />
<ul>
 	<li>Enter a Security Profile Name, a Security Profile Description, and a Consent Privacy Notice URL then click Save</li>
 	<li>Take not of the client ID &amp; Client secret</li>
</ul>
<img class="aligncenter" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-31_at_1.12.05_PM.png" alt="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-31_at_1.12.05_PM.png" />
<ul>
 	<li>Run the command below to configure the Auth Category</li>
</ul>
<pre class=""><code class="theme:dark-terminal lang:sh decode:true ">amplify add auth
</code></pre>
<ul>
 	<li>Set the details below when prompted</li>
</ul>
<pre><code class="theme:dark-terminal lang:sh decode:true ">Do you want to use the default authentication and security configuration? Default configuration with Social Provider (Federation)
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.
 What domain name prefix do you want to use? myauthapplication7ae1f03e-7ae1f03e
 Enter your redirect signin URI: myauthapp://callback/
? Do you want to add another redirect signin URI No
 Enter your redirect signout URI: myauthapp://signout/
? Do you want to add another redirect signout URI No
 Select the social providers you want to configure for your user pool: Login With Amazon
  
 You've opted to allow users to authenticate via Amazon.  If you haven't already, you'll need to create an Amazon App ID. 
 
 Enter your Amazon App ID for your OAuth flow:  amzn1.application-oa2-client.88a2ae52a05349d8a8027c93d9e5fc51
 Enter your Amazon App Secret for your OAuth flow:  b9f0fa476eea36200d8f1f304adc7711a63fa6422d22d515b50f729f33560a61
Successfully added resource myauthapplication7ae1f03e locally

</code></pre>
<ul>
 	<li>Publish those changes by running the command below</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">amplify push</pre>
<ul>
 	<li>Once complete it will display your UI endpoint Url as belwo</li>
</ul>
<pre class="theme:dark-terminal lang:sh decode:true">✔ All resources are updated in the cloud

Hosted UI Endpoint: &lt;https://myauthapplication7ae1f03e-7ae1f03e-amplify.auth.us-east-1.amazoncognito.com/&gt;
Test Your Hosted UI Endpoint: &lt;https://myauthapplication7ae1f03e-7ae1f03e-amplify.auth.us-east-1.amazoncognito.com/login?response_type=code&amp;client_id=5ig0u8445jd6v23ejt9db1ks3p&amp;redirect_uri=myauthapp://callback/&gt;
</pre>
<ul>
 	<li>On Amazon developer portal, click on the security profile you created above and select the web Settings tab</li>
</ul>
<img class="aligncenter" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-31_at_3.13.24_PM.png" alt="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-31_at_3.13.24_PM.png" />
<ul>
 	<li>Choose Edit then Type your UI endpoint Url into Allowed Origins and type UI endpoint Url with the /oauth2/idpresponse endpoint into Allowed Return URLs.</li>
</ul>
<img class="aligncenter" src="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-31_at_1.24.02_PM.png" alt="http://www.offlineprogrammer.com/wp-content/uploads/2020/07/Screen_Shot_2020-07-31_at_1.24.02_PM.png" />
<ul>
 	<li>Update the AndroidManifest.xm to set the android:launchMode and intent-filter for the MainActivity as below</li>
</ul>
<pre class="lang:xhtml decode:true">&lt;activity android:name=".MainActivity"
            android:launchMode="singleInstance"&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.MAIN" /&gt;
                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
                &lt;action android:name="android.intent.action.VIEW" /&gt;
                &lt;category android:name="android.intent.category.DEFAULT" /&gt;
                &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
                &lt;data android:scheme="myauthapp" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;</pre>
<ul>
 	<li>To capture the response from the sign in web UI add the method below to MainActivity</li>
</ul>
<pre><code class="language-java">@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if(intent.getData() != null &amp;&amp; "myauthapp".equals(intent.getData().getScheme())) {
            Amplify.Auth.handleWebUISignInResponse(intent);
        }
    }
</code></pre>
<ul>
 	<li>Download the login button from <a href="https://developer.amazon.com/docs/login-with-amazon/button.html#android-images">here</a> and add it to your Drawable folder. we are going to use both (btnlwa_gold_login.png) &amp; (btnlwa_gold_login_pressed.png).</li>
 	<li>Right click on Drawable folder and create a Drawable Resource File . Name it login_button_image_state.xml</li>
 	<li>This file will define the selector for the login button as below</li>
</ul>
<pre class="lang:xhtml decode:true">&lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    &lt;item android:state_pressed="false" android:drawable="@drawable/btnlwa_gold_login" /&gt;
    &lt;item android:state_pressed="true" android:drawable="@drawable/btnlwa_gold_login_pressed" /&gt;
&lt;/selector&gt;</pre>
<ul>
 	<li>Update the activity_main.xml to add the login button &amp; progress bar as below</li>
</ul>
<pre class="lang:xhtml decode:true">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;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"&gt;

    &lt;TextView
        android:id="@+id/login_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click the button below to login"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" /&gt;


    &lt;ImageButton
        android:id="@+id/login_with_amazon"
        android:background="@android:color/transparent"
        android:src="@drawable/login_button_image_state"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/login_textView"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:contentDescription="Null" /&gt;

    &lt;FrameLayout
        android:id="@+id/loginProgressLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:gravity="center"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/login_textView"&gt;

        &lt;ProgressBar
            android:id="@+id/log_in_progress"
            style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="@android:color/transparent"
            android:visibility="gone" /&gt;
    &lt;/FrameLayout&gt;


&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;</pre>
<ul>
 	<li>Update the MainActivity.java to introduce a login method to be called when the user click on the signIn button. below is the final code of MainActivity.java</li>
</ul>
<pre><code class="language-java">public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    ImageButton login_with_amazon;
    TextView login_textView;
    ProgressBar log_in_progress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        login_with_amazon = findViewById(R.id.login_with_amazon);
        login_textView = findViewById(R.id.login_textView);
        log_in_progress = findViewById(R.id.log_in_progress);

        login_with_amazon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                log_in_progress.setVisibility(View.VISIBLE);
                login_with_amazon.setVisibility(View.GONE);
                login();
            }
        });


    }

    private void login() {
        Amplify.Auth.signInWithSocialWebUI(
                AuthProvider.amazon(),
                this,
                result -&gt; {
                    Log.i(TAG, "AuthQuickstart RESULT " + result.toString());
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            login_textView.setText("Login is successfull");
                            login_with_amazon.setVisibility(View.GONE);
                            log_in_progress.setVisibility(View.GONE);
                        }
                    });
                },
                error -&gt; {
                    Log.e(TAG, "AuthQuickstart ERROR " + error.toString());
                }
        );

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if(intent.getData() != null &amp;&amp; "myauthapp".equals(intent.getData().getScheme())) {
            Amplify.Auth.handleWebUISignInResponse(intent);
        }
    }

}
</code></pre>
Check the full code on <a href="https://github.com/offlineprogrammer/MyAuthApplication">github</a> and follow me on <a href="https://twitter.com/MohammedMalaka">Twitter</a> for more tips about #coding, #learning, #technology, #Java, #JavaScript, #Autism, #Parenting...etc.

Check my Apps on <a href="https://bit.ly/3h05gQ7">Google Play</a>

&nbsp;

&nbsp;