Created
March 8, 2022 00:14
-
-
Save bvlion/f8301987635b524238a14da2c7321c86 to your computer and use it in GitHub Desktop.
Bearer トークンの妥当性だけを確認する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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