Skip to content

Instantly share code, notes, and snippets.

@bvlion
Created March 8, 2022 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bvlion/f8301987635b524238a14da2c7321c86 to your computer and use it in GitHub Desktop.
Save bvlion/f8301987635b524238a14da2c7321c86 to your computer and use it in GitHub Desktop.
Bearer トークンの妥当性だけを確認する
import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
@Suppress("unused")
fun Application.module() {
install(Authentication) {
bearer {
validate(environment.config.property("app.bearer").getString())
}
}
routing {
authenticate {
get("/target") {
call.respond(mapOf("success" to "ok"))
}
}
}
}
fun main(args: Array<String>) {
embeddedServer(Netty, commandLineEnvironment(args)).start()
}
import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.http.auth.*
import io.ktor.request.*
import io.ktor.response.*
class BearerAuthenticationProvider internal constructor(
configuration: Configuration
) : AuthenticationProvider(configuration) {
val realm: String = configuration.realm
val authenticationFunction = configuration.authenticationFunction
class Configuration(name: String?) : AuthenticationProvider.Configuration(name) {
var authenticationFunction: AuthenticationFunction<BearerPrincipal> = {
throw NotImplementedError(
"Bearer auth validate function is not specified. Use bearer { validate(correctToken) } to fix."
)
}
var realm: String = "Ktor Server"
fun validate(correctToken: String) {
authenticationFunction = {
if (it.token == correctToken) {
EmptyPrincipal
} else {
null
}
}
}
}
}
fun Authentication.Configuration.bearer(
name: String? = null,
configure: BearerAuthenticationProvider.Configuration.() -> Unit
) {
val provider = BearerAuthenticationProvider(BearerAuthenticationProvider.Configuration(name).apply(configure))
val realm = provider.realm
val authenticate = provider.authenticationFunction
provider.pipeline.intercept(AuthenticationPipeline.RequestAuthentication) { context ->
val credentials = call.request.bearerAuthenticationCredentials()
val principal = credentials?.let { authenticate(call, it) }
val cause = when {
credentials == null -> AuthenticationFailedCause.NoCredentials
principal == null -> AuthenticationFailedCause.InvalidCredentials
else -> null
}
if (cause != null) {
context.challenge(BearerAuthenticationChallengeKey, cause) {
call.respond(
UnauthorizedResponse(
HttpAuthHeader.Parameterized(
"Bearer",
mapOf(HttpAuthHeader.Parameters.Realm to realm)
)
)
)
it.complete()
}
}
if (principal != null) {
context.principal(principal)
}
}
register(provider)
}
fun ApplicationRequest.bearerAuthenticationCredentials(): BearerPrincipal? {
when (val authHeader = parseAuthorizationHeader()) {
is HttpAuthHeader.Single -> {
if (!authHeader.authScheme.equals("Bearer", ignoreCase = true)) {
return null
}
return BearerPrincipal(authHeader.blob)
}
else -> return null
}
}
data class BearerPrincipal(val token: String): Principal
object EmptyPrincipal : Principal
private val BearerAuthenticationChallengeKey: Any = "BearerAuth"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment