mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 12:27:45 +00:00
231 lines
7.9 KiB
ReStructuredText
231 lines
7.9 KiB
ReStructuredText
Security
|
|
========
|
|
|
|
Connexion implements a pluggable security validation mechanism and provides built-in support for
|
|
some of the most popular security schemes.
|
|
|
|
.. csv-table::
|
|
:widths: 30, 70
|
|
:header-rows: 1
|
|
|
|
**Swagger 2**, **Connexion support**
|
|
Basic Authentication, |:white_check_mark:|
|
|
API key, |:white_check_mark:|
|
|
Oauth2, |:white_check_mark:|
|
|
**OpenAPI**,
|
|
HTTP Basic, |:white_check_mark:|
|
|
HTTP Bearer, |:white_check_mark:|
|
|
Other HTTP schemes (RFC 7253), "No built-in support, use a `custom security handler <#custom-security-handlers>`_"
|
|
API key, |:white_check_mark:|
|
|
Oauth2, |:white_check_mark:|
|
|
OpenID, "No built-in support, use a `custom security handler <#custom-security-handlers>`_"
|
|
|
|
General authentication flow
|
|
---------------------------
|
|
|
|
For each supported authentication type, Connexion lets you register a validation function to
|
|
validate the incoming credentials, and return information about the authenticated user.
|
|
|
|
The validation function must either be defined in the API security definition
|
|
as ``x-{type}InfoFunc``, or in the environment variables as ``{TYPE}INFO_FUNC``. The function
|
|
should be referenced as a string using the same syntax that is used to connect an ``operationId``
|
|
to a Python function when :ref:`routing <Routing:Explicit routing>`.
|
|
|
|
While the validation functions should accept different arguments based on the authentication type
|
|
(as documented below), they should all return a dict which complies with `RFC 7662 <rfc7662_>`_:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"active": true,
|
|
"client_id": "l238j323ds-23ij4",
|
|
"username": "jdoe",
|
|
"scope": "read write dolphin",
|
|
"sub": "Z5O3upPC88QrAjx00dis",
|
|
"aud": "https://protected.example.net/resource",
|
|
"iss": "https://server.example.com/",
|
|
"exp": 1419356238,
|
|
"iat": 1419350238,
|
|
"extension_field": "twenty-seven"
|
|
}
|
|
|
|
The token information is made available to your endpoint view functions via the
|
|
:ref:`context <context:context.context>`, which you can also have passed in as an
|
|
:ref:`argument <request:Context>`.
|
|
|
|
.. note::
|
|
|
|
Note that you are responsible to validate any fields other than the scopes yourself.
|
|
|
|
.. _rfc7662: https://tools.ietf.org/html/rfc7662
|
|
|
|
Basic Authentication
|
|
--------------------
|
|
|
|
For Basic authentication, the API security definition must include an
|
|
``x-basicInfoFunc`` definition or set the ``BASICINFO_FUNC`` environment variable.
|
|
|
|
The function should accept the following arguments:
|
|
|
|
- username
|
|
- password
|
|
- required_scopes (optional)
|
|
|
|
You can find a `minimal Basic Auth example application`_ in Connexion's "examples" folder.
|
|
|
|
.. _minimal Basic Auth example application: https://github.com/spec-first/connexion/tree/main/examples/basicauth
|
|
|
|
Bearer Authentication (JWT)
|
|
---------------------------
|
|
|
|
For Bearer authentication (JWT), the API security definition must include an
|
|
``x-bearerInfoFunc`` definition or set the ``BEARERINFO_FUNC`` environment variable.
|
|
|
|
The function should accept the following arguments:
|
|
|
|
- token
|
|
- required_scopes (optional)
|
|
|
|
You can find a `minimal Bearer example application`_ in Connexion's "examples" folder.
|
|
|
|
.. _minimal Bearer example application: https://github.com/spec-first/connexion/tree/main/examples/jwt
|
|
|
|
ApiKey Authentication
|
|
---------------------
|
|
|
|
For API key authentication, the API security definition must include an
|
|
``x-apikeyInfoFunc`` definition or set the ``APIKEYINFO_FUNC`` environment variable.
|
|
|
|
The function should accept the following arguments:
|
|
|
|
- apikey
|
|
- required_scopes (optional)
|
|
|
|
You can find a `minimal API Key example application`_ in Connexion's "examples" folder.
|
|
|
|
.. _minimal API Key example application: https://github.com/spec-first/connexion/tree/main/examples/apikey
|
|
|
|
OAuth 2 Authentication and Authorization
|
|
----------------------------------------
|
|
|
|
For OAuth authentication, the API security definition must include an
|
|
``x-tokenInfoFunc`` definition or set the ``TOKENINFO_FUNC`` environment variable.
|
|
|
|
The function should accept the following arguments:
|
|
|
|
- token
|
|
- required_scopes (optional)
|
|
|
|
As alternative to an ``x-tokenInfoFunc`` definition, you can set an ``x-tokenInfoUrl`` definition or
|
|
``TOKENINFO_URL`` environment variable, and connexion will call the url instead of a local
|
|
function instead. Connexion expects the authorization server to receive the OAuth token in the
|
|
``Authorization`` header field in the format described in `RFC 6750 <rfc6750_>`_ section 2.1 and
|
|
return the token information in the same format as a validation function. When both
|
|
``x-tokenInfoUrl`` and ``x-tokenInfoFunc`` are used, Connexion will prioritize the function.
|
|
|
|
The list of scopes returned in the token information will be validated against the scopes
|
|
required by the API security definition to determine if the user is authorized.
|
|
You can supply a custom scope validation func by defining ``x-scopeValidateFunc``
|
|
or setting a ``SCOPEVALIDATE_FUNC`` environment variable.
|
|
|
|
The function should accept the following arguments:
|
|
|
|
- required_scopes
|
|
- token_scopes
|
|
|
|
and return a boolean indicating if the validation was successful.
|
|
|
|
Deprecated features, retained for backward compatibility:
|
|
|
|
- ``scope`` field can also be named ``scopes``.
|
|
- ``sub`` field can also be named ``uid``.
|
|
|
|
You can find a `minimal OAuth example application`_ showing the use of
|
|
``x-tokenInfoUrl``, and `another OAuth example`_ showing the use of
|
|
``x-tokenInfoFunc`` in Connexion's "examples" folder.
|
|
|
|
.. _minimal OAuth example application: https://github.com/spec-first/connexion/tree/main/examples/oauth2
|
|
.. _another OAuth example: https://github.com/spec-first/connexion/tree/main/examples/oauth2_local_tokeninfo
|
|
.. _rfc6750: https://tools.ietf.org/html/rfc6750
|
|
|
|
Multiple Authentication Schemes
|
|
-------------------------------
|
|
|
|
With Connexion, it is also possible to combine multiple authentication schemes
|
|
as described in the `OpenAPI specification`_. When multiple authentication
|
|
schemes are combined using logical AND, the ``token_info`` argument will
|
|
consist of a dictionary mapping the names of the security scheme to their
|
|
corresponding ``token_info``.
|
|
|
|
Multiple OAuth2 security schemes in AND fashion are not supported.
|
|
|
|
.. _OpenAPI specification: https://swagger.io/docs/specification/authentication/#multiple
|
|
|
|
Custom security handlers
|
|
------------------------
|
|
|
|
You can implement your own security handlers for schemes that are not supported yet in Connexion
|
|
by subclassing the ``connexion.security.AbstractSecurityHandler`` class and passing it in a custom
|
|
``security_map`` to your application or API:
|
|
|
|
.. code-block:: python
|
|
:caption: **app.py**
|
|
|
|
from connexion.security import AbstractSecurityHandler
|
|
|
|
|
|
class MyCustomSecurityHandler(AbstractSecurityHandler):
|
|
|
|
security_definition_key = "x-{type}InfoFunc"
|
|
environ_key = "{TYPE}INFO_FUNC"
|
|
|
|
def _get_verify_func(self, {type}_info_func):
|
|
...
|
|
|
|
security_map = {
|
|
"{type}": MyCustomSecurityHandler,
|
|
}
|
|
|
|
.. tab-set::
|
|
|
|
.. tab-item:: AsyncApp
|
|
:sync: AsyncApp
|
|
|
|
.. code-block:: python
|
|
:caption: **app.py**
|
|
|
|
from connexion import AsyncApp
|
|
|
|
app = AsyncApp(__name__, security_map=security_map)
|
|
app.add_api("openapi.yaml", security_map=security_map)
|
|
|
|
|
|
.. tab-item:: FlaskApp
|
|
:sync: FlaskApp
|
|
|
|
.. code-block:: python
|
|
:caption: **app.py**
|
|
|
|
from connexion import FlaskApp
|
|
|
|
app = FlaskApp(__name__, security_map=security_map)
|
|
app.add_api("openapi.yaml", security_map=security_map)
|
|
|
|
.. tab-item:: ConnexionMiddleware
|
|
:sync: ConnexionMiddleware
|
|
|
|
.. code-block:: python
|
|
:caption: **app.py**
|
|
|
|
from asgi_framework import App
|
|
from connexion import ConnexionMiddleware
|
|
|
|
app = App(__name__)
|
|
app = ConnexionMiddleware(app, security_map=security_map)
|
|
app.add_api("openapi.yaml", security_map=security_map)
|
|
|
|
.. note::
|
|
|
|
If you implement a custom security handler, and think it would be valuable for other users, we
|
|
would appreciate it as a contribution.
|