We are using IdentityServer4 for managing user identities and logins. In the business domain there are companies that are divided into organizations. Companies are distinguished by unique identifiers, while organization identifiers might clash between different companies, which makes only the combination of company ID and organization ID unique.
A normal user typically has access only to some organizations in one company, but there is a need for superusers that have access to organizations in multiple companies. The claims in IdentityServer were originally designed only for one company, so it has not really been thought how multiple companies should fit into this.
For a normal user it would totally fine that he would have one company claim and one or many organization claims. But this does not really work for superusers that need to access many organizations in many companies.
How should this kind of combination identifier be modelled? The only way we can come up with is combining the company ID and organization ID into one claim, but that means that we must split the claim everywhere we need to have the identifiers separated, which feels rather cumbersome and error prone. So is there a better or more proper way, or is this perhaps a problem that should be fixed outside of Identity server?
Related
I work on an application that stores data from multiple Twilio accounts in a single backend DB. Part of the stored data is SIDs for various resources within an account - tasks, channels, services etc.
When designing my schema, can I consider all these various types of SIDs to be unique across all accounts, or would I need to consider them only to be unique within the scope of their owning account, and specify my constraints, relationships & queries accordingly?
Yes, they are globally unique :)
A String Identifier (SID) is a unique key that is used to identify specific resources.
source
I am planning to use Identity Server 4 and Asp.net Core Identity together. My website that will be talking to Identity Server 4/Asp.net Core Identity will be expecting that a company name comes back with each user.
Should I create a new customer table called Company and in the Asp User table add a column linking them together.
Or should this be a claim?
I know when I authenticated my user and they are sent back to my main site, I will have a company table and they will be linked but just not sure for the purposes of identifying them.
I feel like it should be a claim but I want to double check since I am new to all this.
In terms of using IdentityServer, technically everything is a claim. The "user" object IdentityServer returns will have all the properties mapped as claims. In that sense, it really doesn't matter which approach you go with.
However, it's generally better to keep data on your user table, if it makes sense to. Something like a foreign key relationship is especially valuable to exist at a database level, as there's more value to that than simply getting a company name.
Storing data as claims is most useful when that data is transient or not applicable to every user. Typical examples include things like third-party access tokens, such as from Facebook. Storing that on the database-level would inevitably result in denormalization of your database table, so it makes more sense to use a claim.
I am implementing an authentication system into an existing database system. Currently, the database has a "Person" table that includes things like: First Name, Last Name, Date of Birth, Email (username), etc. This is the primary table for a user.
I need to add the following fields for authentication: Password, IsLocked, LockDate, LastLoginDate.
Would you suggest putting these fields in the Person table or would you put them in a new Authentication table? My original plan was for "Person" to simply contain data about that person, not necessarily about authentication.
The other approach could be to store the password along with the email in Person, but then place the authentication data in a separate table. This way, the username and password would be in the same place, but the meta data would be in its own entity.
Anyone have any thoughts?
Thanks for the help!
Keep them separate so that users can query the system for information about a Person without necessarily having access to their account credentials.
This also has a nice side-effect where not all Person entities may have accounts.
Keep the account information separate. Your current business requirement may be for each person to have only one account, but it could come up in the future that a person needs to have multiple accounts, or even that you need an account that is shared by multiple people. Having a separate table for authentication means that such future changes will have a smaller impact on your code.
Also, from the perspective of protecting authentication information, the fewer people/processes that can access the account data the better off you'll be. It's much easier to implement table-level access than column-level access.
I don't think it makes much sense to create a seperate table for Authentication data. Authentication can't exist independently of the Person, as far as I can tell - and there doesn't seem to be a way one Person could reasonably be associated with two Authentications (or vice versa).
In other words: There's a 1:1 relationship between Person and Authentication, so why split it off?
In our SaaS system we're dividing users into separate "pools" according to the customer that originally "owns" the user. We're using "email addresses plus ID of owning organisation" to identify users, rather than just email addresses - so duplicate email addresses can exist between customers (don't ask). Users arrive at the site on various subdomains, and we use these subdomains to identify the "user pool" we're authenticating the user against.
My question: is there any established name for this pattern or something similar?
Cheers!
In database terminology, when uniquely identifying a row using more than one column, this is called a composite primary key (aka compound key).
The scenario you describe is used commonly when a single database is used for multiple customers - one form of multitenancy.
"home-realm-discovery" is a common term for identifying what tenant a user belongs to in a multi-tenant SaaS application. It's most often talked about in the context of Federated Identity but applies in your case too. Using a sub-domain like you're doing is a common practice.
I am not aware of any specific name for this scenario, but in general, this would fall under the phrase "multi-tenant" / "multi-tenancy". Many SaaS implementations do customer (or rather tenant) based branding already on the login screen, which would mean that they'd have to identify the user based on the URL / subdomain, or at least in some way other than the email address used.
Routing to different servers based on the subdomain is also a common way to achieve tiered service levels for SaaS implementations.
I'm not sure I've answered the question, but I hope the general info helps!
I have a full multi-tenant database with TenantID's on all the tenanted databases. This all works well, except now we have a requirement to allow the tenanted databases to "link to" shared data. So, for example, the users can create their own "Bank" records and link accounts to them, but they could ALSO link accounts to "global" Bank records that are shared across all tenants.
I need an elegant solution which keeps referential integrity
The ways I have come up with so far:
Copy: all shared data is copied to each tenant, perhaps with a "System" flag. Changes to shared data involve huge updates across all tenants. Probably the simplest solution, but I don't like the data duplication
Special ID's: all links to shared data use special ID's (e.g. negative ID numbers). These indicate that the TenantID is not to be used in the relation. You can't use an FK to enforce this properly, and certainly cannot reuse ID's within tenants if you have ANY FK. Only triggers could be used for integrity.
Separate ID's: all tables which can link to shared data have TWO FK's; one uses the TenantID and links to local data, the other does not use TenantID and links to shared data. A constraint indicates that one or the other is to be used, not both. This is probably the most "pure" approach, but it just seems...ugly, but maybe not as ugly as the others.
So, my question is in two parts:
Are there any options I haven't considered?
Has anyone had experience with these options and has any feedback on advantages/disadvantages?
A colleague gave me an insight that worked well. Instead of thinking about the tenant access as per-tenant think about it as group access. A tenant can belong to multiple groups, including it's own specified group. Data then belongs to a group, possibly the Tenant's specific group, or maybe a more general one.
So, "My Bank" would belong to the Tenant's group, "Local Bank" would belong to a regional grouping which the tenant has access to, and "Global Bank" would belong to the "Everyone" group.
This keeps integrity, FK's and also adds in the possibility of having hierarchies of tenants, not something I need at all in my scenario, but a nice little possibility.
At Citus, we're building a multi-tenant database using PostgreSQL. For shared information, we keep it in what we call "reference" tables, which are indeed copied across all the nodes. However, we keep this in-sync and consistent using 2PC, and can also create FK relationships between reference and non-reference data.
You can find more information here.