# Lab9

## Lab9-1 : Add authentication to the App
1. Run this command from the root of your app directory
* **Replace the name for the project into CP[student ID]**
```
amplify init
```

2. Run this command from the root of your app directory
```
amplify add auth
```

3. Run this command from the root of your app directory
```
amplify push
```

4. Add the following imports to the top of the **app/java/com.cloudprog.example/ui/AuthenticatorActivity.java**
``` java
import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;
import com.amazonaws.mobile.auth.core.IdentityManager;
import com.amazonaws.mobile.auth.core.DefaultSignInResultHandler;
import com.amazonaws.mobile.auth.core.IdentityProvider;
import com.amazonaws.mobile.auth.ui.AuthUIConfiguration;
import com.amazonaws.mobile.auth.ui.SignInActivity;
import com.example.cloudprog.viewmodels.Injection;
```
5. Edit the **onCreate()** method of **app/java/com.cloudprog.example/ui/AuthenticatorActivity.java** as follows:
``` java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authenticator);
//Todo : Handle cognito signin
Injection.initialize(getApplicationContext());
final IdentityManager identityManager = Injection.getAWSService().getIdentityManager();
// Set up the callbacks to handle the authentication response
identityManager.login(this, new DefaultSignInResultHandler() {
@Override
public void onSuccess(Activity activity, IdentityProvider identityProvider) {
Toast.makeText(AuthenticatorActivity.this,
String.format("Logged in as %s", identityManager.getCachedUserID()),
Toast.LENGTH_LONG).show();
// Go to the main activity
final Intent intent = new Intent(activity, MainActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(intent);
activity.finish();
}
@Override
public boolean onCancel(Activity activity) {
return false;
}
});
// Start the authentication UI
AuthUIConfiguration config = new AuthUIConfiguration.Builder()
.userPools(true)
.build();
SignInActivity.startSignInActivity(this, config);
AuthenticatorActivity.this.finish();
}
```
6. Compile and Run app on Emulator

7. Create a new account and Confirm your account


8. Done! Show TA the validation results of Step 6 and 7
## Lab9-2 Create a S3 bucket
1. Add the following imports to the top of the **app/java/com.cloudprog.example/ui/MainActivity.java**
``` java
//lab9-2 import
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AccessControlList;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CreateBucketRequest;
import com.amazonaws.services.s3.model.GroupGrantee;
import com.amazonaws.services.s3.model.Permission;
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.regions.Regions;
import android.os.StrictMode;
```
2. Replace "studentID" with your student ID in **app/res/values/strings.xml**

3. Get Identity pool AWS Credentials
* AWS Console > Cognito > Federated Identities > Choose the pool of your app > Sample code in menu bar
* Copy the **Identitiy pool ID**

4. Add the Credentials and the code below to top of **onCreate()** of **app/java/com.cloudprog.example/ui/MainActivity.java**
* Remember use your **Identitiy pool ID**.
```java
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//network policy
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
// Initialize the Amazon Cognito credentials provider
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
"", // Use your Identity pool ID
Regions.US_EAST_1 // Region
);
// Initialize s3Client
final AmazonS3Client s3Client = new AmazonS3Client(credentialsProvider.getCredentials());
```
5. Add the code below to **button2.setOnClickListener()**
* Use **alt+enter** to import Toast automatically.
* If you encounter the error: "**InvalidBucketAclWithObjectOwnership**", replace "s3Client.createBucket(**createBucketRequest**);" into "s3Client.createBucket(**getString(R.string.bucket_name)**);"
``` java
button2.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//Todo : create a s3 bucket & add permission
try{
//Check bucket name in app/res/values/string.xml
AccessControlList acl = new AccessControlList();
acl.grantPermission(GroupGrantee.AllUsers, Permission.FullControl);
CreateBucketRequest createBucketRequest = new CreateBucketRequest(getString(R.string.bucket_name))
.withAccessControlList(acl).withCannedAcl(CannedAccessControlList.PublicReadWrite);
s3Client.createBucket(createBucketRequest);
Toast.makeText(MainActivity.this, "Create success", Toast.LENGTH_LONG).show();
}catch(Exception e){
e.printStackTrace();
Toast.makeText(MainActivity.this, "Create fail", Toast.LENGTH_LONG).show();
}
}
});
```
6. Add **S3FullAccess** policy to **amplify-CP[student ID]-env-XXXXXXX-authRole**

7. Done! Compile, Run, Click button and Check the bucket you created in S3.

## Lab9-3 : Upload a Object to S3
Note :
* Make sure you have finished lab9-1 and 9-2, or you may get some error in lab9-3.
* If camera on virtual device doesn't work, just close the camera and reopen it.
1. Add the following imports to the top of the **app/java/ui/CameraActivity.java**
``` java
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3Client;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
```
2. Add the Credentials and the code below to top of **onCreate()** of **app/java/com.cloudprog.example/ui/CameraActivity.java**
* Use **alt+enter** to import StrictMode automatically.
* Use your **Identitiy pool ID**.
``` java
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
this.imageView = (ImageView)this.findViewById(R.id.image_view);
//network policy
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
//CredentialsProvider initialization
CognitoCachingCredentialsProvider credentialsProvider;
credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
"", // Use your Identity Pool ID
Regions.US_EAST_1 // Region
);
//s3client initialization
final AmazonS3Client s3Client = new AmazonS3Client(credentialsProvider.getCredentials());
```
3.Add the code below to **uploadbutton.setOnClickListener()**
``` java
uploadButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//Todo : Upload a picture to S3
//create a file to write bitmap data
File f = new File(getCacheDir(), "test1.jpg");
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//Convert bitmap to byte array
Bitmap bitmap = upload_image;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file && send image to s3-bucket
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
fos.write(bitmapdata);
fos.flush();
fos.close();
s3Client.putObject(getString(R.string.bucket_name), "upload_image.jpg", f);
Toast.makeText(CameraActivity.this, "Upload success", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(CameraActivity.this, "Upload fail", Toast.LENGTH_LONG).show();
}
}
});
```
4. Done! Take a picture and upload to S3
* Open camera

