Easy and secure implementation of Azure AD for your FastAPI APIs
Project description
FastAPI-Azure-Auth
Azure AD Authentication for FastAPI apps made easy.
🚀 Description
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python, based on standard Python type hints.
At Intility, FastAPI is a popular framework among its developers, with customer-facing and internal services developed entirely on a FastAPI backend.
This package enables our developers (and you 😊) to create features without worrying about authentication and authorization.
Also, we're hiring!
⚡️ Quick start
Azure
Azure docs will be available when create-fastapi-app is developed. In the meantime please use the .NET documentation.
FastAPI
1. Install this library:
pip install fastapi-azure-auth
# or
poetry add fastapi-azure-auth
2. Configure your FastAPI app
Include swagger_ui_oauth2_redirect_url
and swagger_ui_init_oauth
in your FastAPI app initialization:
# file: main.py
app = FastAPI(
...
swagger_ui_oauth2_redirect_url='/oauth2-redirect',
swagger_ui_init_oauth={
'usePkceWithAuthorizationCodeGrant': True,
'clientId': settings.OPENAPI_CLIENT_ID # SPA app with grants to your app
},
)
3. Setup CORS
Ensure you have CORS enabled for your local environment, such as http://localhost:8000
. See main.py
and the BACKEND_CORS_ORIGINS
in config.py
4. Configure the AzureAuthorizationCodeBearer
You can do this in main.py
, but it's recommended to put it
in your dependencies.py
file instead, as this will avoid circular imports later.
See the demo project and read the official documentation
on bigger applications
# file: demoproj/api/dependencies.py
from fastapi_azure_auth.auth import AzureAuthorizationCodeBearer
azure_scheme = AzureAuthorizationCodeBearer(
app=app,
app_client_id=settings.APP_CLIENT_ID, # Web app
scopes={
f'api://{settings.APP_CLIENT_ID}/user_impersonation': 'User Impersonation',
},
)
5. Configure dependencies
Set your intility_scheme
as a dependency for your wanted views/routers:
# file: main.py
from demoproj.api.dependencies import azure_scheme
app.include_router(api_router, prefix=settings.API_V1_STR, dependencies=[Depends(azure_scheme)])
6. Load config on startup
This is optional but recommended. This will ensure the app crashes if something is misconfigured on startup (instead of when someone tries to do a request), and ensures the first request don't have to wait for the provider config to load.
# file: main.py
from fastapi_azure_auth.provider_config import provider_config
@app.on_event('startup')
async def load_config() -> None:
"""
Load config on startup.
"""
await provider_config.load_config()
⚙️ Configuration
For those using a non-Intility tenant, you also need to make changes to the provider_config
to match
your tenant ID. You can do this in your previously created load_config()
function.
# file: main.py
from fastapi_azure_auth.provider_config import provider_config
@app.on_event('startup')
async def load_config() -> None:
provider_config.tenant_id = 'my-own-tenant-id'
await provider_config.load_config()
If you want, you can deny guest users to access your API by passing the allow_guest_users=False
to AzureAuthorizationCodeBearer
:
# file: demoproj/api/dependencies.py
azure_scheme = AzureAuthorizationCodeBearer(
...
allow_guest_users=False
)
💡 Nice to knows
User object
A User
object is attached to the request state if the token is valid. Unparsed claims can be accessed at
request.state.user.claims
.
# file: demoproj/api/api_v1/endpoints/hello_world.py
from fastapi_azure_auth.user import User
from fastapi import Request
@router.get(...)
async def world(request: Request) -> dict:
user: User = request.state.user
return {'user': user}
Permission checking
You often want to check that a user has a role or using a specific scope. This
can be done by creating your own dependency, which depends on azure_scheme
. The azure_scheme
dependency
returns a fastapi_azure_auth.user.User
object.
Create your new dependency, which checks that the user has the correct role (in this case the
AdminUser
-role):
# file: demoproj/api/dependencies.py
from fastapi import Depends
from fastapi_azure_auth.auth import InvalidAuth
from fastapi_azure_auth.user import User
async def validate_is_admin_user(user: User = Depends(azure_scheme)) -> None:
"""
Validated that a user is in the `AdminUser` role in order to access the API.
Raises a 401 authentication error if not.
"""
if 'AdminUser' not in user.roles:
raise InvalidAuth('User is not an AdminUser')
Add the new dependency on either your route or on the API, as we've done in our demo project.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for fastapi-azure-auth-3.0.0rc1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0f92ee3d3fabc473824e950adf8d9dcca27e34d9aee3f03be2ab60ce16066bef |
|
MD5 | 3c15334c3b733b1879bdae81a1ce1d07 |
|
BLAKE2b-256 | 55e1fb7a679c005edb816ab71e56e14f059eb67bafd27646cda342647df6db30 |
Hashes for fastapi_azure_auth-3.0.0rc1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8775961fc61e22eb058469c113e5545dbc9ee5c91ac9f52792e9b53977371ce6 |
|
MD5 | f6489f1a9d96886c63833da065660aa6 |
|
BLAKE2b-256 | 7661d9d1533fd5a649d49f3e17fe742956db22d979356c5fa55488be41bd3191 |