Is this a good way a web service interacts with a multi-tenant database? - database

I am trying to make my web service identify specific client data to return as JSON. I am not sure this is the right way, and I'd love some advice.
The way it currently works is:
Database table for users with an appropriate company_id where they belong.
Upon logging in, an authentication service issues JWT tokens with the company_id in the token payload.
The clients sends HTTP requests with the token, after which a service verifies the validity of the token, and then the specific route returns data with SQL doing a WHERE company_id = company_id_in_token.
The red flags I'm running into are:
Having user data in the token payload. SSL will negate this, but I am worried about bad design.
Having to include a company_id column in every single table for the filtering.
Please, I kindly ask you to rip me a new one.

If you refer to the OpenID specification, it states that you send the id_token, but signs it for later verification. Also, if the upn or sub claim is available, you can infer the tenant from this data. However, in case if the userin question works on behalf of another tenant, special headers are required to infer the tenant, example contextual tenant can be a header that contains the tenant under context.
In case of having tenant id column, it is a good practice to have a tenant id column in the core business objects tables. There will be no tenant id column in a table that is dependent on the core business object, because it by itself doesn't convey any significance.
HTH

Related

Inviting a consumer to Azure AD B2C with custom in-app attributes

Inviting a consumer user to Azure AD B2C has been covered by other Stack Overflow questions & answers, and AFAIK requires the use of custom policies that entail a signed JWT being created and used during invite redemption.
What I'm trying to figure out: In our application, we have differently permissioned user groups and different organisations managed by internal RBAC logic. We identify & authorize users based on their oid claim in the access token that's returned to msal-react/msal-browser and used to authenticate against our backend's API.
In Microsoft Graph, a user can be invited and the API will respond with the created user's oid. However, this is the wrong type of user and not appropriate for B2C scenarios.
With the custom policy route not creating the user object in AAD B2C at the time of invite, and therefore without knowing the user's oid at the time of inviting them to the application, what might be the best way to configure their in-app profile and have them identifiable to the application itself upon first login?
My thought at the moment is to have the application store the emails of users that are invited who have not yet redeemed/signed-in. We can configure the emails claim to be returned upon login, which is checked against the invited emails store when an oid claim is returned that isn't present in the database. This can then trigger a function to update the user's internal id with the oid in their first login's claim.
If this is inadvisable or if there's a better way, I'd be very grateful to hear it.
It would work, or just pre create the user up front via MS Graph API. Then you have an email and objectId available.
You could also put an extension attribute on the account indicating whether the user has redeemed their invite. That would allow you to monitor who has redeemed, and also be a way to provide a different experience depending on if the user has redeemed or not redeemed the link.

Clarification on Identityserver 4 protecting API scopes with ApiResources

I don't really understand the protecting API using APIResource and APIScopes
I have an angular client application which is calling a .Net APIs lets say API1, Api2 , How can I define the values in APIResource.
I am going through the Identity server4 (version 4.0.0) database table after migration. I found the tables as below
ApiResources
ApiResourceScopes
ApiResourceClaims
ApiResourceProperties
ApiResourceSecrets
ApiScopes
ApiScopeClaims
ApiScopeProperties
My understanding was either we can use 1-5 tables for API setups or we can use 6-8 tables. I tried with tables 1-5. Added values in ApiResources ,ApiResourceScopes & ApiResourceClaims but getting below error
[18:03:53 Debug] IdentityServer4.EntityFramework.Stores.ResourceStore
Found ["TestAPI.Read"] scopes in database
Values in Tables
what is the use of ApiResourceClaims table? is this returning user claims with access token?
How do I access this scope from the client?
Is there any other tables, do I need to add data?
First I recommend that you read my answer here
what is the use of ApiResourceClaims table? is this returning user claims with access token?
It contains a list of user claims that will be included in the access token. Meaning, the names of the claims that it will then take from the user database.
How do I access this scope from the client?
You need to tie an ApiScope. You ask for a ApiScope that then will include one or more ApiResources.
ApiResources represents the individual API's in your system. So, you have one ApiResource per API. You use the ApiResource name and secret to let individual API authenticate against IdentityServer and login to for example get details about the access token (Token introspection)
I think this picture I have below shows the relations between the various parts:
The client asks for a ApiSCope and that will then create an access token that will give access to one or multiple ApiResources. Each ApiResource might using the userclaims ask for additional user information that you want to have present in the Access token. Perhaps for the authorization step in the API. To determine if the user is really allowed in or not.
To complement this answer, I write a blog post that goes into more detail about this topic:
IdentityServer – IdentityResource vs. ApiResource vs. ApiScope

