import kotlinx.coroutines.*
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import java.net.NetworkInterface
import java.net.InetAddress
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.net.URI
import java.security.MessageDigest
import java.time.Duration
private const val API_KEY = "your-api-key-here"
private const val API_URL = "http://your-domain.com/api/license/auth"
private const val PRODUCT = "MyKotlinApp"
private const val VERSION = "1.0.0"
@Serializable
data class AuthRequest(
val data: AuthData
)
@Serializable
data class AuthData(
val product: String,
val version: String,
val licensekey: String,
val ip: String,
val hwid: String
)
@Serializable
data class AuthResponse(
val status_overview: String,
val status_msg: String? = null,
val discord_username: String? = null,
val discord_tag: String? = null,
val discord_id: String? = null,
val expire_date: String? = null,
val staff_license: Boolean = false,
val version: String? = null,
val message: String? = null
)
sealed class AuthResult {
data class Success(val response: AuthResponse) : AuthResult()
data class Failure(val error: String) : AuthResult()
}
class TKIAuth {
private val httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.build()
private val json = Json { ignoreUnknownKeys = true }
private fun getHWID(): String {
return try {
val interfaces = NetworkInterface.getNetworkInterfaces()
val mac = interfaces.asSequence()
.firstOrNull { it.hardwareAddress != null }
?.hardwareAddress
?.joinToString("") { "%02x".format(it) }
?: "fallback"
val systemInfo = "${System.getProperty("os.name")}-${System.getProperty("os.arch")}-$mac"
val digest = MessageDigest.getInstance("MD5")
val hash = digest.digest(systemInfo.toByteArray())
"KT-${hash.joinToString("") { "%02x".format(it) }.take(16)}"
} catch (e: Exception) {
"KT-FALLBACK-${System.currentTimeMillis() % 1000000}"
}
}
private fun getLocalIP(): String {
return try {
InetAddress.getLocalHost().hostAddress
} catch (e: Exception) {
"127.0.0.1"
}
}
suspend fun authenticate(
licenseKey: String,
ip: String? = null,
hwid: String? = null
): AuthResult = withContext(Dispatchers.IO) {
try {
val authRequest = AuthRequest(
data = AuthData(
product = PRODUCT,
version = VERSION,
licensekey = licenseKey,
ip = ip ?: getLocalIP(),
hwid = hwid ?: getHWID()
)
)
val jsonBody = json.encodeToString(authRequest)
val request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.header("Content-Type", "application/json")
.header("Authorization", API_KEY)
.header("User-Agent", "TKI-Auth-Kotlin/1.0")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build()
val response = httpClient.send(request, HttpResponse.BodyHandlers.ofString())
when (response.statusCode()) {
200 -> {
val authResponse = json.decodeFromString<AuthResponse>(response.body())
if (authResponse.status_overview == "success") {
AuthResult.Success(authResponse)
} else {
AuthResult.Failure(authResponse.message ?: "Authentication failed")
}
}
429 -> AuthResult.Failure("Rate limit exceeded")
in 400..499 -> {
val errorResponse = json.decodeFromString<AuthResponse>(response.body())
AuthResult.Failure(errorResponse.message ?: "Client error")
}
else -> AuthResult.Failure("HTTP ${response.statusCode()}")
}
} catch (e: Exception) {
AuthResult.Failure("Network error: ${e.message}")
}
}
suspend fun authenticateWithRetry(
licenseKey: String,
maxRetries: Int = 3,
ip: String? = null,
hwid: String? = null
): AuthResult {
repeat(maxRetries) { attempt ->
when (val result = authenticate(licenseKey, ip, hwid)) {
is AuthResult.Success -> return result
is AuthResult.Failure -> {
if (attempt < maxRetries - 1) {
val waitTime = (attempt + 1) * 1000L
println("Attempt ${attempt + 1} failed, retrying in ${waitTime}ms...")
delay(waitTime)
} else {
return result
}
}
}
}
return AuthResult.Failure("Max retries exceeded")
}
}
class LicenseManager {
private val auth = TKIAuth()
private var licenseInfo: AuthResponse? = null
private var isAuthenticated = false
private var validationJob: Job? = null
suspend fun authenticate(licenseKey: String): Boolean {
println("Authenticating license...")
return when (val result = auth.authenticateWithRetry(licenseKey)) {
is AuthResult.Success -> {
isAuthenticated = true
licenseInfo = result.response
println("â License authenticated!")
println(" User: ${result.response.discord_username}")
println(" Tag: ${result.response.discord_tag}")
println(" Expires: ${result.response.expire_date}")
println(" Staff License: ${result.response.staff_license}")
true
}
is AuthResult.Failure -> {
println("â Authentication failed: ${result.error}")
false
}
}
}
fun startPeriodicValidation(
licenseKey: String,
intervalMinutes: Long = 30,
scope: CoroutineScope
) {
validationJob = scope.launch {
while (isActive && isAuthenticated) {
delay(intervalMinutes * 60 * 1000)
when (val result = auth.authenticate(licenseKey)) {
is AuthResult.Success -> {
println("â Periodic validation successful")
}
is AuthResult.Failure -> {
println("â Periodic validation failed: ${result.error}")
onLicenseExpired()
break
}
}
}
}
}
private fun onLicenseExpired() {
isAuthenticated = false
licenseInfo = null
println("License expired or validation failed!")
}
fun getLicenseInfo(): AuthResponse? = licenseInfo
fun isAuthenticated(): Boolean = isAuthenticated
fun shutdown() {
validationJob?.cancel()
isAuthenticated = false
licenseInfo = null
}
}
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private val licenseManager = LicenseManager()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val licenseKey = "TKI-XXXXX-XXXXX"
lifecycleScope.launch {
if (licenseManager.authenticate(licenseKey)) {
licenseManager.startPeriodicValidation(licenseKey, 30, lifecycleScope)
initializeApp()
} else {
showLicenseError()
}
}
}
private fun initializeApp() {
println("App initialized successfully!")
}
private fun showLicenseError() {
println("License validation failed!")
}
override fun onDestroy() {
super.onDestroy()
licenseManager.shutdown()
}
}
class ConsoleApp {
private val licenseManager = LicenseManager()
suspend fun run(): Int {
println("Enter license key:")
val licenseKey = readLine()?.trim()
if (licenseKey.isNullOrEmpty()) {
println("No license key provided!")
return 1
}
if (!licenseManager.authenticate(licenseKey)) {
return 1
}
val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
licenseManager.startPeriodicValidation(licenseKey, 30, scope)
println("Starting application...")
repeat(10) { i ->
if (!licenseManager.isAuthenticated()) {
println("Application stopped due to license issues")
return 1
}
println("Application is running... (iteration ${i + 1})")
delay(2000)
}
println("Application completed successfully!")
licenseManager.shutdown()
scope.cancel()
return 0
}
}
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import io.ktor.http.*
data class UserSession(val authenticated: Boolean, val userInfo: AuthResponse?)
fun Application.configureRouting() {
install(Sessions) {
cookie<UserSession>("user_session")
}
val licenseManager = LicenseManager()
routing {
get("/") {
val session = call.sessions.get<UserSession>()
if (session?.authenticated != true) {
call.respondRedirect("/login")
return@get
}
val userInfo = session.userInfo
call.respondText("""
<h1>Welcome to Licensed App!</h1>
<p>User: ${userInfo?.discord_username}</p>
<p>Expires: ${userInfo?.expire_date}</p>
<a href="/logout">Logout</a>
""".trimIndent(), ContentType.Text.Html)
}
get("/login") {
val error = call.request.queryParameters["error"]
val errorMsg = if (error != null) "<p style='color: red;'>$error</p>" else ""
call.respondText("""
<h1>License Authentication</h1>
<form method="post" action="/authenticate">
<input type="text" name="license_key" placeholder="Enter license key" required>
<button type="submit">Authenticate</button>
</form>
$errorMsg
""".trimIndent(), ContentType.Text.Html)
}
post("/authenticate") {
val parameters = call.receiveParameters()
val licenseKey = parameters["license_key"]
if (licenseKey.isNullOrEmpty()) {
call.respondRedirect("/login?error=Please+enter+a+license+key")
return@post
}
if (licenseManager.authenticate(licenseKey)) {
call.sessions.set(UserSession(true, licenseManager.getLicenseInfo()))
call.respondRedirect("/")
} else {
call.respondRedirect("/login?error=Authentication+failed")
}
}
get("/logout") {
call.sessions.clear<UserSession>()
licenseManager.shutdown()
call.respondRedirect("/login")
}
}
}
fun startWebServer() {
embeddedServer(Netty, port = 8080) {
configureRouting()
}.start(wait = true)
}
suspend fun main(args: Array<String>) {
when (args.getOrNull(0)) {
"web" -> startWebServer()
"console" -> {
val app = ConsoleApp()
kotlin.system.exitProcess(app.run())
}
else -> {
println("Usage: kotlin Main.kt [console|web]")
println("Running console app by default...")
val app = ConsoleApp()
kotlin.system.exitProcess(app.run())
}
}
}