Skip to content

Version v1.1.0

Latest
Compare
Choose a tag to compare
@waza-ari waza-ari released this 28 Jul 17:47
· 12 commits to main since this release
4bdd1f8

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

⚠️ The 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.

⚠️ As a consequence, also the 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