JWT and JWK

note

JWT and JWK - 图1

This help topic is in development and will be updated in the future.

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>.

Ktor has a couple of classes to use the JWT Payload as Credential or as Principal.

  1. class JWTCredential(val payload: Payload) : Credential
  2. class JWTPrincipal(val payload: Payload) : Principal

Configuring server/routes:

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.

Using a verifier and a validator:

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.

application.conf:

  1. jwt {
  2. domain = "https://jwt-provider-domain/"
  3. audience = "jwt-audience"
  4. realm = "ktor sample app"
  5. }

JWT auth:

  1. val jwtIssuer = environment.config.property("jwt.domain").getString()
  2. val jwtAudience = environment.config.property("jwt.audience").getString()
  3. val jwtRealm = environment.config.property("jwt.realm").getString()
  4. install(Authentication) {
  5. jwt {
  6. realm = jwtRealm
  7. verifier(makeJwtVerifier(jwtIssuer, jwtAudience))
  8. validate { credential ->
  9. if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null
  10. }
  11. }
  12. }
  13. private val algorithm = Algorithm.HMAC256("secret")
  14. private fun makeJwtVerifier(issuer: String, audience: String): JWTVerifier = JWT
  15. .require(algorithm)
  16. .withAudience(audience)
  17. .withIssuer(issuer)
  18. .build()

Using a JWK provider:

  1. fun AuthenticationPipeline.jwtAuthentication(jwkProvider: JwkProvider, issuer: String, realm: String, validate: (JWTCredential) -> Principal?)
  1. val jwkIssuer = "https://jwt-provider-domain/"
  2. val jwkRealm = "ktor jwt auth test"
  3. val jwkProvider = JwkProviderBuilder(jwkIssuer)
  4. .cached(10, 24, TimeUnit.HOURS)
  5. .rateLimited(10, 1, TimeUnit.MINUTES)
  6. .build()
  7. install(Authentication) {
  8. jwt {
  9. verifier(jwkProvider, jwkIssuer)
  10. realm = jwkRealm
  11. validate { credentials ->
  12. if (credentials.payload.audience.contains(audience)) JWTPrincipal(credentials.payload) else null
  13. }
  14. }
  15. }