This commit is contained in:
xds
2025-10-31 17:11:40 +03:00
parent 5b9d2366db
commit d2458633db
11 changed files with 128 additions and 26 deletions

View File

@@ -1,23 +1,67 @@
package space.luminic.finance.api
import org.apache.commons.codec.digest.DigestUtils.sha256
import org.apache.commons.codec.digest.HmacUtils.hmacSha256
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.web.bind.annotation.*
import space.luminic.finance.dtos.UserDTO
import space.luminic.finance.dtos.UserDTO.AuthUserDTO
import space.luminic.finance.dtos.UserDTO.RegisterUserDTO
import space.luminic.finance.mappers.UserMapper.toDto
import space.luminic.finance.mappers.UserMapper.toTelegramMap
import space.luminic.finance.services.AuthService
import java.security.MessageDigest
import java.time.Instant
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
@RestController
@RequestMapping("/auth")
class AuthController(
private val authService: AuthService
private val authService: AuthService,
@Value("\${telegram.bot.token}") private val botToken: String
) {
private val logger = LoggerFactory.getLogger(javaClass)
fun verifyTelegramAuth(data: Map<String, String>, botToken: String): Boolean {
val hash = data["hash"] ?: return false
val dataCheckString = data
.filterKeys { it != "hash" }
.toSortedMap()
.map { "${it.key}=${it.value}" }
.joinToString("\n")
val secretKey = sha256(botToken)
val hmacHex = hmacSha256(secretKey, dataCheckString)
if (hmacHex != hash) return false
val authDate = data["auth_date"]?.toLongOrNull() ?: return false
val now = Instant.now().epochSecond
// Опционально — запрет старых ответов (например, старше 1 часа)
val maxAgeSeconds = 3600
if (now - authDate > maxAgeSeconds) return false
return true
}
private fun sha256(input: String): ByteArray =
MessageDigest.getInstance("SHA-256").digest(input.toByteArray())
private fun hmacSha256(secret: ByteArray, message: String): String {
val key = SecretKeySpec(secret, "HmacSHA256")
val mac = Mac.getInstance("HmacSHA256")
mac.init(key)
val hashBytes = mac.doFinal(message.toByteArray())
return hashBytes.joinToString("") { "%02x".format(it) }
}
@GetMapping("/test")
fun test(): String {
val authentication = SecurityContextHolder.getContext().authentication
@@ -26,23 +70,26 @@ class AuthController(
}
@PostMapping("/login")
fun login(@RequestBody request: AuthUserDTO): Map<String, String> {
fun login(@RequestBody request: AuthUserDTO): Map<String, String> {
val token = authService.login(request.username.lowercase(), request.password)
return mapOf("token" to token)
}
@PostMapping("/register")
fun register(@RequestBody request: RegisterUserDTO): UserDTO {
fun register(@RequestBody request: RegisterUserDTO): UserDTO {
return authService.register(request.username, request.password, request.firstName).toDto()
}
@PostMapping("/tgLogin")
fun tgLogin(@RequestHeader("X-Tg-Id") tgId: String): Map<String, String> {
val token = authService.tgLogin(tgId)
return mapOf("token" to token)
@PostMapping("/tg-login")
fun tgLogin(@RequestBody tgUser: UserDTO.TelegramAuthDTO): String {
val ok = verifyTelegramAuth(tgUser.toTelegramMap(), botToken)
if (!ok) throw IllegalArgumentException("Invalid Telegram login")
return authService.tgAuth(tgUser)
}
@GetMapping("/me")
fun getMe(): UserDTO {
logger.info("Get Me")