From 0f6f31c99518133a7aa0f078429fc01d9573f06f Mon Sep 17 00:00:00 2001 From: Henrik Lepson Date: Thu, 25 Nov 2021 18:09:45 +0200 Subject: [PATCH] MOB-40 improved authentication UX --- .../mobileauthapp/AuthFragment.kt | 98 +++++++++---------- .../mobileauthapp/HomeFragment.kt | 2 + .../mobileauthapp/ResultFragment.kt | 25 +++-- .../app/src/main/res/layout/fragment_auth.xml | 11 ++- .../src/main/res/layout/fragment_result.xml | 26 ++--- .../app/src/main/res/values-en/strings.xml | 1 + .../app/src/main/res/values-et/strings.xml | 1 + .../app/src/main/res/values/dimens.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + 9 files changed, 79 insertions(+), 87 deletions(-) diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt index bff62f4..8dfdfd7 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/AuthFragment.kt @@ -4,6 +4,7 @@ import android.app.Activity import android.content.Context import android.content.Intent import android.nfc.NfcAdapter +import android.nfc.TagLostException import android.nfc.tech.IsoDep import android.os.Bundle import android.os.CountDownTimer @@ -69,12 +70,33 @@ class AuthFragment : Fragment() { goToTheStart() } }.start() - //binding!!.nextButton.visibility = View.INVISIBLE + binding!!.nextButton.visibility = View.GONE binding!!.nextButton.setOnClickListener { goToNextFragment() } binding!!.cancelButton.setOnClickListener { goToTheStart() } val adapter = NfcAdapter.getDefaultAdapter(activity) if (adapter != null) getInfoFromIdCard(adapter) + else { // If we don't have access to an NFC adapter then we can't detect an ID card, maybe should tell the user reason as well + goToTheStart() + } + } + + private fun goToNextFragment() { + timer.cancel() + val action = AuthFragmentDirections.actionAuthFragmentToResultFragment(mobile = args.mobile) + findNavController().navigate(action) + } + + private fun goToTheStart() { + viewModel.clearUserInfo() + timer.cancel() + if (args.mobile) { + val resultIntent = Intent() + requireActivity().setResult(AppCompatActivity.RESULT_CANCELED, resultIntent) + requireActivity().finish() + } else { + requireActivity().finishAndRemoveTask() + } } private fun getInfoFromIdCard(adapter: NfcAdapter) { @@ -88,33 +110,34 @@ class AuthFragment : Fragment() { card.use { try { val comms = Comms(it, viewModel.userCan) - if (args.auth) { - val jws = Authenticator(comms).authenticate( - intentParameters.challenge, - intentParameters.origin, - viewModel.userPin - ) - intentParameters.setToken(jws) - } else { - val response = comms.readPersonalData(byteArrayOf(1, 2, 6, 3, 4, 8)) - viewModel.setUserFirstName(response[1]) - viewModel.setUserLastName(response[0]) - viewModel.setUserIdentificationNumber(response[2]) - viewModel.setGender(response[3]) - viewModel.setCitizenship(response[4]) - viewModel.setExpiration(response[5]) - } + val jws = Authenticator(comms).authenticate( + intentParameters.challenge, + intentParameters.origin, + viewModel.userPin + ) + intentParameters.setToken(jws) requireActivity().runOnUiThread { - binding!!.timeCounter.text = getString(R.string.data_read) + goToNextFragment() } } catch (e: Exception) { - requireActivity().runOnUiThread { - binding!!.timeCounter.text = getString(R.string.no_success) + when(e) { + is TagLostException -> requireActivity().runOnUiThread { binding!!.timeCounter.text = getString(R.string.id_card_removed_early) } + else -> { + when ("invalid pin") { + in e.message.toString().lowercase() -> requireActivity().runOnUiThread { + val messagePieces = e.message.toString().split(" ") + binding!!.timeCounter.text = getString(R.string.wrong_pin, messagePieces[messagePieces.size - 1]) + viewModel.deletePin(requireContext()) + } + else -> { + binding!!.timeCounter.text = getString(R.string.no_success) + viewModel.deleteCan(requireContext()) + } + } + } } - // If the CAN is wrong we will also delete the saved CAN so that the user won't use it again. - viewModel.deleteCan(requireContext()) - // Gives user some time to read the error message - Thread.sleep(1000) + // Give user some time to read the error message + Thread.sleep(2000) goToTheStart() } finally { adapter.disableReaderMode(activity) @@ -123,33 +146,6 @@ class AuthFragment : Fragment() { }, NfcAdapter.FLAG_READER_NFC_A, null) } - private fun goToNextFragment() { - timer.cancel() - if (args.auth) { - val action = AuthFragmentDirections.actionAuthFragmentToResultFragment(mobile = args.mobile) - findNavController().navigate(action) - } else { - findNavController().navigate(R.id.action_authFragment_to_userFragment) - } - } - - private fun goToTheStart() { - viewModel.clearUserInfo() - timer.cancel() - if (args.reading) { - findNavController().navigate(R.id.action_authFragment_to_homeFragment) - } else { - if (!args.mobile) { - //Currently for some reason the activity is not killed entirely. Must be looked into further. - requireActivity().finishAndRemoveTask() - } else { - val resultIntent = Intent() - requireActivity().setResult(AppCompatActivity.RESULT_CANCELED, resultIntent) - requireActivity().finish() - } - } - } - override fun onDestroy() { super.onDestroy() binding = null diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt index aea295f..b63a06f 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/HomeFragment.kt @@ -78,6 +78,8 @@ class HomeFragment : Fragment() { /** * Method that starts the authentication use case. + * + * NOTE: Comment out try-catch block when testing without backend */ private fun startAuthentication(mobile: Boolean) { try { diff --git a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt index e658c72..b891bc5 100644 --- a/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt +++ b/MobileAuthApp/app/src/main/java/com/tarkvaraprojekt/mobileauthapp/ResultFragment.kt @@ -39,10 +39,21 @@ class ResultFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding!!.resultBackButton.visibility = View.GONE postToken() } + /** + * Only used when the MobileAuthApp was launched by an app. Not for website use. + */ + private fun createResponse(success: Boolean = true, result: String = "noResult", token: String = "noToken") { + val responseCode = if (success) AppCompatActivity.RESULT_OK else AppCompatActivity.RESULT_CANCELED + val resultIntent = Intent() + resultIntent.putExtra("result", result) + resultIntent.putExtra("token", token) + requireActivity().setResult(responseCode, resultIntent) + requireActivity().finish() + } + /** * Makes a POST request to the backend server with a tokenItem */ @@ -77,18 +88,6 @@ class ResultFragment : Fragment() { } } - /** - * Only used when the MobileAuthApp was launched by an app. Not for website use. - */ - private fun createResponse(success: Boolean = true, result: String = "noResult", token: String = "noToken") { - val responseCode = if (success) AppCompatActivity.RESULT_OK else AppCompatActivity.RESULT_CANCELED - val resultIntent = Intent() - resultIntent.putExtra("result", result) - resultIntent.putExtra("token", token) - requireActivity().setResult(responseCode, resultIntent) - requireActivity().finish() - } - override fun onDestroy() { super.onDestroy() binding = null diff --git a/MobileAuthApp/app/src/main/res/layout/fragment_auth.xml b/MobileAuthApp/app/src/main/res/layout/fragment_auth.xml index 3da81db..7730d12 100644 --- a/MobileAuthApp/app/src/main/res/layout/fragment_auth.xml +++ b/MobileAuthApp/app/src/main/res/layout/fragment_auth.xml @@ -23,7 +23,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:padding="@dimen/padding"> + android:padding="@dimen/padding_small"> @@ -72,9 +73,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_big" + android:layout_marginStart="@dimen/padding_tiny" android:text="@string/cancel_text" android:textSize="@dimen/regular_text" - app:layout_constraintEnd_toStartOf="@id/next_button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/card_view" /> diff --git a/MobileAuthApp/app/src/main/res/layout/fragment_result.xml b/MobileAuthApp/app/src/main/res/layout/fragment_result.xml index 1bff4c1..dc9a975 100644 --- a/MobileAuthApp/app/src/main/res/layout/fragment_result.xml +++ b/MobileAuthApp/app/src/main/res/layout/fragment_result.xml @@ -4,14 +4,14 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:padding="24dp" + android:padding="@dimen/padding" tools:context=".ResultFragment"> -