Add token renewal backend
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package be.vandewalleh.routing
|
||||
|
||||
import be.vandewalleh.auth.SimpleJWT
|
||||
import be.vandewalleh.auth.UsernamePasswordCredential
|
||||
import be.vandewalleh.extensions.respondStatus
|
||||
import be.vandewalleh.services.UserService
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException
|
||||
import io.ktor.application.*
|
||||
import io.ktor.auth.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.request.*
|
||||
import io.ktor.response.*
|
||||
import io.ktor.routing.*
|
||||
import org.kodein.di.Kodein
|
||||
import org.kodein.di.generic.instance
|
||||
import org.mindrot.jbcrypt.BCrypt
|
||||
|
||||
data class RefreshToken(val refreshToken: String)
|
||||
data class DualToken(val token: String, val refreshToken: String)
|
||||
|
||||
fun Routing.auth(kodein: Kodein) {
|
||||
val authSimpleJwt by kodein.instance<SimpleJWT>("auth")
|
||||
val refreshSimpleJwt by kodein.instance<SimpleJWT>("refresh")
|
||||
val userService by kodein.instance<UserService>()
|
||||
|
||||
post("/user/login") {
|
||||
val credential = call.receive<UsernamePasswordCredential>()
|
||||
|
||||
val (email, password) = userService.getEmailAndPasswordFromUsername(credential.username)
|
||||
?: return@post call.respondStatus(HttpStatusCode.Unauthorized)
|
||||
|
||||
if (!BCrypt.checkpw(credential.password, password)) {
|
||||
return@post call.respondStatus(HttpStatusCode.Unauthorized)
|
||||
}
|
||||
|
||||
val response = DualToken(
|
||||
token = authSimpleJwt.sign(email),
|
||||
refreshToken = refreshSimpleJwt.sign(email)
|
||||
)
|
||||
return@post call.respond(response)
|
||||
}
|
||||
|
||||
post("/user/refresh_token") {
|
||||
val token = call.receive<RefreshToken>().refreshToken
|
||||
|
||||
val email = try {
|
||||
val decodedJWT = refreshSimpleJwt.verifier.verify(token)
|
||||
decodedJWT.getClaim("email").asString()
|
||||
} catch (e: JWTVerificationException) {
|
||||
return@post call.respondStatus(HttpStatusCode.Unauthorized)
|
||||
}
|
||||
|
||||
val response = DualToken(
|
||||
token = authSimpleJwt.sign(email),
|
||||
refreshToken = refreshSimpleJwt.sign(email)
|
||||
)
|
||||
return@post call.respond(response)
|
||||
}
|
||||
|
||||
authenticate {
|
||||
get("/user/me") {
|
||||
// retrieve email from token
|
||||
val email = call.principal<UserIdPrincipal>()!!.name
|
||||
val info = userService.getUserInfo(email)
|
||||
if (info != null) call.respond(mapOf("user" to info))
|
||||
else call.respondStatus(HttpStatusCode.Unauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package be.vandewalleh.routing
|
||||
|
||||
import be.vandewalleh.auth.SimpleJWT
|
||||
import be.vandewalleh.auth.UsernamePasswordCredential
|
||||
import be.vandewalleh.extensions.respondStatus
|
||||
import be.vandewalleh.services.UserService
|
||||
import io.ktor.application.*
|
||||
import io.ktor.auth.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.request.*
|
||||
import io.ktor.response.*
|
||||
import io.ktor.routing.*
|
||||
import org.kodein.di.Kodein
|
||||
import org.kodein.di.generic.instance
|
||||
import org.mindrot.jbcrypt.BCrypt
|
||||
|
||||
fun Routing.login(kodein: Kodein) {
|
||||
val simpleJwt by kodein.instance<SimpleJWT>()
|
||||
val userService by kodein.instance<UserService>()
|
||||
|
||||
data class TokenResponse(val token: String)
|
||||
|
||||
post("/user/login") {
|
||||
val credential = call.receive<UsernamePasswordCredential>()
|
||||
|
||||
val (email, password) = userService.getEmailAndPasswordFromUsername(credential.username)
|
||||
?: return@post call.respond(HttpStatusCode.Unauthorized)
|
||||
|
||||
if (!BCrypt.checkpw(credential.password, password)) {
|
||||
return@post call.respond(HttpStatusCode.Unauthorized)
|
||||
}
|
||||
|
||||
return@post call.respond(TokenResponse(simpleJwt.sign(email)))
|
||||
}
|
||||
|
||||
authenticate {
|
||||
get("/user/me") {
|
||||
// retrieve email from token
|
||||
val email = call.principal<UserIdPrincipal>()!!.name
|
||||
val info = userService.getUserInfo(email)
|
||||
if (info != null) call.respond(mapOf("user" to info))
|
||||
else call.respondStatus(HttpStatusCode.Unauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import org.kodein.di.Kodein
|
||||
|
||||
fun Routing.registerRoutes(kodein: Kodein) {
|
||||
user(kodein)
|
||||
login(kodein)
|
||||
auth(kodein)
|
||||
notes(kodein)
|
||||
title(kodein)
|
||||
tags(kodein)
|
||||
|
||||
@@ -34,7 +34,6 @@ fun Routing.user(kodein: Kodein) {
|
||||
}
|
||||
|
||||
authenticate {
|
||||
|
||||
put {
|
||||
val user = call.receive<UserDto>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user