diff --git a/.idea/copilot/chatSessions/blobs/version b/.idea/copilot/chatSessions/blobs/version new file mode 100644 index 0000000000000000000000000000000000000000..720d64f4baafc33efdf971f02084aca5f25b34a5 Binary files /dev/null and b/.idea/copilot/chatSessions/blobs/version differ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 591428e16423cfd5eea6981d8c22dd7293fa8c37..019d1264550b79c477d85b8b7dbca22dbd473d66 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { implementation(libs.androidx.navigation.ui.ktx) implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation("androidx.security:security-crypto:1.1.0-alpha06") testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/java/com/example/myapplication/LoginActivity.kt b/app/src/main/java/com/example/myapplication/LoginActivity.kt index 9776f0c5ff177f86c5630fa15c62aa1209c9d74e..551b78bed9725344a57cac64f6693be38a350f5d 100644 --- a/app/src/main/java/com/example/myapplication/LoginActivity.kt +++ b/app/src/main/java/com/example/myapplication/LoginActivity.kt @@ -1,33 +1,32 @@ package com.example.myapplication +import android.content.Context +import android.content.SharedPreferences import android.os.Bundle import android.util.Log import android.widget.Button -import com.google.android.material.bottomnavigation.BottomNavigationView import androidx.appcompat.app.AppCompatActivity -import androidx.navigation.findNavController -import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.setupActionBarWithNavController -import androidx.navigation.ui.setupWithNavController import com.example.myapplication.databinding.ActivityLoginBinding -import com.example.myapplication.databinding.ActivityMainBinding import com.example.myapplication.repository.AuthRepository import com.example.myapplication.ui.login.UserViewModel import com.example.myapplication.util.LoginListener +import com.example.myapplication.util.SecretPreference class LoginActivity : AppCompatActivity() , LoginListener { private lateinit var binding: ActivityLoginBinding private var userViewModel : UserViewModel = UserViewModel() - private var authRepository : AuthRepository = AuthRepository(this) + private lateinit var secretPreference : SecretPreference + private lateinit var authRepository : AuthRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + secretPreference = SecretPreference(this) + authRepository = AuthRepository(this, secretPreference) + binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) - - } override fun onStart() { @@ -44,6 +43,8 @@ class LoginActivity : AppCompatActivity() , LoginListener { override fun onLoginSuccess() { userViewModel.setUser(binding.emailInput.text.toString(), binding.passwordInput.text.toString()) Log.d("Development", "Activity: Login success") + val preference : SharedPreferences = getSharedPreferences("secret_shared_prefs", MODE_PRIVATE) + Log.d("Development", "Activity: Token: ${preference.getString("token", null)}\nPref: ${secretPreference.getToken()}") finish() } diff --git a/app/src/main/java/com/example/myapplication/backendconnect/BackendService.kt b/app/src/main/java/com/example/myapplication/backendconnect/BackendService.kt index f759e9c8b97fa53b1e6b02ceb0937b0daa5d2d1f..fa10fd0b88a21d86796bdb4df5dfde4c80c5ec6f 100644 --- a/app/src/main/java/com/example/myapplication/backendconnect/BackendService.kt +++ b/app/src/main/java/com/example/myapplication/backendconnect/BackendService.kt @@ -5,7 +5,7 @@ import com.example.myapplication.model.auth.UserCred import retrofit2.Call import retrofit2.http.Body import retrofit2.http.POST -import java.net.PasswordAuthentication + interface BackendService { @POST("auth/login") diff --git a/app/src/main/java/com/example/myapplication/repository/AuthRepository.kt b/app/src/main/java/com/example/myapplication/repository/AuthRepository.kt index 12787498a5ab0fc15a61414f1cc26d99c4b0201d..139f5ad9618c67254bbe83e49f8acac7f48657c7 100644 --- a/app/src/main/java/com/example/myapplication/repository/AuthRepository.kt +++ b/app/src/main/java/com/example/myapplication/repository/AuthRepository.kt @@ -1,15 +1,19 @@ package com.example.myapplication.repository +import android.content.Context import android.util.Log import com.example.myapplication.backendconnect.Client import com.example.myapplication.model.auth.Token import com.example.myapplication.model.auth.UserCred import com.example.myapplication.util.LoginListener +import com.example.myapplication.util.SecretPreference import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class AuthRepository (private val loginListener: LoginListener) { +class AuthRepository ( + private val loginListener: LoginListener, + private val secretPreference: SecretPreference) { fun loginRequest(email: String, password: String){ Log.d("Development", "Login request to backend service") @@ -18,20 +22,23 @@ class AuthRepository (private val loginListener: LoginListener) { override fun onResponse(call: Call<Token>, response: Response<Token>) { Log.d("Development", "Response: ${response.body()}") if (response.isSuccessful) { - val token = response.body() + val token : Token? = response.body() Log.d("Development", "Successful Login\nToken: ${token?.token}") + + // store the token ONLY, not the Token object + secretPreference.saveToken(token?.token ?: "") + + // callback the loginActivity loginListener.onLoginSuccess() - // TODO: Save token to shared preferences + } else { Log.d("Development", "LOGIN FAILED, http code : ${response.code()}") - // Handle error loginListener.onLoginFailure() } } override fun onFailure(call: Call<Token>, t: Throwable) { Log.d("Development", "LOGIN FAILED, error on delivery : ${t.message}") - // Handle error loginListener.onLoginFailure() } } diff --git a/app/src/main/java/com/example/myapplication/ui/login/UserViewModel.kt b/app/src/main/java/com/example/myapplication/ui/login/UserViewModel.kt index f1d90ec8a86e10665cf6fcaafc4dfafa1e5764e2..872fa416554176a23338f5bd631415e43a5f7fcc 100644 --- a/app/src/main/java/com/example/myapplication/ui/login/UserViewModel.kt +++ b/app/src/main/java/com/example/myapplication/ui/login/UserViewModel.kt @@ -1,10 +1,8 @@ package com.example.myapplication.ui.login -import android.app.Application -import androidx.lifecycle.AndroidViewModel + import androidx.lifecycle.ViewModel -import com.example.myapplication.repository.AuthRepository -import com.example.myapplication.util.LoginListener + class UserViewModel() : ViewModel(){ var email: String = "" diff --git a/app/src/main/java/com/example/myapplication/util/SecretPreference.kt b/app/src/main/java/com/example/myapplication/util/SecretPreference.kt new file mode 100644 index 0000000000000000000000000000000000000000..e0fd205f8288888970b764b9cbc80732e2388b7d --- /dev/null +++ b/app/src/main/java/com/example/myapplication/util/SecretPreference.kt @@ -0,0 +1,28 @@ +package com.example.myapplication.util + +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKey +import android.content.Context +import android.util.Log + +class SecretPreference (private val context: Context) { + + private val masterKey = MasterKey.Builder(context) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build() + + private val sharedPreferences = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM) + + fun saveToken(token: String){ + sharedPreferences.edit().putString("token", token).apply() + Log.i("Development", "Token saved") + } + + fun getToken(): String? = sharedPreferences.getString("token", null) + +} \ No newline at end of file