Skip to content

Commit c3cf7f2

Browse files
committed
initData validation API
1 parent b663b09 commit c3cf7f2

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

launcher/fly/requests.http

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ Content-Type: application/json
99
"url": "https://{{ngrok}}/{{telegram_token}}"
1010
}
1111

12+
### Validate initData
13+
POST https://{{ngrok}}/app/api/auth/validation
14+
Authorization: Bearer {{api_token}}
15+
16+
1217
### Get group members
13-
GET http://{{local}}/app/api/group/members
18+
GET https://{{ngrok}}/app/api/group/members
19+
Authorization: Bearer {{api_token}}
20+
21+
### Get group currencies
22+
GET https://{{ngrok}}/app/api/group/currencies
1423
Authorization: Bearer {{api_token}}

launcher/fly/src/main/kotlin/me/madhead/tyzenhaus/launcher/fly/routes/MiniAppAPI.kt

+33
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package me.madhead.tyzenhaus.launcher.fly.routes
22

3+
import com.soywiz.krypto.HMAC
34
import io.ktor.http.HttpStatusCode
5+
import io.ktor.http.decodeURLQueryComponent
46
import io.ktor.server.application.call
57
import io.ktor.server.auth.authenticate
68
import io.ktor.server.auth.principal
79
import io.ktor.server.config.ApplicationConfig
10+
import io.ktor.server.request.receiveText
811
import io.ktor.server.response.respond
912
import io.ktor.server.routing.Route
1013
import io.ktor.server.routing.get
1114
import io.ktor.server.routing.localPort
15+
import io.ktor.server.routing.post
1216
import io.ktor.server.routing.route
17+
import io.ktor.utils.io.core.toByteArray
1318
import me.madhead.tyzenhaus.core.service.GroupCurrenciesService
1419
import me.madhead.tyzenhaus.core.service.GroupMembersService
1520
import me.madhead.tyzenhaus.launcher.fly.security.APITokenPrincipal
21+
import org.koin.ktor.ext.get
1622
import org.koin.ktor.ext.inject
1723

1824
/**
@@ -22,10 +28,37 @@ fun Route.miniAppAPI() {
2228
val config by inject<ApplicationConfig>()
2329
val groupMembersService by inject<GroupMembersService>()
2430
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+
}
2537

2638
localPort(config.property("deployment.port").getString().toInt()) {
2739
authenticate("api") {
2840
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+
2962
route("group") {
3063
get("members") {
3164
val principal = call.principal<APITokenPrincipal>()!!

mini-app/src/history/HistoryApp.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function HistoryApp() {
2121
return (
2222
<div>
2323
<h1>History</h1>
24-
Data: {JSON.stringify(data)}
24+
Init Data: {WebApp.initData}
2525
</div>
2626
);
2727
}

0 commit comments

Comments
 (0)