What is the best approach to design database with external users, groups and permissions?

We are removing User, User Group and Permission models from our backend in favor of Auth0.
Our first idea was to just delete User, Group and Permission tables from DB and replace related foreign keys with varchar field. In this field we would then enter IDs that we get from Auth0 in JWT (pointing to something not present in our DB).
Is this good approach? I somehow feel that there must be more "relational" way of doing this.
Generally OAuth will not do all of the permission checks for you. Instead it gives you general mechanisms to sign the user in and issue + validate tokens.
In most real world architectures you also need to manage a second level of authorization in your back end - using domain specific user data for roles, permissions etc.
A couple of write ups of mine may help:
User Data Management
API Authorization
Auth0 Community Manager Dan here,
In this scenario you may be able to leverage the RBAC to replace your existing users/groups/permissions setup.
You would register a user's roles and the associated permissions of each role in the Auth0 dashboard or programmatically via the management API. Then you can setup a rule to add user roles to the token.
To connect this user to your existing user data store you can store the Auth0 id, similarly to how you have described.
This allows you to lookup the user when the token is received, and to associate any permissions or roles the user has. You can make roles API-specific by adding a prefix to the role, or have roles be general depending on your needs.

IdentityServer4 Add Tenant Claim after Authentication

I have a multi-tenant scenario in which one email can be associated with multiple tenants.
I've thus configured a custom AccountChooserResponseGenerator that inherits from the built-in AuthorizeInteractionResponseGenerator class.
After the user authenticates, the UI correctly diverts the user to an Account Chooser view, which lists the tenants the email address is associated with. The idea being that the user must now select the Tenant he/she wants to log in to, and then get redirected to that Tenant's URI.
My problem though is that I can't figure out how, after selecting a Tenant, I can add that Tenant Id as a Claim to the token that gets passed to the app from IdentityServer (multiple tenants could share the same URL so I need something in the token to know which Tenant has context).
So in the AccountChooserController.TenantSelected(long tenantId) method, I'm expecting to be able to add this tenantId to the User Claims, but it does not seem like this is supported.
Please advise if this is possible, and how?
Put the tenant information into the cookie when calling SignInAsync - you can then retrieve it from your profile service.

Are there security-risks in managing multi-tenancy based on Claims using IdentityServer4?

For some time i've been busy building an identity-server, some complicated structures came up as i'm trying to implemented multi-tenancy.
I would like to know if there are any security-risks regarding the approach im planning to take. Maybe others are struggling as well and could use an example-structure. The following case is present:
One identityserver
Multiple tenants with seperate domains
Multiple user-accounts possible for a user per tenant (Student & Teacher)
Registered with multiple tenants under differentusernames/email-addresses
SSO required for all tenants at once
The structure i had in mind:
A user is logged in at the Identityserver. The available clients (applications/tenants) for which de id-server can provide authentication are presented like a hub. One is selected (Company3 for example) and the option to link an account for this specific tenant is available.
The user provides an email (Student#company3.com) and a verification is sent to the user. The identityserver-database holds data regarding a one-to-many relationship between a user and the registered client, and a one-to-many between these registrations and the verified email-addresses.
When logging into the identityserver, the token would hold the data for the tenants and the verified accounts. This token is returned and the current client verifies the token using the key from the discovery-endpoint.
An example of the custom claims would be:
{
"company3":[ "student#company3.com", "teacher#company3.com"]
"company1":[ "student#company1.com", "teacher#company1.com"]
}
Company3 would have secure confirmation that the current user has access to 2 accounts. Company1 would have the same information out the token which makes SSO between the different tenants possible.
As i see it, there wouldnt be any security risks. But, im not very experienced with Identity-servers and authentication yet. I would love some feedback regarding possible security risks.
Cheers

Resources