diff --git a/app/src/main/java/com/example/bondoman/data/repositories/UserRepository.kt b/app/src/main/java/com/example/bondoman/data/repositories/UserRepository.kt
index 68acf1a760e58348de90897edf2e6f898d1991d6..2c5283b39f5eddba072ac60846b0d815131b6ce7 100644
--- a/app/src/main/java/com/example/bondoman/data/repositories/UserRepository.kt
+++ b/app/src/main/java/com/example/bondoman/data/repositories/UserRepository.kt
@@ -2,6 +2,7 @@ package com.example.bondoman.data.repositories
 
 import com.example.bondoman.networks.requests.LoginRequest
 import com.example.bondoman.networks.responses.LoginResponse
+import com.example.bondoman.networks.responses.TokenResponse
 import com.example.bondoman.networks.services.UserService
 import retrofit2.Response
 
@@ -9,4 +10,8 @@ class UserRepository (private val service: UserService) {
 	suspend fun login(email: String, password: String): Response<LoginResponse> {
 		return service.login(LoginRequest(email, password))
 	}
+
+	suspend fun checkToken(): Response<TokenResponse> {
+		return service.checkToken()
+	}
 }
diff --git a/app/src/main/java/com/example/bondoman/data/utils/PreferencesManager.kt b/app/src/main/java/com/example/bondoman/data/utils/PreferencesManager.kt
index 789e1cf2fafe74954312ead666ca048b9efa7b20..7df9205a5334716dd6505e01134a9f0d280d2290 100644
--- a/app/src/main/java/com/example/bondoman/data/utils/PreferencesManager.kt
+++ b/app/src/main/java/com/example/bondoman/data/utils/PreferencesManager.kt
@@ -25,4 +25,57 @@ object PreferencesManager {
 			EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
 		)
 	}
+
+	fun putString(context: Context, key: String, value: String, encrypted: Boolean = false) {
+		val editor = if (encrypted) {
+			getEncryptedSharedPreferences(context).edit()
+		} else {
+			getSharedPreferences(context).edit()
+		}
+
+		editor.putString(key, value)
+		editor.apply()
+	}
+
+	fun getString(context: Context, key: String, encrypted: Boolean = false): String? {
+		val sharedPreferences = if (encrypted) {
+			getEncryptedSharedPreferences(context)
+		} else {
+			getSharedPreferences(context)
+		}
+
+		return sharedPreferences.getString(key, null)
+	}
+
+	fun putBoolean(context: Context, key: String, value: Boolean, encrypted: Boolean = false) {
+		val editor = if (encrypted) {
+			getEncryptedSharedPreferences(context).edit()
+		} else {
+			getSharedPreferences(context).edit()
+		}
+
+		editor.putBoolean(key, value)
+		editor.apply()
+	}
+
+	fun getBoolean(context: Context, key: String, encrypted: Boolean = false): Boolean {
+		val sharedPreferences = if (encrypted) {
+			getEncryptedSharedPreferences(context)
+		} else {
+			getSharedPreferences(context)
+		}
+
+		return sharedPreferences.getBoolean(key, false)
+	}
+
+	fun remove(context: Context, key: String, encrypted: Boolean = false) {
+		val editor = if (encrypted) {
+			getEncryptedSharedPreferences(context).edit()
+		} else {
+			getSharedPreferences(context).edit()
+		}
+
+		editor.remove(key)
+		editor.apply()
+	}
 }
diff --git a/app/src/main/java/com/example/bondoman/data/viewmodels/login/LoginViewModel.kt b/app/src/main/java/com/example/bondoman/data/viewmodels/login/LoginViewModel.kt
index 9f085ca1e9feab84fd957a914a7062bb383209b2..e7b5618840222f27174e9ed3c3f6dfb94dd8b946 100644
--- a/app/src/main/java/com/example/bondoman/data/viewmodels/login/LoginViewModel.kt
+++ b/app/src/main/java/com/example/bondoman/data/viewmodels/login/LoginViewModel.kt
@@ -6,22 +6,39 @@ import androidx.lifecycle.viewModelScope
 import com.example.bondoman.data.repositories.UserRepository
 import com.example.bondoman.networks.RetrofitClient
 import com.example.bondoman.networks.responses.LoginResponse
