Releases: waza-ari/fastapi-keycloak-middleware
Version v1.1.0
New Features
Dependency based permission checking
This release introduces a new way of handling authorisation. The library now favours a dependency based approach for permission handling instead of the previous decorator based approach.
Warning
The old decorator based approach using the @require_permission
decorator is now deprecated and will be removed in version 2 of this library. For now, no breaking changes have been introduced. See the section about deprecations below for details
Migration
The most simple case is a normal permission. In this case, it can simply be rewritten by changing the @require_permission
decorator to the CheckPermission
dependency as follows:
# Old
@router.get("/your-endpoint")
@require_permission("your_permission")
async def your_endpoint(user = Depends(get_user)):
pass
# New
@router.get(
"/your-endpoint",
dependencies=[Depends(CheckPermissions("your_permission"))],
)
async def your_endpoint():
pass
Tip
Note that the new version doesn't include the get_user
dependency anymore. Using the CheckPermission
dependency automatically makes sure a user is successfully authenticated by presenting a valid token. You can of course still use the get_user
dependency is you need a reference to the user:
@router.get(
"/your-endpoint",
dependencies=[Depends(CheckPermissions("your_permission"))],
)
async def your_endpoint(user = Depends(get_user)):
pass
Complex permission matching
The new approach supports the same more complex patterns that the decorator based approach supported. You can provide a list of permissions and optionally a strategy that should be applied:
@router.get(
"/your-endpoint",
dependencies=[Depends(CheckPermissions(["your_first_permission", "your_second_permission"], match_strategy=MatchStrategy.OR))],
)
async def your_endpoint():
pass
Accessing the authorisation result
If you need to access the result (e.g. based on which permission the user was allowed access), you can now simply use the dependency result instead of using the decorator + the legacy get_authorization_result
dependency:
@router.get("/your-endpoint")
async def your_endpoint(authorization_result: AuthorizationResult = Depends(CheckPermissions(["your_first_permission", "your_second_permission"], match_strategy=MatchStrategy.OR))):
pass
New Doc section: testing
The docs have been extended and now include a section about my perceived best practices when testing applications secured by this library. These might not be the best ideas, I'm happy to hear about better options.
Deprecations
require_permission
decorator is deprecated and scheduled to be removed in the next major release.
The previous approach was based on the middleware injecting users and roles into the request scope, and then having the require_permission
extracting them from the request to perform access validation. It then injects the authorisation result to the next function call, but only if the dependency has been added to the method.
This approach was quite inflexible and "hacky", it required manual modification of the method signature if the dependency was used. This new approach makes testing simpler, will allow us to remove fairly complicated code in the future and is more in line with FastAPI principles.
get_authorization_result
is being marked as deprecated and is scheduled to be removed in the next major release.
Important
Both methods will emit a standard Python DeprecationWarning from this release onwards.
Full Changelog
feat: implement new way of handling authorization, switching away from the decorator approach. Currently, the decorator approach is still supported, it is marked deprecated in this release though.
[docs: adjust docs to correctly have authorization related config settings in KeycloakConfiguration. Fixes https://github.com//issues/54
build: raise version number to 1.0.2
fix: deprecation warnings after switching to Pydantic v2
fix: type hint of validation_option had wrong brackets](docs: adjust docs to correctly have authorization related config settings in KeycloakConfiguration. Fixes #54)docs: adjust docs to correctly have authorization related config settings in KeycloakConfiguration. Fixes #54
fix: remove non-required statements from init file
dev: add mypy cache files to gitignore
style: fix various typing issues
Full Changelog: v1.0.2...v1.1.0
v1.0.2
Breaking Changes
No breaking changes have been introduced.
Full Changelog
docs: adjust docs to correctly have authorization related config settings in KeycloakConfiguration. Fixes #54
build: raise version number to 1.0.2
fix: deprecation warnings after switching to Pydantic v2
fix: type hint of validation_option had wrong brackets
Full Changelog: v1.0.1...v1.0.2
v1.0.1
Breaking Changes
No breaking changes have been introduced.
Full Changelog
fix: type hint of validation_option had wrong brackets
Full Changelog: v0.1.0...v1.0.1
v1.0.0
Breaking Changes
The underlying python-keycloak
library has been updated to v4.0.0. This changes a couple of things:
python-jose
has been replaced withJWCrypto
for token validation. This means that the options that are available to customise token validation have changed- As a consequence, the
decode_options
setting ofKeycloakConfiguration
has been removed. In previous versions it was passed topython-keycloak
which in turn passed it topython-jose
- Two new settings have been introduced:
validate_token
accepts a boolean value and controls whetherpython-keycloak
will attempt to validate the token or notvalidation_options
acceptskwargs
that are passed straight to theJWT
constructor. Check the JWCrypto documentation for a list of supported arguments
Full Changelog
fix: use correct type for validation_options
waza-ari
chore: update python-keycloak to v4.0.0
waza-ari
Full Changelog: v0.4.2...v1.0.0
Release v0.4.2
What's Changed
- feat: add support for websocket authentication
- remove unused "install" package from pyproject.toml and poetry.lock requirements by @manfred-kaiser in #47
New Contributors
- @manfred-kaiser made their first contribution in #47
Full Changelog: v0.4.1...v0.4.2
v0.4.1
Breaking Changes
No breaking changes are introduced.
Full Changelog
- fix: swagger_client_id should be optional fixes #42
- docs: fix wrong swagger example
- docs: fix typo in docs for swagger UI integration
- fix: type hint for scope_mapper is missing async awaitable annotation
- style: switch to ruff for both linting and formatting
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #40
Full Changelog: v0.4.0...v0.4.1
Version 0.4.0
Overview
Changes
- New setup method to add middleware to FastAPI app - enabling additional features
- Error response code added to OpenAPI spec by default
- JSONResponse instead of PlainTextResponse following a consistent schema
New Features
- Swagger UI Authentication
Important Changes
New Setup Method
This version introduces a new method to configure the middleware for your FastAPI application. The old method of adding the Middleware class directly is still available and supported, therefore consider this as a new method adding new options while maintaining backwards compatibility.
Old usage
from fastapi_keycloak_middleware import KeycloakConfiguration, KeycloakMiddleware
# Set up Keycloak
keycloak_config = KeycloakConfiguration(
...
)
app = FastAPI()
# Add middleware with basic config
app.add_middleware(
KeycloakMiddleware,
keycloak_configuration=keycloak_config,
)
New usage
from fastapi_keycloak_middleware import KeycloakConfiguration, setup_keycloak_middleware
# Set up Keycloak
keycloak_config = KeycloakConfiguration(
...
)
app = FastAPI()
# Add middleware with basic config
setup_keycloak_middleware(
app,
keycloak_configuration=keycloak_config,
)
This allows us to make more sophisticated changes to the app, such as adding proper responses and add Swagger UI authentication.
Error Response codes
Error response codes are now enabled by default. See below for details.
New Feature
Swagger UI Authentication
It is now possible to properly configure the Swagger UI to authenticate against Keycloak and send requests with the correct token to the backend. Therefore it is now possible to actually test the API using Swagger UI. It requires the new setup method mentioned above and needs to be explicitly enabled.
** Example **:
keycloak_config = KeycloakConfiguration(
url="https://sso.your-keycloak.com/auth/",
realm="<Realm Name>",
client_id="<Client ID>",
client_secret="<Client Secret>",
swagger_client_id="<Swagger Client ID>",
swagger_auth_scopes=["openid", "profile"], # Optional
swagger_auth_pkce=True, # Optional
swagger_scheme_name="keycloak" # Optional
)
setup_keycloak_middleware(
app,
keycloak_configuration=keycloak_config,
add_swagger_auth=True
)
Please refer to the documentation for additional details.
Error Response codes
The library now has the ability to automatically add 401 and 403 error responses to the OpenAPI spec. This is mainly useful when working with client generators that automatically create client SDKs based on the OpenAPI spec. This feature is enabled by default, but doesn't overwrite any existing responses you may have added to your application.
The default behaviour can be disabled by setting the add_exception_response
to False
when calling setup_keycloak_middleware
:
setup_keycloak_middleware(
app,
keycloak_configuration=keycloak_config,
add_exception_response=False
)
Full Changelog
- fix: properly use Pydantic field defaults by @waza-ari in #36
- Switch from PlainTextResponse to JSONResponse by @waza-ari in #37
- fix: middleware typing was incorrectly accepting a FastAPI app, while… by @waza-ari in #38
- Add initialisation helper by @waza-ari in #39
Full Changelog: v0.3.1...v0.4.0
Version 0.3.1
Breaking Changes
No breaking changes are introduced.
Full Changelog
fix: pin python-keycloak to <v3.9.1 for now
This release is needed due to a change in python-keycloak
. See #30 for details.
Version 0.3.0
Breaking Changes
No breaking changes are introduced.
Full Changelog
feat(jwt): Make JWT decode options configurable #14
It is now possible to configure the options passed to python-jose
which is used to decode the JWT.
chore(dependencies): #15 update python-keycloak dependency
The decency on python-keycloak
was unnecessarily strict. It has been relaxed to allow any version above v2.14.0 (which the library has been written and tested with) and <v4 as there is no breaking change in v3 that affects this library.
Merge pull request #12 from hokiegeek2/11_update_keycloak_configuration
The SSL verification behaviour regarding the Keyclaok SSL certificate is now configurable. Possible values are True
, which validates the server certificate using the system certificate store, a string containing a path for a CA bundle file, in which case this CA bundle file is used to validate the certificate or False
which disables certificate validation altogether. Thanks @hokiegeek2 for the contribution!
Version 0.2.2
Breaking Changes
No breaking changes are introduced.