* Upload Image

<!-- ## Lab9-4 Third party login
1. Follow the Lab9 slides to setup cognito and FB application
2. Add application ID and protocol_scheme in res/values/strings
protocol shceme is fb+app_id
``` java
<resources>
<string name="app_name">CloudProg</string>
<string name="bucket_name">cloudprog-hw3-studentID</string>
<string name="queue_name">cloudprog-hw3</string>
<string name="facebook_app_id">280920040359127</string>
<string name="fb_login_protocol_scheme">fb280920040359127</string>
</resources>
```
3. Add fb activities to AndroidManifest.xml
``` java
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />
<activity android:name=".ui.AuthenticatorActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<activity android:name=".ui.CameraActivity" />
<activity android:name=".ui.MainActivity">
</activity>
</application>
```
4. Add dependencies to build.gradle
``` java
// FB
implementation 'com.facebook.android:facebook-login:[5,6)'
implementation 'com.amazonaws:aws-android-sdk-auth-facebook:2.15.+@aar'
```
5. Change codes in AuthenticatorActivity.java
``` java
package com.example.cloudprog.ui;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.amazonaws.mobile.config.AWSConfiguration;
import com.example.cloudprog.R;
import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;
import com.facebook.AccessToken;
import com.amazonaws.mobile.auth.facebook.FacebookButton;
import com.amazonaws.mobile.auth.facebook.FacebookSignInProvider;
import com.amazonaws.mobile.auth.core.IdentityManager;
import com.amazonaws.mobile.auth.core.DefaultSignInResultHandler;
import com.amazonaws.mobile.auth.core.IdentityProvider;
import com.amazonaws.mobile.auth.ui.AuthUIConfiguration;
import com.amazonaws.mobile.auth.ui.SignInActivity;
import com.example.cloudprog.viewmodels.Injection;
import java.util.HashMap;
import java.util.Map;
public class AuthenticatorActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Todo : Handle cognito signin
Injection.initialize(getApplicationContext());
initializeApplication();
final IdentityManager identityAWSManager = Injection.getAWSService().getIdentityManager();
final IdentityManager identityFBManager = IdentityManager.getDefaultIdentityManager();
// FacebookSdk.sdkInitialize(getApplicationContext());
// AppEventsLogger.activateApp(this);
// AWS: Set up the callbacks to handle the authentication response
identityAWSManager.login(this, new DefaultSignInResultHandler() {
@Override
public void onSuccess(Activity activity, IdentityProvider identityProvider) {
Toast.makeText(AuthenticatorActivity.this,
String.format("Logged in as %s", identityAWSManager.getCachedUserID()),
Toast.LENGTH_LONG).show();
// Go to the function activity
final Intent intent = new Intent(activity, MainActivity.class) //MainActivity
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(intent);
activity.finish();
}
@Override
public boolean onCancel(Activity activity) {
return false;
}
}
);
// FB: Set up the callbacks to handle the authentication response
identityFBManager.login(this, new DefaultSignInResultHandler() {
@Override
public void onSuccess(Activity activity, IdentityProvider identityProvider) {
Map<String, String> logins = new HashMap<String, String>();
logins.put("graph.facebook.com", AccessToken.getCurrentAccessToken().getToken());
AccessToken accessToken = AccessToken.getCurrentAccessToken();
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();
Toast.makeText(AuthenticatorActivity.this,
String.format("Signed in with %s",
identityProvider.getDisplayName()), Toast.LENGTH_LONG).show();
// Go to the function activity
final Intent intent = new Intent(activity, MainActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(intent);
activity.finish();
}
@Override
public boolean onCancel(Activity activity) {
return false;
}
}
);
// Start the authentication UI
AuthUIConfiguration config = new AuthUIConfiguration.Builder()
.userPools(true)
.signInButton(FacebookButton.class) // Show Facebook button
.build();
SignInActivity.startSignInActivity(this, config);
AuthenticatorActivity.this.finish();
}
private void initializeApplication() {
AWSConfiguration awsConfiguration = new AWSConfiguration(getApplicationContext());
// If IdentityManager is not created, create it
if(IdentityManager.getDefaultIdentityManager() == null){
IdentityManager identityFBManager =
new IdentityManager(getApplicationContext(),awsConfiguration);
IdentityManager.setDefaultIdentityManager(identityFBManager);
}
// Add Facebook as Identity Provider
IdentityManager.getDefaultIdentityManager().addSignInProvider(
FacebookSignInProvider.class);
FacebookSignInProvider.setPermissions("public_profile");
}
}
```
7. Build and run

 -->