question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Security documentation not being generated

See original GitHub issue

We’ve been able to implement JWT-authenticated endpoints through the Ktor-OpenAPI-Generator API, and authentication works - but the generated OpenAPI.json doesn’t contain any information about the security scheme. It should, right?

We have written the following code to tell Ktor-OpenAPI-Generator about the authentication:

  val authProvider = JwtProvider();

  inline fun NormalOpenAPIRoute.auth(route: OpenAPIAuthenticatedRoute<UserPrincipal>.() -> Unit): 
  OpenAPIAuthenticatedRoute<UserPrincipal> {
    val authenticatedKtorRoute = this.ktorRoute.authenticate { }
    var openAPIAuthenticatedRoute= OpenAPIAuthenticatedRoute(authenticatedKtorRoute, this.provider.child(), authProvider = authProvider);
    return openAPIAuthenticatedRoute.apply {
        route()
    }
  }

  data class UserPrincipal(val userId: String, val email: String?, val name: String?) : Principal

  class JwtProvider : AuthProvider<UserPrincipal> {
    override val security: Iterable<Iterable<Security<*>>> =
        listOf(listOf(Security(SecuritySchemeModel(SecuritySchemeType.openIdConnect, scheme = HttpSecurityScheme.bearer, bearerFormat = "JWT", name = "JWT"), Scopes.values().toList())))

    override suspend fun getAuth(pipeline: PipelineContext<Unit, ApplicationCall>): UserPrincipal {
        return pipeline.context.authentication.principal() ?: throw RuntimeException("No JWTPrincipal")
    }

    override fun apply(route: NormalOpenAPIRoute): OpenAPIAuthenticatedRoute<UserPrincipal> {
        val authenticatedKtorRoute = route.ktorRoute.authenticate { }
        return OpenAPIAuthenticatedRoute(authenticatedKtorRoute, route.provider.child(), this)
    }
  }

  enum class Scopes(override val description: String) : Described {
    Profile("Some scope")
  }

In our Application.apirouting, we wrap the required paths with auth{}, and make sure we use the routing functions from com.papsign.ktor.openapigen.route.path.auth.* in those cases. We are able to access the authenticated user through the principal()-function. An example:

auth {
  route("/user") {
        get<Unit, List<User>, UserPrincipal> {
            val principal = principal()
            log.info("principal1 ${principal.userId}")
            log.info("principal1 ${principal.email}")
            respond(registry.userRepository.retrieveAllUsers())
        }
  }
}

Everything seems to work fine for actual use - but as mentioned, we’re not finding any information about the security scheme in the generated openapi.json. 😦

We are calling addModules(authProvider) as part of the installation of OpenAPIGen, but we’re under the impression this isn’t working as intended. (We are supposed to add it as a module, right?) Here, we’re ending up in the object com.papsign.ktor.openapigen.modules.handlers.AuthHandler:

package com.papsign.ktor.openapigen.modules.handlers

import com.papsign.ktor.openapigen.OpenAPIGen
import com.papsign.ktor.openapigen.model.operation.OperationModel
import com.papsign.ktor.openapigen.model.security.SecurityModel
import com.papsign.ktor.openapigen.modules.ModuleProvider
import com.papsign.ktor.openapigen.modules.ofType
import com.papsign.ktor.openapigen.modules.openapi.OperationModule
import com.papsign.ktor.openapigen.modules.providers.AuthProvider

object AuthHandler: OperationModule {
    override fun configure(apiGen: OpenAPIGen, provider: ModuleProvider<*>, operation: OperationModel) {
        val authHandlers = provider.ofType<AuthProvider<*>>()
        val security = authHandlers.flatMap { it.security }.distinct()
        operation.security = security.map { SecurityModel().also { sec ->
            it.forEach { sec[it.scheme.name] = it.requirements }
        } }
        apiGen.api.components.securitySchemes.putAll(security.flatMap { it.map { it.scheme } }.associateBy { it.name })
    }
}

Here, in the configure method, provider seems to contain our authProvider object, but it isn’t returned from the “provider.ofType<AuthProvider<*>>()” call. But at this point we’re a bit uncertain if we’re barking up the wrong tree, and if we’re not, why our AuthProvider isn’t recognized as one by ofType…

We’re not sure if this is a bug in OpenAPIGen or just something we haven’t understood about how to use the framework. Any help would be greatly appreciated.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:19 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
davidhiendlcommented, Jul 24, 2020

Actually I’m mistaken, my latest KType changes have not been released yet - but I will take a look at it regardless as I have the same problem.

1reaction
davidhiendlcommented, Jul 24, 2020

Hello, I actually wrote that change to KType and must have missed something. I will take a look at it shortly (as I noticed this problem myself with our my project). A failing test would be helpful.

Read more comments on GitHub >

github_iconTop Results From Across the Web

What Is Documentation Security and Why It Matters?
The issues to be considered in document security are as follows: Documents that are not adequately labeled or packaged are often challenging ...
Read more >
Data Security Standards When Generating Paperless ... - Inkit
Generating paperless documents? Be sure to follow these 7 best data security standards for compliant, safe, and efficient document ...
Read more >
Trusted documents - Microsoft Support
More reasons why files cannot be made trusted documents · The file opened from an unsafe location, such as your temporary Internet folder...
Read more >
Setting up security policies for PDFs - Adobe Support
Creating policies for password and certificate security in Adobe Acrobat lets you reuse the same security settings for any number of PDFs.
Read more >
Container and Document Security - iManage Control Center
A value must to be assigned when a container is created, or a document is ... Indicates that the document does not have...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found