The plugin currently supports single-tenancy only. The goal of this issue is to add multitenancy support.
Below is the information shared by Colin Ng regarding multitenancy in Document AI:
- Each subscriber tenant is expected to provision its own service instance. Data in each instance is isolated. Example: if a user wants 2 Doc AI environment (DEV, PROD), they provision 1 Doc AI subscription (which provides UI) and provision 2 Doc AI instances (1 for DEV, 1 for PROD).
Subscription: Just provisions a UI. You can just take it as a UI shell/entry point. It has no tenant data associated. You may ignore this in the context of this tenancy topic.
Instance: 1 instance will create 1 HANA container, where each instance's data is isolated. So 1 instance = 1 tenant is a fair interpretation.
Client: In a single instance, a user can create a few clients to create logical separation between their data. This is a virtual separation - data from different clients are stored in the same HANA container. We do not use this for multi-tenancy as it is not safe. User can change the ODATA filter in their Api calls and access another client’s data. This client concept is not relevant in the context of multi-tenancy. You may ignore this.
In summary, to handle multi-tenancy, you just need to be concerned about instances - how underlying users can provide the tokens associated with their instances to the multi-tenant CAP app.
- Firstly, the client concept is not what we use to segregate tenants. In our context, multi-tenancy means each customer using the CAP app (that integrates our CAP plugin) provides their own Doc AI instance.
From the API POV, each tenant will use his own authorization header tokens (obtained from the oauth/token of their Doc AI instance) in their API calls. That is how we distinguish tenants.
We implemented a solution to handle multi-tenancy in our own plugin implementation that we were developing before we came across your repo. So there’s 2 main types of scenarios as you have identified:
CAP app only uses 1 doc AI instance belonging to the provider. In this case, the service binding approach works. But this is not multi-tenancy. This just assumes that the CAP app developer just needs 1 instance to be shared across all users for their use case.
Multi-tenant CAP app where users provide their Doc AI instances. In this case, retrieval of credentials via service binding no longer works. End-users’ Doc AI instance subscriptions will never be accessible to us via service binding since it lives in their (subscriber) BTP whereas the CAP app lives in the developer (provider) BTP. Our solution is to use the destination service. Destination service allows a provider CAP app to access end-users’ (subscriber) destinations. A user is required to input their Doc AI service key details as a destination in their BTP using a predefined name (e.g DOC_AI_INSTANCE). The provider CAP app is configured to, in turn, fetch tokens from this destination. This allows the CAP app to fetch the users' tokens and support multi-tenancy.
In our implementation, we incorporated both: It will look for a service binding first. If that doesn’t exist, it falls back to relying on destination service (to look for the user’s Doc AI destination). Even in the first scenario, we convert the bindings to a destination. Our rationale is that the cloud SDK helps to handle the token caching/refresh as we do not want to call the /oauth endpoint to regenerate the token during each request nor do we do not want to handle token caching ourselves in the plugin.
The plugin currently supports single-tenancy only. The goal of this issue is to add multitenancy support.
Below is the information shared by Colin Ng regarding multitenancy in Document AI:
Subscription: Just provisions a UI. You can just take it as a UI shell/entry point. It has no tenant data associated. You may ignore this in the context of this tenancy topic.
Instance: 1 instance will create 1 HANA container, where each instance's data is isolated. So 1 instance = 1 tenant is a fair interpretation.
Client: In a single instance, a user can create a few clients to create logical separation between their data. This is a virtual separation - data from different clients are stored in the same HANA container. We do not use this for multi-tenancy as it is not safe. User can change the ODATA filter in their Api calls and access another client’s data. This client concept is not relevant in the context of multi-tenancy. You may ignore this.
In summary, to handle multi-tenancy, you just need to be concerned about instances - how underlying users can provide the tokens associated with their instances to the multi-tenant CAP app.
From the API POV, each tenant will use his own authorization header tokens (obtained from the oauth/token of their Doc AI instance) in their API calls. That is how we distinguish tenants.
We implemented a solution to handle multi-tenancy in our own plugin implementation that we were developing before we came across your repo. So there’s 2 main types of scenarios as you have identified:
CAP app only uses 1 doc AI instance belonging to the provider. In this case, the service binding approach works. But this is not multi-tenancy. This just assumes that the CAP app developer just needs 1 instance to be shared across all users for their use case.
Multi-tenant CAP app where users provide their Doc AI instances. In this case, retrieval of credentials via service binding no longer works. End-users’ Doc AI instance subscriptions will never be accessible to us via service binding since it lives in their (subscriber) BTP whereas the CAP app lives in the developer (provider) BTP. Our solution is to use the destination service. Destination service allows a provider CAP app to access end-users’ (subscriber) destinations. A user is required to input their Doc AI service key details as a destination in their BTP using a predefined name (e.g DOC_AI_INSTANCE). The provider CAP app is configured to, in turn, fetch tokens from this destination. This allows the CAP app to fetch the users' tokens and support multi-tenancy.
In our implementation, we incorporated both: It will look for a service binding first. If that doesn’t exist, it falls back to relying on destination service (to look for the user’s Doc AI destination). Even in the first scenario, we convert the bindings to a destination. Our rationale is that the cloud SDK helps to handle the token caching/refresh as we do not want to call the /oauth endpoint to regenerate the token during each request nor do we do not want to handle token caching ourselves in the plugin.