Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Security path inputs always goes before regular input segments #3771

Open
pk1982r opened this issue May 17, 2024 · 3 comments
Open

[BUG] Security path inputs always goes before regular input segments #3771

pk1982r opened this issue May 17, 2024 · 3 comments

Comments

@pk1982r
Copy link

pk1982r commented May 17, 2024

Tapir version: 1.10.7

Scala version: 2.13.14

Security path segments always goes as first in the path. The sequence is not preserved.

What is the problem?

I need to declare endpoint where the security segment is not the first one.
The issue is not in OpenApi. Routes created from declarations also move security input as first segments.

Maybe you can provide code to reproduce the problem?

package com.softwaremill

import org.apache.pekko.actor.ActorSystem
import sttp.apispec.openapi.OpenAPI
import sttp.apispec.openapi.circe.yaml.RichOpenAPI
import sttp.tapir.docs.openapi.OpenAPIDocsInterpreter
import sttp.tapir.endpoint

object HelloWorldPekkoServer extends App {
  implicit val actorSystem: ActorSystem = ActorSystem()

  // should be /regular1/security1/regular2/security2
  // it is     /security1/security2/regular1/regular2:
  val helloWorld =
    endpoint.get
      .in("regular1")
      .securityIn("security1")
      .in("regular2")
      .securityIn("security2")


  val docs: OpenAPI = OpenAPIDocsInterpreter().toOpenAPI(helloWorld, "My Bookshop", "1.0")
  println(docs.toYaml)
}
@adamw
Copy link
Member

adamw commented May 19, 2024

This works as designed:

Any security inputs are decoded first, before regular inputs.

Maybe you can share the use-case of not having the security segment as the first ones, and maybe we can find another solution to the problem?

@pk1982r
Copy link
Author

pk1982r commented May 20, 2024

@adamw thank you for the clarification.
The problematic scenario is related to the authorization in the multi-tenancy service.
I will tackle the issue of declaring security path parameters as regular ones and share authorization logic between the endpoints. But it's not so clear solution, because security logic will leak to the service logic.

The example:
Let's take an OCPI protocol token interface as an example:
https://github.com/ocpi/ocpi/blob/master/mod_tokens.asciidoc#12-interfaces-and-endpoints

Endpoint structure definition:
{token_endpoint_url}/{country_code}/{party_id}/{token_uid}[?type={type}]
Example:
https://www.server.com/ocpi/cpo/2.2.1/tokens/NL/TNM/012345678

Authorization should check if a bearer is allowed to conduct actions for {country_code}/{party_id}. So we need to extract those two segments - NL/TNM in the example.
If we could extract those two segments to security logic we could have authentication and authorization enclosed in security scope.
Now we need to share the authorization code between GET/PUT/PATCH service logics.
This is not so uncommon pattern in authorization.

@adamw
Copy link
Member

adamw commented May 20, 2024

Ah ok, I see. In this situation, yes, you'll need to extract all path parameters that come before whatever you need in the security logic and make them pass-through, that is part of the security logic's output.

I think there were some downsides of having order-dependent decoding (it would probably complicate the data structure that represents an endpoint), but I agree that it's not always ideal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants