3 weeks ago - last edited 3 weeks ago
Hi there,
I have a fastapi app with 2 routes, one for rendering an html page and one for serving a request. I am using Jinja2 for templating.
Example of one of the route:
@router.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
My manifest.yaml for deploying it to cloud foundry:
---
applications:
- name: fastapi-app
disk_quota: 2048M
memory: 256M
path: ./
routes:
- route: fastapi-app.cfapps.eu10.hana.ondemand.com
buildpacks:
- python_buildpack
command: uvicorn com.crack.snap.make.app:app --host 0.0.0.0 --port $PORT
services:
- app-xsuaa
- app-logging-service
logging:
level: error
env:
PYTHONUNBUFFERED: true
xsuaa_connectivity_instance_name: "app-xsuaa"
xsuaa_destination_instance_name: "app-xsuaa"
How do I protect these fastapi routes directly using XSUAA, without having to create one more webapp then use app-router and then forwarding the request to fastapi app?
Also I want the fastapi to use the sub-account's default authentication which we do by using redirect-url of xs-security.json
{
"xsappname": "fastapi-app",
"tenant-mode": "dedicated",
"scopes": [{
"name": "$XSAPPNAME.fastapi_scope"
}],
"role-templates": [{
"name": "FastAPIRoleTemplate",
"default-role-name": "FastAPIRole",
"description": "Role template for app users",
"scope-references": ["$XSAPPNAME.fastapi_scope"]
}
],
"oauth2-configuration": {
"redirect-uris": [
"https://*.cfapps.eu10.hana.ondemand.com/**"
]
}
}
Any help on achieving this will be really appreciated, we can also have a blog post on the same topic
SAP BTP, Cloud Foundry runtime and environment Python SAP BTP Security
I did not find any straight forward solution to this, so I took a little turn around. Since we don't have `@sap/approuter` as a plugin for python/java applications yet. We will need to use Node for using the approuter.
Steps taken to achieve my goal:
1. Create a new node app for sap-approuter, check the below manifest.yaml
- name: router
routes:
- route: fastapi-app.cfapps.eu10.hana.ondemand.com
env:
destinations: >
[
{
"name":"fastapi-app",
"url":"https://fastapi-srv.cfapps.eu10.hana.ondemand.com",
"forwardAuthToken": true,
"timeout": 600000
}
]
disk_quota: 256M
timeout: 600
memory: 256M
path: web
services:
- a-xsuaa
- a-logging-service
If you need more information on creating the node app, refer to this tutorial.
This destination will be used later to hit the FastAPI app through app-router app after authentication
2. Simple example xs-security.json for creating the xsuaa instance, where I will use our default IdP of the sub-account for authentication.
{
"xsappname": "fastapi-app",
"tenant-mode": "dedicated",
"oauth2-configuration": {
"redirect-uris": [
"https://fastapi-app.cfapps.eu10.hana.ondemand.com/**"
]
}
}
3. The magic of redirect resides in the xs-app.json, where i will redirect all incoming requests after authentication to FastAPI App. Whenever the user hits app-router app url `fastapi-app.cfapps.eu10.hana.ondemand.com`, which in my case gives an impression of FastAPI app url, I will simply redirect them to FastAPI's route which in turns returns the landing page for the user.
{
"routes": [
{
"source": "/(.*)",
"target": "$1",
"destination": "fastapi-app",
"httpMethods": ["GET"],
"csrfProtection": false
}
],
"errorPage": [
{
"status": [403],
"file": "resources/forbidden.html"
},
{
"status": [404],
"file": "resources/404.html"
}
]
}
Here the destination should match the destination's name environment variable that we created in manifest.yaml that's how it know which server to call with the generated oauth token after authentication.
4. Example of the FastAPI route to return the landing page after authorization check
router = APIRouter()
templates = Jinja2Templates(directory="com/crack/snap/make/templates")
@router.get("/", response_class=HTMLResponse)
async def read_root(request: Request, security_context: Optional[SecurityContextXSUAA] = Depends(require_auth)):
return templates.TemplateResponse("index.html", {"request": request})
5. I have skipped the role creation and role check for simplicity
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The tutorial Create an Application with Cloud Foundry Python Buildpack provides an example using Flask. Maybe you can adopt that to FastAPI. Would be great if you share it afterwards.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
66 | |
10 | |
10 | |
10 | |
10 | |
8 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.