diff --git a/private/minis-backend/src/main/kotlin/de/walamana/plugins/Security.kt b/private/minis-backend/src/main/kotlin/de/walamana/plugins/Security.kt index a92c6b8..eea46b6 100644 --- a/private/minis-backend/src/main/kotlin/de/walamana/plugins/Security.kt +++ b/private/minis-backend/src/main/kotlin/de/walamana/plugins/Security.kt @@ -59,7 +59,7 @@ fun Payload.mid() = getClaim("id").asInt() object Security { - fun DEFAULT_EXPIRY() = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 14); + fun DEFAULT_EXPIRY() = Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 40); suspend fun authenticateUser(application: Application, username: String, password: String): Ministrant? { println("Username $username password $password") diff --git a/private/minis-backend/src/main/kotlin/de/walamana/views/AuthenticationView.kt b/private/minis-backend/src/main/kotlin/de/walamana/views/AuthenticationView.kt index 8a5f1ee..eb0f1d3 100644 --- a/private/minis-backend/src/main/kotlin/de/walamana/views/AuthenticationView.kt +++ b/private/minis-backend/src/main/kotlin/de/walamana/views/AuthenticationView.kt @@ -3,6 +3,7 @@ package de.walamana.views import at.favre.lib.crypto.bcrypt.BCrypt import com.auth0.jwt.JWT import com.auth0.jwt.algorithms.Algorithm +import de.walamana.models.Ministrant import de.walamana.models.MinistrantenDao import de.walamana.plugins.Security import de.walamana.plugins.getJWTEnvironment @@ -98,6 +99,28 @@ fun Route.configureAuthenticationRoutes() { call.respond(hashMapOf("password" to newPassword)) } + post("refresh") { + val principal = call.principal()!! + val jwtEnv = application.getJWTEnvironment() + val username = principal.payload.username() + + val ministrant = if (username == "admin") { + val allMinis = MinistrantenDao.allMinistranten().map { it.username } + Ministrant(0, "admin", "", "admin", "admin", null, allMinis) + } else { + MinistrantenDao.getMinistrant(username) ?: return@post + } + + val newToken = Security.createToken(jwtEnv, ministrant) + val expiry = Security.DEFAULT_EXPIRY().toGMTString() + + call.response.header( + "Set-Cookie", + "token=$newToken; HttpOnly; Expires=$expiry" + ) + + call.respond(AuthenticationResult(true, newToken, ministrant.privileges)) + } } } } diff --git a/public/src/App.vue b/public/src/App.vue index f900d66..1b95328 100644 --- a/public/src/App.vue +++ b/public/src/App.vue @@ -22,8 +22,11 @@ function print(){ window.print() } -onMounted(() => { +onMounted(async () => { Auth.checkForToken() + if (Auth.getToken()) { + await Auth.refreshToken() + } }) LoginService.subject.subscribe(() => { diff --git a/public/src/services/auth.ts b/public/src/services/auth.ts index 58abe21..61e2bdb 100644 --- a/public/src/services/auth.ts +++ b/public/src/services/auth.ts @@ -71,6 +71,30 @@ export namespace Auth { } } + export async function refreshToken(): Promise { + const token = getToken() + if (!token) return false + + return api("/auth/refresh", "POST").then(res => { + if (res.status == 200) { + return res.json().then(data => { + if (data.success) { + setToken(data.token ?? "") + const payload = parseJwt(data.token) + loggedIn = true + user = payload.username + privileges = payload.privileges + privileges.push(user) + loggedInSubject.next(true) + return true + } + return false + }) + } + return false + }).catch(() => false) + } + function parseJwt (token) { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');