tapir icon indicating copy to clipboard operation
tapir copied to clipboard

Let serverSecurityLogic access path values

Open geirolz opened this issue 1 year ago • 3 comments

Given this code I have some doubts

// user/{id}
val getUser = endpoint
   .securityIn(sttp.tapir.auth.bearer[AuthEncodedToken]())
   .in("user")
   .in(path[UserId]("id"))

val ep = getUser
   .serverSecurityLogic(token => decodeAndValidateToken(token))
   .serverLogic(token => userId => canAccessOrForbidden(token, userId) { ... })

The problem is that with this design within serverSecurityLogic i can just decode the token, if I want to check that the token has the rights to access that user I have to move this logic in serverLogic because I don't have access to the UserId. This force to have the security logic in two places.

It would be great to have access to the endpoint path values within serverSecurityLogic in order to have the security checks all in one place.

Am I not seeing it right ? Is there a solution ?

geirolz avatar Mar 15 '24 16:03 geirolz

I think the solution is to simply make all path components a .securityIn. The inputs differ in the order of decoding: first all security inputs are decoded, the security logic is run, and then the rest of the inputs. See the note here: https://tapir.softwaremill.com/en/latest/endpoint/security.html#authentication-inputs

So you'd have:

val getUser = endpoint
   .securityIn(sttp.tapir.auth.bearer[AuthEncodedToken]())
   .securityIn("user")
   .securityIn(path[UserId]("id"))

adamw avatar Mar 15 '24 16:03 adamw

Thanks @adamw for the quick reply. Do you this as a workaround or a definitive solution ? Because in this way then in serverLogic I won't have access to UserId

geirolz avatar Mar 15 '24 17:03 geirolz

Yes, then whatever security logic returns is available to the server logic - this might include any "raw" values from the inputs that are needed by the security logic to be also consumed by the server logic.

adamw avatar Mar 18 '24 16:03 adamw