Ktor supports JWT (JSON Web Tokens), which is a mechanism for authenticating JSON-encoded payloads. It is useful to create stateless authenticated APIs in the standard way, since there are client libraries for it in a myriad of languages.
This feature will handle Authorization: Bearer <JWT-TOKEN>
.
io.ktor:ktor-auth-jwt:$ktor_version
中的
io.ktor.auth.jwt.jwt
方法中定义。
dependencies {
implementation "io.ktor:ktor-auth-jwt:$ktor_version"
}
dependencies {
implementation("io.ktor:ktor-auth-jwt:$ktor_version")
}
<project>
...
<dependencies>
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-auth-jwt</artifactId>
<version>${ktor.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Ktor has a couple of classes to use the JWT Payload as Credential
or as Principal
.
class JWTCredential(val payload: Payload) : Credential
class JWTPrincipal(val payload: Payload) : Principal
JWT and JWK each have their own method with slightly different parameters.
Both require the realm
parameter, which is used in the WWW-Authenticate response header.
The verifier will use the secret to verify the signature to trust the source.
You can also check the payload within validate
callback to ensure everything is right and to produce a Principal.
jwt {
domain = "https://jwt-provider-domain/"
audience = "jwt-audience"
realm = "ktor sample app"
}
val jwtIssuer = environment.config.property("jwt.domain").getString()
val jwtAudience = environment.config.property("jwt.audience").getString()
val jwtRealm = environment.config.property("jwt.realm").getString()
install(Authentication) {
jwt {
realm = jwtRealm
verifier(makeJwtVerifier(jwtIssuer, jwtAudience))
validate { credential ->
if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null
}
}
}
private val algorithm = Algorithm.HMAC256("secret")
private fun makeJwtVerifier(issuer: String, audience: String): JWTVerifier = JWT
.require(algorithm)
.withAudience(audience)
.withIssuer(issuer)
.build()
fun AuthenticationPipeline.jwtAuthentication(jwkProvider: JwkProvider, issuer: String, realm: String, validate: (JWTCredential) -> Principal?)
val jwkIssuer = "https://jwt-provider-domain/"
val jwkRealm = "ktor jwt auth test"
val jwkProvider = JwkProviderBuilder(jwkIssuer)
.cached(10, 24, TimeUnit.HOURS)
.rateLimited(10, 1, TimeUnit.MINUTES)
.build()
install(Authentication) {
jwt {
verifier(jwkProvider, jwkIssuer)
realm = jwkRealm
validate { credentials ->
if (credentials.payload.audience.contains(audience)) JWTPrincipal(credentials.payload) else null
}
}
}