Adds JWT-based auth with refresh tokens

This commit is contained in:
2026-04-09 15:57:26 -05:00
parent 3a53769421
commit 9633d95e75
21 changed files with 426 additions and 48 deletions

View File

@@ -4,6 +4,7 @@ import net.halfbinary.scavengerhuntapi.error.exception.InvalidEmailException
import net.halfbinary.scavengerhuntapi.error.exception.LoginFailedException
import net.halfbinary.scavengerhuntapi.error.exception.NotFoundException
import net.halfbinary.scavengerhuntapi.error.exception.PreexistingAccountException
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.validation.FieldError
@@ -15,7 +16,9 @@ import org.springframework.web.bind.annotation.RestControllerAdvice
@RestControllerAdvice
class ExceptionHandler {
companion object {
private val log = LoggerFactory.getLogger(net.halfbinary.scavengerhuntapi.error.ExceptionHandler::class.java)
}
@ExceptionHandler(PreexistingAccountException::class)
@ResponseStatus(HttpStatus.CONFLICT)
fun preexistingAccountException(e: PreexistingAccountException): String? {
@@ -42,8 +45,16 @@ class ExceptionHandler {
@ExceptionHandler(HttpMessageNotReadableException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun httpMessageNotReadableException(e: HttpMessageNotReadableException): String? {
return e.message
fun httpMessageNotReadableException(e: HttpMessageNotReadableException): Map<String, String?> {
if (e.message?.contains("body is missing")?:false) {
return simpleMap("body","Body is missing")
}
if (e.message?.contains("parameter")?:false) {
val missingParameter = e.message?.split("parameter ")[1]
return simpleMap(missingParameter?:"","Missing required parameter $missingParameter")
}
log.debug("JSON parsing issue", e)
return simpleMap("body", "Parsing error")
}
@ExceptionHandler(MethodArgumentNotValidException::class)
@@ -56,4 +67,8 @@ class ExceptionHandler {
)
}
}
private fun simpleMap(key: String, value: String?): Map<String, String?> {
return mapOf(Pair(key, value))
}
}

View File

@@ -0,0 +1,5 @@
package net.halfbinary.scavengerhuntapi.error.exception
import net.halfbinary.scavengerhuntapi.model.RefreshId
class ExpiredRefreshTokenException(token: RefreshId): RuntimeException("The refresh token $token is expired.")

View File

@@ -0,0 +1,5 @@
package net.halfbinary.scavengerhuntapi.error.exception
import net.halfbinary.scavengerhuntapi.model.RefreshId
class InvalidRefreshTokenException(token: RefreshId): RuntimeException("The refresh token $token is not valid.")