Save tokens when logging in and implement refresh token

This commit is contained in:
Reimar 2025-05-01 09:43:14 +02:00
parent 3aba01d56a
commit a63b98e180
Signed by: Reimar
GPG Key ID: 93549FA07F0AE268
5 changed files with 63 additions and 15 deletions

View File

@ -27,7 +27,7 @@ class LoginActivity : AppCompatActivity() {
thread {
try {
login(email, password)
login(this, email, password)
} catch (e: ApiRequestException) {
runOnUiThread {
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()

View File

@ -34,7 +34,7 @@ class RegisterActivity : AppCompatActivity() {
thread {
try {
register(email, username, password)
register(this, email, username, password)
} catch (e: ApiRequestException) {
runOnUiThread {
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()

View File

@ -3,15 +3,13 @@ package tech.mercantec.easyeat
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import tech.mercantec.easyeat.helpers.isLoggedIn
class SplashActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// TODO do auth check
val loggedIn = false
if (!loggedIn) {
if (!isLoggedIn(this)) {
startActivity(Intent(this, WelcomeActivity::class.java))
return

View File

@ -16,9 +16,12 @@ class ApiRequestException(message: String, cause: Throwable?) : Exception(messag
class HttpResponse(val body: String, val code: Int)
fun request(method: String, path: String, data: String?): HttpResponse {
fun request(ctx: Context, method: String, path: String, data: String?): HttpResponse {
val url = URL(BuildConfig.API_BASE_URL + path)
val prefs = ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE)
val authToken = prefs.getString("auth-token", null)
try {
with(url.openConnection() as HttpURLConnection) {
requestMethod = method
@ -26,6 +29,9 @@ fun request(method: String, path: String, data: String?): HttpResponse {
if (data != null) {
setRequestProperty("Content-Type", "application/json")
if (authToken != null)
setRequestProperty("Authorization", "Bearer $authToken")
outputStream.write(data.toByteArray())
outputStream.flush()
}
@ -45,13 +51,13 @@ fun request(method: String, path: String, data: String?): HttpResponse {
@Serializable
class HttpErrorResponse(val message: String)
inline fun <reified Req, reified Res> requestJson(method: String, path: String, data: Req?): Res {
inline fun <reified Req, reified Res> requestJson(ctx: Context, method: String, path: String, data: Req?): Res {
val requestJson =
if (data != null)
Json.encodeToString(serializer<Req>(), data)
else null
val response = request(method, path, requestJson)
val response = request(ctx, method, path, requestJson)
if (response.code >= 400) {
try {

View File

@ -9,20 +9,64 @@ data class LoginRequest(val emailUsr: String, val password: String)
@Serializable
data class LoginResponse(val token: String, val userName: String, val id: Int, val refreshToken: String)
fun login(email: String, password: String) {
fun login(ctx: Context, email: String, password: String) {
val request = LoginRequest(email, password)
val response = requestJson<LoginRequest, LoginResponse>("POST", "/api/User/login", request)
// TODO save tokens
val response = requestJson<LoginRequest, LoginResponse>(ctx, "POST", "/api/User/login", request)
with (ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) {
putInt("user-id", response.id)
putString("username", response.userName)
putString("auth-token", response.token)
putString("refresh-token", response.refreshToken)
apply()
}
}
@Serializable
data class CreateUserRequest(val email: String, val userName: String, val password: String)
fun register(email: String, username: String, password: String) {
fun register(ctx: Context, email: String, username: String, password: String) {
val request = CreateUserRequest(email, username, password)
requestJson<CreateUserRequest, Boolean>("POST", "/api/User/create", request)
requestJson<CreateUserRequest, Boolean>(ctx, "POST", "/api/User/create", request)
}
@Serializable
data class RefreshTokenRequest(val refreshToken: String)
@Serializable
data class RefreshTokenResponse(val token: String, val refreshToken: String)
fun refreshAuthToken(ctx: Context, refreshToken: String): Boolean {
val response: RefreshTokenResponse
try {
response = requestJson<RefreshTokenRequest, RefreshTokenResponse>(
ctx,
"POST", "/api/User/refreshtoken",
RefreshTokenRequest(refreshToken)
)
} catch (e: ApiRequestException) {
return false
}
with (ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) {
putString("auth-token", response.token)
putString("refresh-token", response.refreshToken)
apply()
}
return true
}
fun isLoggedIn(ctx: Context): Boolean {
val prefs = ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE)
val authToken = prefs.getString("auth-token", null)
val refreshToken = prefs.getString("refresh-token", null) ?: return false
if (authToken == null) {
return refreshAuthToken(ctx, refreshToken)
}
return true
}