initial commit - source
This commit is contained in:
1 parent
003b5501f0
commit
e89bb29070
45 files changed
+5997
No files matched your search
@@ -0,0 +1,19 @@
|
||||
package net.keinekekse.app
|
||||
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
import net.keinekekse.app.server.VERSION
|
||||
import net.keinekekse.app.server.config.configureSecurity
|
||||
|
||||
fun main() {
|
||||
// embeddedServer(Netty, port = SERVER_PORT, host = "0.0.0.0", module = Application::module)
|
||||
println("**\n** Starting ${VERSION.displayName} - ${VERSION.description} ${VERSION.fullVersion}\n**")
|
||||
embeddedServer(Netty, port = 7770, host = "0.0.0.0", module = Application::module)
|
||||
.start(wait = true)
|
||||
}
|
||||
|
||||
fun Application.module() {
|
||||
configureSecurity()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.keinekekse.app.server
|
||||
|
||||
import net.keinekekse.version.Version
|
||||
|
||||
object VERSION: Version {
|
||||
override val version = "0.1.0-beta.1+build.19"
|
||||
override val fullVersion = "0.1.0-beta.1+build.19"
|
||||
override val major = 0
|
||||
override val minor = 1
|
||||
override val patch = 0
|
||||
override val preRelease = "beta.1"
|
||||
override val buildMetadata = "build.19"
|
||||
override val buildDate = "2026-02-02T23:47:38.629893Z"
|
||||
override val displayName = "kAS"
|
||||
override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
||||
override val name = "server"
|
||||
override val description = "ktor Application-Server"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.keinekekse.app.server.config
|
||||
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import java.security.Principal
|
||||
|
||||
class AppPrincipal(credential: JWTCredential) : Principal {
|
||||
val userId: String = credential.getClaim("preferred_username", String::class) ?: ""
|
||||
val vorname: String = credential.getClaim("given_name", String::class) ?: ""
|
||||
val nachname: String = credential.getClaim("family_name", String::class) ?: ""
|
||||
val email: String = credential.getClaim("email", String::class) ?: ""
|
||||
val roles: List<String>
|
||||
|
||||
init {
|
||||
val realmAccess: Map<*, *>? = credential.getClaim("realm_access", Map::class)
|
||||
val list = realmAccess?.get("roles")
|
||||
roles = if (list is List<*>) list.map { it as String } else emptyList()
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
return "$userId ($vorname $nachname) <$email>"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.keinekekse.app.server.config
|
||||
|
||||
import com.auth0.jwk.UrlJwkProvider
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import net.keinekekse.app.server.VERSION
|
||||
import java.net.URI
|
||||
|
||||
fun Application.configureSecurity() {
|
||||
|
||||
// TODO die Werte müssen aus der Config kommen
|
||||
|
||||
// Kommunikation funktioniert nur im internen Containernetzwerk,
|
||||
// d.h. Container- bzw. Pod-Name + interner Port
|
||||
val keycloakInternal = "http://kec:8080/realms"
|
||||
val keycloak = "https://kec.keinekekse.net/realms"
|
||||
val realm = "app-server-realm"
|
||||
val clientId = "pkce-book-app"
|
||||
val certUrl = "$keycloakInternal/$realm/protocol/openid-connect/certs"
|
||||
val issuer = "$keycloak/$realm"
|
||||
authentication {
|
||||
jwt("auth-KC") {
|
||||
verifier(
|
||||
UrlJwkProvider(URI(certUrl).toURL()), issuer
|
||||
) {
|
||||
withAudience("account")
|
||||
withClaim("azp", clientId)
|
||||
}
|
||||
challenge { _, _ ->
|
||||
call.respond(HttpStatusCode.Unauthorized, "Token is not valid or has expired")
|
||||
}
|
||||
validate { credential ->
|
||||
AppPrincipal(credential)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
routing {
|
||||
authenticate("auth-KC") {
|
||||
get("/") {
|
||||
val principal = call.principal<AppPrincipal>()
|
||||
call.respondText("Ktor ${VERSION.displayName} ${VERSION.fullVersion} - principal=${principal?.name}")
|
||||
}
|
||||
|
||||
get("/test") {
|
||||
val principal = call.principal<AppPrincipal>()
|
||||
call.respondText("user: ${principal?.userId}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.netty" level="INFO"/>
|
||||
</configuration>
|
||||
Reference in new issue
Block a user