Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ val kotestVersion = "6.0.3"
val bouncyCastleVersion = "1.82"
val springBootVersion = "3.5.6"
val reactorTestVersion = "3.7.11"
val ktorVersion = "2.3.13"
val ktorVersion = "3.3.0"
val jsonPathVersion = "2.9.0"

val mainClassKt = "no.nav.security.mock.oauth2.StandaloneMockOAuth2ServerKt"
Expand All @@ -29,6 +29,7 @@ plugins {
id("com.google.cloud.tools.jib") version "3.4.5"
id("com.vanniktech.maven.publish") version "0.34.0"
id("org.jetbrains.dokka") version "2.0.0"
kotlin("plugin.serialization") version "2.2.0"
`java-library`
signing
}
Expand Down Expand Up @@ -127,15 +128,18 @@ dependencies {
testImplementation("io.projectreactor:reactor-test:$reactorTestVersion")
testImplementation("io.ktor:ktor-server-netty:$ktorVersion")
testImplementation("io.ktor:ktor-server-sessions:$ktorVersion")
testImplementation("io.ktor:ktor-server-locations:$ktorVersion")
testImplementation("io.ktor:ktor-server-resources:$ktorVersion")
testImplementation("io.ktor:ktor-server-auth:$ktorVersion")
testImplementation("io.ktor:ktor-server-auth-jwt:$ktorVersion")
testImplementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
testImplementation("io.ktor:ktor-client-core:$ktorVersion")
testImplementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
testImplementation("io.ktor:ktor-serialization-jackson:$ktorVersion")
testImplementation("io.ktor:ktor-client-cio:$ktorVersion")
testImplementation("io.ktor:ktor-server-test-host:$ktorVersion")
testImplementation("io.ktor:ktor-server-test-host:$ktorVersion"){
//Provides transitive vulnerable dependency maven:commons-codec:commons-codec:1.11 WS-2019-0379 6.5 Input Validation Results powered by Mend.io
exclude("commons-codec", "commons-codec")
}
}

configurations {
Expand Down
44 changes: 26 additions & 18 deletions src/test/kotlin/examples/kotlin/ktor/login/OAuth2LoginApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.http.ContentType
import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.http.encodedPath
import io.ktor.resources.Resource
import io.ktor.serialization.jackson.jackson
import io.ktor.server.application.Application
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.auth.Authentication
import io.ktor.server.auth.OAuthAccessTokenResponse
Expand All @@ -21,17 +22,16 @@ import io.ktor.server.auth.authenticate
import io.ktor.server.auth.authentication
import io.ktor.server.auth.oauth
import io.ktor.server.engine.embeddedServer
import io.ktor.server.locations.KtorExperimentalLocationsAPI
import io.ktor.server.locations.Location
import io.ktor.server.locations.Locations
import io.ktor.server.locations.location
import io.ktor.server.locations.locations
import io.ktor.server.locations.url
import io.ktor.server.netty.Netty
import io.ktor.server.resources.Resources
import io.ktor.server.resources.href
import io.ktor.server.resources.resource
import io.ktor.server.response.respondText
import io.ktor.server.routing.get
import io.ktor.server.routing.param
import io.ktor.server.routing.routing
import io.ktor.server.util.url
import kotlinx.serialization.Serializable

fun main() {
embeddedServer(Netty, port = 8080) {
Expand All @@ -54,19 +54,21 @@ fun main() {
}.start(true)
}

@OptIn(KtorExperimentalLocationsAPI::class)
fun Application.module(authConfig: AuthConfig) {
val idProviders = authConfig.providers.map { it.settings }.associateBy { it.name }

install(Locations)
install(Resources)
install(Authentication) {
oauth("oauth2") {
client = httpClient
providerLookup = {
idProviders[application.locations.resolve<Login>(Login::class, this).type] ?: idProviders.values.first()
val t = this.parameters["type"].orEmpty()
idProviders[t] ?: idProviders.values.first()
}
urlProvider = {
url(Login(it.name))
url {
encodedPath = application.href(Login(it.name))
}
}
}
}
Expand All @@ -76,26 +78,32 @@ fun Application.module(authConfig: AuthConfig) {
get {
call.respondText("nothing to see here really")
}
location<Login> {
resource<Login> {
// /login/{type}?error=...
param("error") {
handle {
call.respondText(ContentType.Text.Html, HttpStatusCode.BadRequest) {
get {
call.respondText(
ContentType.Text.Html,
HttpStatusCode.BadRequest
) {
"received error on login: ${call.parameters.getAll("error").orEmpty()}"
}
}
}
handle {
// /login/{type}
get {
call.respondText("welcome ${call.subject()}")
}
}

}
}
}

@Location("/login/{type?}")
@OptIn(KtorExperimentalLocationsAPI::class)
@Serializable
@Resource("/login/{type?}")
class Login(
val type: String = "",
val type: String? = "",
)

class AuthConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ internal class OAuth2LoginAppTest {
port: Int,
test: ApplicationEngine.() -> R,
): R {
val engine =
val server =
embeddedServer(Netty, port = port) {
moduleFunction(this)
}
engine.start()
server.start()
try {
return engine.test()
return test(server.engine)
} finally {
engine.stop(0L, 0L)
server.stop(0L, 0L)
}
}

Expand Down