Adding Authentication
OpenAPI provides the ability to specify authentication in a few forms, which can be handled by creating Authentication Controllers.
Defining Authenticators
Authenticator controllers are created with the @Authenticator
decorator on a class that is passed as a controller along with your other controllers. This decorator takes the name of your security scheme, as well as the OpenAPI specification of the scheme.
This class should implement the AuthenticationController
interface, providing an authenticate
function to process the request for authentication requirements. This function will get called with the value of the authentication request, the scopes the endpoint requires, and a context providing the request, response, and detailed information about the endpoint being called. It can be synchronous, or asynchronous, and have the following behavior:
If authentication succeeds, it should return 'true', or an object containing details of the authentication which may be passed to the request method handler as input.
If authentication fails, the function may:
return false
throw an error matching the HttpError interface of the
http-errors
library.
HTTP Basic authentication
The HTTP Basic security scheme takes an encoded (not encrypted) username and password from the Authorization
header. @simply-openapi/controllers will decode the credentials and pass your authenticator an object containing the username
and password
properties.
HTTP Bearer authentication
The HTTP Bearer security scheme expects authentication in an Authorization
header, prefixed with Bearer
. @simply-openapi/controllers will validate the presense of this header and the Bearer prefix, before extracting the payload (everything after Bearer
) and passing it as the value to your authentication method.
Note that the bearerFormat
OpenAPI property is descriptive only; the value indicates no special processing instructions for OpenAPI and is not interpreted by this library.
Requiring Authentication
Authentication can be specified in 3 locations:
At the top level of your OpenAPI specification in the
security
property, to get applied to every endpointPer controller with the
@RequireAuthentication
decorator, to be applied only to methods in that controllerPer method with the
@RequireAuthentication
decorator, to be applied only to that method.
Per the OpenAPI spec, any authentication specified on a method or controller will take precedence over any authentication specified at the root level of your OpenAPI specification.
Requiring authentication for all endpoints
The OpenAPI specification provides the security
top level property, which specifies default security settings for all methods that do not themselves specify a security property.
This property is obeyed by the library, so setting it in your specification will appropriately gate all methods behind it, excepting methods that override it.
To pass in this property, use the addendOpenAPIFromControllers
method to generate the final OpenAPI schema given your starting fragment.
Requiring authentication on all methods of a controller
You can use the @RequireAuthentication
decorator on a controller to annotate that all methods in that controller are gated behind the specified security scheme.
The first argument to @RequireAuthentication
takes either a string name of the security scheme, or it can take a constructor for an AuthenticationController decorated with @Authenticator
.
The second argument to @RequireAuthentication
takes an array of scopes, all of which will be required to access the methods. Note that this is not handled automatically; your AuthenticationController must implement its own logic to check the given scopes against the decoded credentials.
Since OpenAPI has no concept of a controller to group the methods by, the security specification will be repeated on every method in the controller.
For convienence and to reduce duplication, @RequireAuthentication
can be given the class constructor of an existing @Authenticator
-marked authentication controller. This is the equivalent of passing the scheme name defined in that decorator.
You must still pass the @Authenticator
-decorated authentication controller to the list of controllers in createOpenAPIFromControllers
or addendOpenAPIFromControllers
in this case.
Requiring authentication on a specific method
You can use the @RequireAuthentication
decorator on a single method to annotate that the method is gated behind the specified security scheme.
The first argument to the decorator can either be a string specifying the name of the authenticator, or for convienence it may be the constructor of an authenticator class. In the case of the latter, the authenticator class must still be passed as a controller to createOpenAPIFromControllers
, or an error will be thrown when building the spec.
The OpenAPI specification indicates that multiple items in the security
array act as an any-of
fashion; if any entry in the list matches, the request is allowed. In support of this, you may specify @RequireAuthentication
multiple times.
If multiple
@RequireAuthentication
decorators specify the same security scheme, the scopes will be concatenatedIf multiple
@RequireAuthentication
decorators specify different security schemes, then any passing security scheme will allow access. Security schemes will be checked in-order, and the first passing one will be used.
Retrieving the authentication result
@RequireAuthentication
can be placed directly on method arguments. This will both ensure the user is authenticated, and provide the result of the authenticator to the decorated argument.
In the case of multiple security schemes, multiple parameters can be decorated.
Keep in mind that security schemes are tried in order of definition, and the library will stop at the first one to return a value. Due to this, you should only ever expect exactly one argument to be provided. All authentication decorators that were not used will have a value of undefined
.
Alternatively, you can use the @BindSecurity
decorator to retrieve the resolved security scheme value. This is useful in a few cases:
Security schemes defined in OpenAPI for bound methods
Security schemes defined in OpenAPI at the root level
Security schemes defined by
@RequireAuthentication
at the controller level
It is important to remember that @BindSecurity
does not authenticate the method. It only retrieves the value of the authenticator with the given name. If the authenticator was not called for the method in question, the argument will be undefined. In order for a security scheme authenticator to be applied to a method, it must be specified in the OpenAPI specification or by a decorator that adds such specification.
Like @RequireAuthentication
, you may pass a @Authenticator
-decorated class constructor in place of the scheme name.
Last updated