Package: sag-py-auth-brand
sag_py_auth_brandThis provides a way to secure your fastapi with keycloak jwt bearer authentication.
This library bases on sag_py_auth and adds support for instances/brands.What it doesSecure your api endpointsVerifies auth tokens: signature, expiration, issuer, audienceVerifies the brand/customer over a token role (+ alias support)Verifies the instance over a token roleVerifies the stage over a realm roleAllows to set additional permissions by specifying further token rolesSupplies brand information from contextHow to useInstallationpip install sag-py-auth-brandSecure your apisFirst create the fast api dependency with the auth config:fromsag_py_authimportTokenRolefromsag_py_auth_brand.modelsimportAuthConfigfromsag_py_auth_brand.brand_jwt_authimportBrandJwtAuthfromfastapiimportDependsauth_config=BrandAuthConfig("https://authserver.com/auth/realms/projectName","myaudience","myinstance","mystage")required_roles=[TokenRole("clientname","adminrole")]requires_admin=Depends(BrandJwtAuth(auth_config,required_endpoint_roles))Afterwards you can use it in your route like that:@app.post("/posts",dependencies=[requires_admin],tags=["posts"])asyncdefadd_post(post:PostSchema)->dict:Or if you use sub routes, auth can also be enforced for the entire route like that:router=APIRouter()router.include_router(sub_router,tags=["my_api_tag"],prefix="/subroute",dependencies=[requires_admin])Get brand informationSee sag_py_auth to find out how to access the token and user info.Furthermore you can get the brand by accessing it over the context:fromsag_py_auth_brand.request_brand_contextimportget_brandasget_brand_from_contextbrand=get_brand_from_context()This works in async calls but not in sub threads (without additional changes).See:https://docs.python.org/3/library/contextvars.htmlhttps://kobybass.medium.com/python-contextvars-and-multithreading-faa33dbe953dLog the brandIt is possible to log the brand by adding a filter.importloggingfromsag_py_auth_brand.request_brand_logging_filterimportRequestBrandLoggingFilterconsole_handler=logging.StreamHandler(sys.stdout)console_handler.addFilter(RequestBrandLoggingFilter())The filter provides the field request_brand and request_brand_alias with the brand.How a token has to look like{"iss":"https://authserver.com/auth/realms/projectName","aud":["audienceOne","audienceTwo"],"typ":"Bearer","azp":"public-project-swagger","preferred_username":"preferredUsernameValue",....."realm_access":{"roles":["myStage"]},"resource_access":{"role-instance":{"roles":["myInstance"]},"role-brand":{"roles":["myBrand"]},"role-endpoint":{"roles":["permissionOne","permissionTwo"]},"role-brand-alias":{"roles":["myBrand","myBrandAliasOne","myBrandAliasTwo"]}}}role-endpoint is just required for permission checks of the api endpointrole-brand-alias is optional for the alias feature. If you don't use aliases it can be left ayway.role-brand-alias must contain exactly one original brand (also called the compound brand alias) together with one or multiple aliasesHow to start developingWith vscodeJust install vscode with dev containers extension. All required extensions and configurations are prepared automatically.With pycharmInstall latest pycharmInstall pycharm plugin BlackConnectInstall pycharm plugin MypyConfigure the python interpreter/venvpip install requirements-dev.txtpip install black[d]Ctl+Alt+S => Check Tools => BlackConnect => Trigger when saving changed filesCtl+Alt+S => Check Tools => BlackConnect => Trigger on code reformatCtl+Alt+S => Click Tools => BlackConnect => "Load from pyproject.yaml" (ensure line length is 120)Ctl+Alt+S => Click Tools => BlackConnect => Configure path to the blackd.exe at the "local instance" config (e.g. C:\Python310\Scripts\blackd.exe)Ctl+Alt+S => Click Tools => Actions on save => Reformat codeRestart pycharmHow to publishUpdate the version in setup.py and commit your changeCreate a tag with the same version numberLet github do the rest