GeezerVison is showing github.com — Support multiple authentication schemes for a single endpoint · Issue #1644 · oapi-codegen/oapi-codegen
Support multiple authentication schemes for a single endpoint #1644DescriptionThe OpenAPI spec allows specifying multiple security schemes per endpoint/api.
Examples taken from https://swagger.io/docs/specification/authentication/:
Example 1:
security: # A OR B
- A
- B
Example 2:
security: # A AND B
- A
B
Example 3:
security: # (A AND B) OR (C AND D)
- A
B
- C
D
Currently the generated server code for example 1 and 2 are identical, which means they cannot be differentiated from any middlewares. Activitymromaszewicz commented on Jun 6, 2024 I use oapi-codegen in this exact scenario, and this authentication logic doesn't need to go into the generated code, openapi3filter handles it just fine. It'll evaluate the boolean combination of auth schemes correctly, what you need to do is to provide a handler function to tell it whether each individual auth spec is correct.
What kind of generated code do you think would help here? alehed commented on Jun 6, 2024 Ideally the code generator would take care of this entirely, similarly like ogen does this with security handlers.
Alternatively, the generator could add some information to the request context about which authentication methods need to pass, such that a middleware can do the actual authentication. Right now we are using a middleware that guesses this information based on the scopes info in the request context.
I'm not super happy with using a separate tool that reads the api spec at runtime (this complicates deployment/testing). mromaszewicz commented on Jun 6, 2024 The generator doesn't have enough context to make an authorization decision for you entirely, this will always be a runtime check for your own code, with the aid of generated code or middleware. What I'm trying to say is that this can be done completely generically in middleware. This is how we do it for many API's that take multiple OIDC and BasicAuth providers.
At generation time, we don't know how you're going to validate each scheme, so that would have to be a callback for each kind, eg, A, B, C and D in your example, but then our generated code would entirely duplicate what the openapi3filter middleware does.
Let me poke around a bit and see how we can make this nicer today. alehed commented on Jun 6, 2024 I agree that it cannot be done without user-provided callbacks for A, B, C and D.
Right now we have a generic custom middleware which takes callbacks and does the authentication. But due to limited information it has, it can only check A OR B OR C OR D (or it could check the arguably less useful A AND B AND C AND D).
What our middleware does is basically:
for scopeKey, callback := range authenticators {
if r.Context().Value(scopeKey) != nil {
// call callback to check auth and break if successful
}
}
if !authenticated {
// send back 401
}
next.ServeHTTP(w, r)
So it checks for the scope keys in the context.
What I meant about the runtime thing is that to use openapi3filter you need to keep the yaml file around and have it available to the server at runtime (and we need to make sure that we use the same file for generation as well as validation, etc..). alehed commented on Jun 6, 2024 I just saw that you can use the EmbeddedSpec option to make this runtime loading of the spec potentially less painful. Reacted by Marcin Romaszewicz mromaszewicz commented on Jun 6, 2024 Yeah, exactly. The embedded spec is 100% guaranteed to be in-sync with your code and middleware should use it. It never even occurred to me that people wouldn't set this option :) mromaszewicz commented on Jul 16, 2026 We've deprecated embedding auth scope info into the request context, it's really a task for middleware to perform auth. Even the simple embedding we had was causing problems. It was a mistake to include any of this in the first place. We won't be expanding the codegen for auth, because the solution exists in validation middleware (and that's completely independent of any codegen, which is a good thing).
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|