How to sign in a user with AWS Amplify on Android + Kotlin? - android

I'm trying to make an Android app with a sign in screen on Android in Kotlin using AWS Amplify, here's my sign in code:
AWSMobileClient.getInstance().signIn(username, password, null, object : Callback<SignInResult> {
override fun onResult(signInResult: SignInResult) {
runOnUiThread {
Log.d("DEBUG", "Sign-in callback state: " + signInResult.signInState)
when (signInResult.signInState) {
SignInState.DONE -> Log.d("DEBUG", "Sign-in done.")
SignInState.SMS_MFA -> Log.d("DEBUG", "Please confirm sign-in with SMS.")
SignInState.NEW_PASSWORD_REQUIRED -> Log.d("DEBUG", "Please confirm sign-in with new password.")
else -> Log.d("DEBUG", "Unsupported sign-in confirmation: " + signInResult.signInState)
}
}
}
override fun onError(e: Exception) {
Log.e("DEBUG", "Sign-in error", e)
}
})
I used the documentation of Amazon here, copied and pasted the block found at the Sign In chapter into Android Studio that automatically converted the Java code into Kotlin.
Using logs I see that my code above this one is executed when I press the login button but the onResult block is never called. The logs only print a D/AWSMobileClient: Sending password. from AWS sdk.
I remember that this code worked before Christmas holidays so I think that it's maybe a change on the Amazon side but I find nothing in the documentation.
Do you have any idea of what's wrong here ?

Related

Amplify.Storage.** does not work for me on Android

I am using AWS Amplify to make an Android app. I followed the official tutorial to add Authentication, API, and Storage. https://aws.amazon.com/getting-started/hands-on/build-android-app-amplify/module-one/ . But when I run Amplify.Storage.** it doesn't respond at all. There is no error message so I cannot track the issue. Does anyone have suggestions as to what might be wrong?
This is my uploadFile() function:
fun storeAudio(filePath: String, key: String) {
val file = File(filePath)
val options = StorageUploadFileOptions.builder()
.accessLevel(StorageAccessLevel.PROTECTED)
.build()
scope.launch {
Amplify.Storage.uploadFile(
key,
file,
options,
{ progress -> Log.i(TAG, "Fraction completed: ${progress.fractionCompleted}") },
{ result -> Log.i(TAG, "Successfully uploaded: " + result.key) },
{ error -> Log.e(TAG, "Upload failed", error) }
)
}
}
Amplify is configured properly. And my amplifyconfiguration.json file looks correct, but let me know if you need to take a look at it.

do I need to use try and catch in Firebase authentication codes in Kotlin - Android

Do I need to use try and catch in Firebase authentication codes in Kotlin? i.e. in here or similar places you know as experts the goal is to prevent the crashes:
fun handleFirebaseAuthWithGoogle(idToken: String) {
val credential = GoogleAuthProvider.getCredential(idToken, null)
FirebaseAuthRepository().auth.signInWithCredential(credential)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
_isNewUser.value = task.result.additionalUserInfo?.isNewUser
// Sign in success, update UI with the signed-in user's information
Log.d(LoginFragment.TAG, "signInWithCredential:success")
FirebaseAuthRepository().getCurrentUser {
_authWithGoogle.value = it
}
} else {
// If sign in fails, display a message to the user.
Log.w(LoginFragment.TAG, "signInWithCredential:failure", task.exception)
}
}
}
also here:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
// Google Sign In was successful, authenticate with Firebase
val account = task.getResult(ApiException::class.java)!!
Log.d(TAG, "firebaseAuthWithGoogle:" + account.id)
viewModel.handleFirebaseAuthWithGoogle(account.idToken!!)
UiUtils.showSnackBar(requireView(), "Google sign in Succeed", 0)
} catch (e: ApiException) {
// Google Sign In failed, update UI appropriately
Log.w(TAG, "Google sign in failed", e)
hideProgress()
UiUtils.showErrorSnackBar(requireView(), "Google sign in failed", 0)
}
}
}
When you are attempting to implement an authentication mechanism, there are multiple operations that can go wrong. In such cases, we always need to handle the Exceptions.
In your second snippet code, it makes sense to use a try-catch to handle the ApiException, while in the first it doesn't. When you deal with Firebase services, you can get a successful operation or an Exception, never both. It's one or the other. So if the task is successful, then you are successfully authenticated, otherwise, you get an Exception. You can get the corresponding Exception by calling getException() method on the Task object. So there is no need to use a try-catch here because your app won't crash in case of an Exception.
You can use .addOnSuccessListener and .addOnFailureListener to handle the different FirebaseExceptions which can be thrown while authentication.

How To Replace OnActivityResult With New Activity Result API With Parse-SDK