+import com.example.bondoman.networks.responses.TokenResponse
 import com.example.bondoman.networks.services.UserService
 import kotlinx.coroutines.launch
 
 class LoginViewModel : ViewModel() {
-	private val _response = MutableLiveData<LoginResponse>()
-	val response = _response
+	private val _loginResponse = MutableLiveData<LoginResponse>()
+	val loginResponse = _loginResponse
+
+	private val _tokenResponse = MutableLiveData<TokenResponse>()
+	val tokenResponse = _tokenResponse
 
 	fun login(email: String, password: String) {
 		viewModelScope.launch {
-			val repository = UserRepository(RetrofitClient().instance.create(UserService::class.java))
+			val repository = UserRepository(RetrofitClient.getInstance().create(UserService::class.java))
 			val loginResponse = repository.login(email, password)
 
 			if (loginResponse.isSuccessful) {
-				_response.value = loginResponse.body()
+				_loginResponse.value = loginResponse.body()
+			} else {
+				_loginResponse.value = LoginResponse(null, loginResponse.errorBody()?.string() ?: "Unknown error")
+			}
+		}
+	}
+
+	fun checkToken(bearerToken: String) {
+		viewModelScope.launch {
+			val repository = UserRepository(RetrofitClient.getInstanceWithAuth(bearerToken).create(UserService::class.java))
+			val tokenResponse = repository.checkToken()
+
+			if (tokenResponse.isSuccessful) {
+				_tokenResponse.value = tokenResponse.body()
 			} else {
-				_response.value = LoginResponse(null, loginResponse.errorBody()?.string() ?: "Unknown error")
+				_tokenResponse.value = TokenResponse("", 0, 0, tokenResponse.errorBody()?.string() ?: "Unknown error")
 			}
 		}
 	}
diff --git a/app/src/main/java/com/example/bondoman/networks/RetrofitClient.kt b/app/src/main/java/com/example/bondoman/networks/RetrofitClient.kt
index e42a3ac9af5949fdd0c8c99b18889ec43004ddbd..fd17a0c05fa348fb88f6f30d3d09fe02d643b374 100644
--- a/app/src/main/java/com/example/bondoman/networks/RetrofitClient.kt
+++ b/app/src/main/java/com/example/bondoman/networks/RetrofitClient.kt
@@ -1,21 +1,46 @@
 package com.example.bondoman.networks
 
+import com.example.bondoman.networks.interceptors.AuthInterceptor
 import com.squareup.moshi.Moshi
 import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
+import okhttp3.OkHttpClient
 import retrofit2.Retrofit
 import retrofit2.converter.moshi.MoshiConverterFactory
 
-class RetrofitClient {
-	private val baseUrl = "https://pbd-backend-2024.vercel.app/"
+object RetrofitClient {
+	private const val BASE_URL = "https://pbd-backend-2024.vercel.app/"
 
-	val instance: Retrofit by lazy {
-		val moshi = Moshi.Builder()
-			.add(KotlinJsonAdapterFactory())
-			.build()
+	private val moshi = Moshi.Builder()
+		.add(KotlinJsonAdapterFactory())
+		.build()
 
-		Retrofit.Builder()
-			.baseUrl(baseUrl)
-			.addConverterFactory(MoshiConverterFactory.create(moshi))
-			.build()
+	private var instance: Retrofit? = null
+	private var instanceWithAuth: Retrofit? = null
+
+	fun getInstance(): Retrofit {
+		if (instance == null) {
+			instance = Retrofit.Builder()
+				.baseUrl(BASE_URL)
+				.addConverterFactory(MoshiConverterFactory.create(moshi))
+				.build()
+		}
+
+		return instance!!
+	}
+
+	fun getInstanceWithAuth(bearerToken: String): Retrofit {
+		if (instanceWithAuth == null) {
+			val client = OkHttpClient.Builder()
+				.addInterceptor(AuthInterceptor(bearerToken))
+				.build()
+
+			instanceWithAuth = Retrofit.Builder()
+				.baseUrl(BASE_URL)
+				.addConverterFactory(MoshiConverterFactory.create(moshi))
+				.client(client)
+				.build()
+		}
+
+		return instanceWithAuth!!
 	}
 }
diff --git a/app/src/main/java/com/example/bondoman/networks/interceptors/AuthInterceptor.kt b/app/src/main/java/com/example/bondoman/networks/interceptors/AuthInterceptor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c3d8dc12c094fb584b80d71485f3ee04b3dd21d9
--- /dev/null
+++ b/app/src/main/java/com/example/bondoman/networks/interceptors/AuthInterceptor.kt
@@ -0,0 +1,16 @@
+package com.example.bondoman.networks.interceptors
+
+import okhttp3.Interceptor
+import okhttp3.Response
+
+class AuthInterceptor(private val bearerToken: String) : Interceptor {
+
+	override fun intercept(chain: Interceptor.Chain): Response {
+		val request = chain.request()
+		val newRequest = request.newBuilder()
+			.addHeader("Authorization", "Bearer $bearerToken")
+			.build()
+
+		return chain.proceed(newRequest)
+	}
+}
diff --git a/app/src/main/java/com/example/bondoman/networks/responses/TokenResponse.kt b/app/src/main/java/com/example/bondoman/networks/responses/TokenResponse.kt
index 2779b5cb43e28f87d300bebc9bb23ff855c896c2..09e84fe009aa2f46494c11acad7f3d29938adb85 100644
--- a/app/src/main/java/com/example/bondoman/networks/responses/TokenResponse.kt
+++ b/app/src/main/java/com/example/bondoman/networks/responses/TokenResponse.kt
@@ -4,11 +4,13 @@ import com.squareup.moshi.Json
 
 data class TokenResponse(
 	@Json(name = "nim")
-	val nim: String,
+	val nim: String?,
 
 	@Json(name = "iat")
-	val iat: Int,
+	val iat: Int?,
 
 	@Json(name = "exp")
-	val exp: Int,
+	val exp: Int?,
+
+	val error: String? = null
 )
diff --git a/app/src/main/java/com/example/bondoman/networks/services/UserService.kt b/app/src/main/java/com/example/bondoman/networks/services/UserService.kt
index 8e172e322c4c888efae8ae3b1c7dcae02d75a291..1bea68903544d27fddb88454a67acbbd7ce8f4c6 100644
--- a/app/src/main/java/com/example/bondoman/networks/services/UserService.kt
+++ b/app/src/main/java/com/example/bondoman/networks/services/UserService.kt
@@ -2,6 +2,7 @@ package com.example.bondoman.networks.services
 
 import com.example.bondoman.networks.requests.LoginRequest
 import com.example.bondoman.networks.responses.LoginResponse
+import com.example.bondoman.networks.responses.TokenResponse
 import retrofit2.Response
 import retrofit2.http.Body
 import retrofit2.http.POST
@@ -9,4 +10,7 @@ import retrofit2.http.POST
 interface UserService {
 	@POST("/api/auth/login")
 	suspend fun login(@Body request: LoginRequest): Response<LoginResponse>
+
+	@POST("/api/auth/token")
+	suspend fun checkToken(): Response<TokenResponse>
 }
diff --git a/app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt b/app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt
index 62cd75c50e5277e8c4bf78863996d9dc1c1c2c15..8acdbca3cc4f29efa90f5f0ce992e991d07d51dc 100644
--- a/app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt
+++ b/app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt
@@ -2,6 +2,7 @@ package com.example.bondoman.views.activities
 
 import android.content.Intent
 import android.os.Bundle
+import android.util.Log
 import android.widget.Toast
 import androidx.activity.viewModels
 import androidx.appcompat.app.AppCompatActivity
@@ -11,6 +12,7 @@ import com.example.bondoman.R
 import com.example.bondoman.data.utils.PreferencesManager
 import com.example.bondoman.data.viewmodels.login.LoginViewModel
 import com.example.bondoman.networks.responses.LoginResponse
+import com.example.bondoman.networks.responses.TokenResponse
 import com.google.android.material.button.MaterialButton
 import com.google.android.material.textfield.TextInputEditText
 
@@ -27,6 +29,8 @@ class LoginActivity : AppCompatActivity() {
 		super.onCreate(savedInstanceState)
 		setContentView(R.layout.activity_login)
 
+		checkLoginStatus()
+
 		loginLayout = findViewById(R.id.login_layout)
 		emailInput = findViewById(R.id.email_text_input)
 		passwordInput = findViewById(R.id.password_text_input)
@@ -72,32 +76,43 @@ class LoginActivity : AppCompatActivity() {
 			if (response.error != null) {
 				Toast.makeText(this, response.error, Toast.LENGTH_SHORT).show()
 			} else {
+				PreferencesManager.putString(this, "token", response.token ?: "", true)
 				val intent = Intent(this, MainActivity::class.java)
 				startActivity(intent)
 				finish()
 			}
 		}
 
-		viewModel.response.observe(this, observer)
+		viewModel.loginResponse.observe(this, observer)
 	}
 
-	private fun saveToken(token: String) {
-		val sharedPreferences = PreferencesManager.getEncryptedSharedPreferences(applicationContext)
-		val editor = sharedPreferences.edit()
-		editor.putString("token", token)
-		editor.apply()
-	}
+	private fun checkLoginStatus() {
+		val token: String? = PreferencesManager.getString(this, "token", true)
 
-	private fun getToken(): String? {
-		val sharedPreferences = PreferencesManager.getEncryptedSharedPreferences(applicationContext)
-		return sharedPreferences.getString("token", null)
-	}
+		if (token.isNullOrEmpty()) {
+			return
+		}
 
-	private fun isLoggedIn(): Boolean {
-		val token = getToken() ?: return false
+		viewModel.checkToken(token)
 
-		// TODO: Check if JWT token is expired
+		val observer = Observer<TokenResponse> { response ->
+			if (response.error != null) {
+				Log.e("LoginActivity", response.error)
+				return@Observer
+			}
+
+			val currentTime = System.currentTimeMillis() / 1000
+			if (response.exp != null && response.exp < currentTime) {
+				Log.i("LoginActivity", "Token expired")
+				PreferencesManager.remove(this, "token", true)
+				return@Observer
+			}
+
+			val intent = Intent(this, MainActivity::class.java)
+			startActivity(intent)
+			finish()
+		}
 
-		return true
+		viewModel.tokenResponse.observe(this, observer)
 	}
 }