mirror of
https://github.com/TanelOrumaa/Estonian-ID-card-mobile-authenticator-POC.git
synced 2024-12-22 04:20:16 +02:00
MOB-40 improved authentication UX
This commit is contained in:
parent
762a8c8cc2
commit
0f6f31c995
@ -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])
|
||||
}
|
||||
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())
|
||||
}
|
||||
// If the CAN is wrong we will also delete the saved CAN so that the user won't use it again.
|
||||
else -> {
|
||||
binding!!.timeCounter.text = getString(R.string.no_success)
|
||||
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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/auth_fragment_instruction"
|
||||
@ -36,10 +36,11 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/nfc_logo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="@dimen/logo_big"
|
||||
android:layout_height="@dimen/logo_big"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="@dimen/margin"
|
||||
android:padding="@dimen/margin_huge"
|
||||
android:src="@drawable/nfc_logo" />
|
||||
|
||||
<TextView
|
||||
@ -47,7 +48,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin"
|
||||
android:textSize="@dimen/helper_text"
|
||||
android:textSize="@dimen/regular_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/auth_fragment_instruction"
|
||||
tools:text="@string/time_left" />
|
||||
|
||||
@ -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" />
|
||||
|
||||
|
@ -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">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/can_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp"
|
||||
android:layout_margin="@dimen/margin"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -27,33 +27,23 @@
|
||||
<TextView
|
||||
android:id="@+id/result_text"
|
||||
android:text="@string/result_text"
|
||||
android:textSize="20sp"
|
||||
android:padding="12dp"
|
||||
android:layout_marginVertical="6dp"
|
||||
android:textSize="@dimen/regular_text"
|
||||
android:padding="@dimen/padding_small"
|
||||
android:layout_marginVertical="@dimen/margin_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_info_text"
|
||||
android:text="@string/result_info"
|
||||
android:padding="12dp"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginVertical="6dp"
|
||||
android:padding="@dimen/padding_small"
|
||||
android:textSize="@dimen/regular_text"
|
||||
android:layout_marginVertical="@dimen/margin_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/result_back_button"
|
||||
android:text="@string/return_text"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginVertical="6dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -99,4 +99,5 @@
|
||||
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
||||
<string name="id_card_removed_early">ID card was removed too early</string>
|
||||
<string name="try_again">Try Again</string>
|
||||
<string name="wrong_pin">Wrong PIN 1. Tries on the card left %s</string>
|
||||
</resources>
|
@ -97,4 +97,5 @@
|
||||
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
||||
<string name="id_card_removed_early">ID card was removed too early</string>
|
||||
<string name="try_again">Try Again</string>
|
||||
<string name="wrong_pin">Wrong PIN 1. Tries on the card left %s</string>
|
||||
</resources>
|
@ -10,4 +10,5 @@
|
||||
<dimen name="regular_text">24sp</dimen>
|
||||
<dimen name="headline_text">32sp</dimen>
|
||||
<dimen name="helper_text">16sp</dimen>
|
||||
<dimen name="logo_big">128dp</dimen>
|
||||
</resources>
|
@ -97,4 +97,5 @@
|
||||
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
||||
<string name="id_card_removed_early">ID card was removed too early</string>
|
||||
<string name="try_again">Try Again</string>
|
||||
<string name="wrong_pin">Wrong PIN 1. Tries on the card left %s</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user