1
1
package me.madhead.tyzenhaus.launcher.fly.routes
2
2
3
+ import com.soywiz.krypto.HMAC
3
4
import io.ktor.http.HttpStatusCode
5
+ import io.ktor.http.decodeURLQueryComponent
4
6
import io.ktor.server.application.call
5
7
import io.ktor.server.auth.authenticate
6
8
import io.ktor.server.auth.principal
7
9
import io.ktor.server.config.ApplicationConfig
10
+ import io.ktor.server.request.receiveText
8
11
import io.ktor.server.response.respond
9
12
import io.ktor.server.routing.Route
10
13
import io.ktor.server.routing.get
11
14
import io.ktor.server.routing.localPort
15
+ import io.ktor.server.routing.post
12
16
import io.ktor.server.routing.route
17
+ import io.ktor.utils.io.core.toByteArray
13
18
import me.madhead.tyzenhaus.core.service.GroupCurrenciesService
14
19
import me.madhead.tyzenhaus.core.service.GroupMembersService
15
20
import me.madhead.tyzenhaus.launcher.fly.security.APITokenPrincipal
21
+ import org.koin.ktor.ext.get
16
22
import org.koin.ktor.ext.inject
17
23
18
24
/* *
@@ -22,10 +28,37 @@ fun Route.miniAppAPI() {
22
28
val config by inject<ApplicationConfig >()
23
29
val groupMembersService by inject<GroupMembersService >()
24
30
val groupCurrenciesService by inject<GroupCurrenciesService >()
31
+ val webAppDataSecretKeyHash by lazy {
32
+ HMAC .hmacSHA256(
33
+ " WebAppData" .toByteArray(),
34
+ this @miniAppAPI.get<ApplicationConfig >().property(" telegram.token" ).getString().toByteArray()
35
+ )
36
+ }
25
37
26
38
localPort(config.property(" deployment.port" ).getString().toInt()) {
27
39
authenticate(" api" ) {
28
40
route(" /app/api" ) {
41
+ route(" auth" ) {
42
+ post(" validation" ) {
43
+ val initData = call.receiveText()
44
+ val fields = initData
45
+ .decodeURLQueryComponent()
46
+ .split(" &" )
47
+ val preparedData = fields
48
+ .filterNot { it.startsWith(" hash=" ) }
49
+ .sorted()
50
+ .joinToString(" \n " )
51
+ val computedHash = HMAC .hmacSHA256(webAppDataSecretKeyHash.bytes, preparedData.toByteArray()).hexLower
52
+ val hash = fields.find { it.startsWith(" hash=" ) }?.removePrefix(" hash=" )?.lowercase()
53
+
54
+ if (computedHash == hash) {
55
+ call.respond(HttpStatusCode .NoContent )
56
+ } else {
57
+ call.respond(HttpStatusCode .Unauthorized )
58
+ }
59
+ }
60
+ }
61
+
29
62
route(" group" ) {
30
63
get(" members" ) {
31
64
val principal = call.principal<APITokenPrincipal >()!!
0 commit comments