I wonder if someone may be able to assist with my struggles, I apologise as I’m new to Kotlin.
After implementing facebook login following the parse-sdk-android documentation I have realised that onActivityResult() is deprecated (though it still works for the timebeing).
I am trying to adapt my code to work with the new Activity Result API’s (I saw a previous suggestion to use registerForActivityResult) however, my issue is that we are only calling the method ParseFacebookUtils.logInWithReadPermissionsInBackground in the code and the activity being called is nested within this method.
I attempted to use registerForActivityResult to start the activity containing this method however it will only capture the result of the activity started and not that of the nested activity within ParseFacebookUtils.logInWithReadPermissionsInBackground (which is the expected behaviour). Online searches have not brought back any results for a way to implement this for parse-sdk-android.
So my question is whether there is a way to capture the result of the nested activity using just the method ? without being able to change the nested code.
My code for logging in currently is as below:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loginFacebook()
}
private fun loginFacebook(){
val permissions: List<String> = listOf("public_profile", "email")
ParseFacebookUtils.logInWithReadPermissionsInBackground(this,permissions) { user: ParseUser?, err: ParseException? ->
when {
err != null -> {
Log.e("FacebookLoginExample", "done: ", err)
Toast.makeText(this, err.message, Toast.LENGTH_LONG).show()
}
user == null -> {
Toast.makeText(this, "The user cancelled the Facebook login.", Toast.LENGTH_LONG).show()
Log.d("FacebookLoginExample", "Uh oh. The user cancelled the Facebook login.")
}
user.isNew -> {
Toast.makeText(this, "User signed up and logged in through Facebook.", Toast.LENGTH_LONG).show()
Log.d("FacebookLoginExample", "User signed up and logged in through Facebook!")
getUserDetailFromFB()
}
else -> {
Toast.makeText(this, "User logged in through Facebook.", Toast.LENGTH_LONG).show()
Log.d("FacebookLoginExample", "User logged in through Facebook!")
showAlert("Oh, you!", "Welcome back!")
}
}
}
}

AWS auth seesion not keeping alive when we close the android application

I'm using AWS Amplify SDK for Cognito integration. Actually, I successfully integrated user sign in and sign up flows based on the documentation available here. However, after the successful login if we restart the app the user session is not persisting. Amplify.Auth.fetchAuthSession() always returns isSignedIn as false. I have no idea where I'm making a problem. Please find the 'sign in' snippet below.
fun onSingIn(view: View) {
Amplify.Auth.signIn(
email.value,
password.value,
{ result ->
Log.i(TAG, if (result.isSignInComplete) "Sign in succeeded" else "Sign in not complete")
if (result.isSignInComplete) {
view.context.let {
it.startActivity(Intent(it, FeedActivity::class.java))
signInStatus.postValue(true)
}
}
},
{ error ->
view.context.let {
var message = it.getString(R.string.something_went_wrong)
when (error.cause) {
is UserNotConfirmedException ->{
email.value?.let {emailAddress ->
val direction =LoginFragmentDirections
.actionLoginFragmentToEmailVerificationCodeFragment(emailAddress)
view.findNavController().navigate(direction)
}
}
is UserNotFoundException ->
message = it.getString(R.string.credentilas_incorrect)
else->
viewModelScope.launch(Dispatchers.Main) { it.showToast(message) }
}
Log.e(TAG, error.toString())
}
}
)
}
Finally resolved the issue. The problem was related user pool app client settings configurations. I haven't checked identity providers inside app client settings. After choosing 'Cognito User Pool' as an identity provider the login session stayed alive without any issues. Hope this answer will help someone facing a similar issue.

Android: AWS Amplify User State is not getting update

I have just started learning AWS Amplify and I am integrating it to my android project to authenticate users. I have successfully logged-in but UserState is still SIGNED_OUT.
AWSMobileClient.getInstance().signIn(userName, password, null, callback)
Callback Code snippet
fun fetchAuthenticationCallBack(): Callback<SignInResult> {
return object : Callback<SignInResult> {
override fun onResult(result: SignInResult?) {
when (result?.signInState) {
SignInState.DONE -> {
// AWSMobileClient.getInstance().confirmSignIn()
Log.d(TAG, "LOGIN SUCCESS ${AWSMobileClient.getInstance().tokens.accessToken}")
}
SignInState.NEW_PASSWORD_REQUIRED -> {
Log.d(TAG, "NEW PASSWORD CHALLENGE")
}
else -> {
// Unsupported sign-in confirmation:
}
}
}
override fun onError(e: java.lang.Exception?) {
TODO("Not yet implemented")
}
}
}
I want to get the accessToken but it gives me Exception
Token does not support retrieving while user is SIGN_OUT
Is there anything that I am missing in the authentication part?
If anyone will face this issue in the future.
Kindly check your awsconfiguration.json file there is something went wrong. In my case CognitoIdentity credentials were wrong. I have just fixed the awsconfiguration.json file everything is working as expected

Categories

Resources