I have the following scenario:
Multiple users (< 100)
User accounts in AD (under different groups)
Every group in AD corresponds to a internal department; each department have at least one supervisor
(One may say) We have cross-supervisioning (there are supervisor roles appliable to group of groups, i.e., there may be one supervisor that actually supervises three or for groups - as existent in AD)
Multiple internal systems, half of them web-based, all of them built over .Net framework
Currently we have most of desktop-based systems authenticating users by folder permissions (deployed in network environment using ClickOnce, each deployment folder permissioned by individual users). That does not work for all desktop systems, though; we have two of them using their own embedded authentication system, as follows:
System A consists basically of different datatables (just shows some data in the screen).
All of the datatables are actually different groupings of the same data; this data refers to specific account.
Every account row contain the columns {number, owner, type, data1, data2, data3, data4 ...}; the different groupings are based on number/owner/type.
All of the data(n) columns are numbers (the sum for each grouping is displayed when grouping is done)
For this specific system, the data columns are attributed to groups. So, users in AD Group1 can see columns data(1-5), Group2 can se columns data (7-9) and so on. However, supervisor for each group can see one extra column for their group (supervisor of Group1 can see data(1-5) and data6 - lets call it "special column" for the group); there are supervisors who can see other groups columns (either including the "special column" or not), there are general supervisors who can see all of the columns and there are also users who can see all of the non-special columns. It's a mess.
In order to solve this problem ClickOnce is not enough; so basically what the dev team did was to embed a particular authorization assembly, which queries a database using the current system as a parameter (it supports other systems) and returning a set of column names as results; these results are then used in another query that retrieves only the specific user columns.
This legacy system is about to be replaced by a newer one; after a lot of consideration (including maintainability - the system architecture is a mess), since it's just about data retrieval and displaying with minimal processing we decided to use (some of) the queries and re-write the data retrieval logic.
On top of that, most of the existing web-based systems are hard-code permissioned (if (sADLogin == "userA") {..}); a few of them only rely on ultra-non-intuitive URLs sent to specific users and fingers crossed. Sad.
We'd like to use a more abstract approach for permission (so we can make every system use the same authentication provider). Using web services/WCF just seems appropriate (also considering that I still have to authenticate desktop-based systems and some spreadsheets, maybe using monikers); however I couldn't find an adequate pattern or architecture model for it. There is one WCF Intranet pattern in Microsoft documentation that solves most of it - except that I can't use my Windows Groups as roles. There is an Internet pattern (http://msdn.microsoft.com/en-us/library/ff650091.aspx), however, that seems to handle the roles problem (that's what I'm going with right now), but since it's my first time dealing with WCF security I'd like to have some expert opinions on this matter.
Any ideas?
Thanks,
For web-based applications, this can be simply solved with single-signon to Active Directory using the built-in ASP.NET Provider Model (see: http://msdn.microsoft.com/en-us/library/aa478948.aspx). You can use Active Directory for authentication, and domain groups for authorization. There are several built-in ways you can limit access to pages (using tags in web.config), access to certain parts of a page (using ), and access to code (using User.IsInRole() or RolePermission attribute) - that all works automatically. For web, this is sort of the standard (internet or intranet).
For non-web-based applications, you can actually still use features of that same provider model. You can also pretty easily look up group membership in Active Directory.
If all you need is to know what groups someone is in, this is probably how you should do it. If instead, that database table you have, has something more complicated (like delegation authorization), then yeah - you may want to throw a WCF service in front of that, and have all your applications use that. However, in the case of ASP.NET, I'd STILL use the provider model, and just write my own RoleProvider, so I could still use all the built-in features of the ASP.NET security. Hope that helps.
Related
I am testing out Identity for my ASP NET CORE MVC application. From what I have read the Identity solution provided is probably the way to go now considering user management and security for logins.
What I have not yet understood is if it is somehow possible to combine the Identity solution with custom groups?
Let me explain..
Lets say I create a webpage for Factories.
This means that several customers that own these Companies that run the factories would like to use this system.
Company A has 3 Factories with 100 workers on each factory.
Company B only has one factory with 20 workers on that factory.
I have read alot of roles and that of sort on how we could seperate these by roles. What they can see, what they can do. But how in the world do I isolate Company A from Company B?
The old fashioned SQL table way would be like to have a Users table, a factory table and a perhaps Customers table. And from there build the logic. But with Identity it does not seem to work in that way?
Any suggestions or links to further reading about this would be appriciated! And even if you guys know that Identity is not the way to go for this kind of solution, then be it. Just so I don't waste any time on something that perhaps is not meant to be.
There's a lot to unravel in your question, but I'll give it a shot. At a high-level it sounds like you're looking for a multi-tenant system.
and pretty much everything you're saying is on point, you probably just need an example to get going. If so, check out Microsoft's example of a multi-tenant system. It might be enough to get you going.
There's several different approaches to a multi-tenant system depending on your business requirements, but here's a few of the more common approaches I've seen used:
Database Isolation - Each Company would be in a separate database. When a user from Company A connected, you would be able to look up which database/schema you should connect too.
Row Level - All companies store data in the same tables, but there's a column called something like "company_id". Every time you query against the table, you filter on company_id based on which user is logged in.
Instance per tenant (AKA Standalone) - On this approach you essentially have multiple web servers running, one per company. They are completely isolated from the web server all the way down to the database. This can be desirable in some situations, but requires a bit more hardware. On the code side, you can handle this fairly effectively with just moving relevant settings into the appsettings file.
Further Reading:
Identity Management In Multitenant Applications
Multi-Tenant Patterns on SQL Databases
Row Level Multi-Tenant Example
The implementation for the different companies changes depending on how you decide to implement the multi-tenant system. So it's hard for me to give you any concrete advice on implementation.
The only word of warning I'd give is think through the relationship between a user and a company. That could change/complicate your implementation fairly quickly.
Can a user be part of Company A and Company B at the same time?
Hope this helps a bit, and best of luck.
How to Retrieve All Active Inventories from All tenants and companies to one custom screen selector in Acumatica??
In ISV Solution I am trying this. How to approach this scenario
Disclaimer: What you are asking appears to venture into a use case that is contrary to a foundational design element of Acumatica ERP - isolation of tenants within a single database. While I have a similar use case in mind in which I need to do the same, use of any of these suggestions should be weighed seriously against your business requirements and operating constraints.
After discussion with some Acumatica Developer MVP's and Acumatica staff, there is no SUPPORTED method for doing this directly with tables already containing a CompanyID field. However, here are a few possible ways to achieve your desired results.
Create alternate SQL Tables / Acumatica DAC's without CompanyID and CompanyMask so that the data can be shared. This will require keeping the supplemental table data in sync.
UNSUPPORTED (This will fail an ISV Certification) - Create a SQL view that excludes CompanyID and CompanyMask and an Acumatica DAC for that view. This will allow visibility to the data, regardless of tenant, without having to create or maintain duplicate data. Again, I was advised strongly against this approach in the same statement of it being possible.
Use an alternative tool to access the data in the SQL database if you have direct access to the database. This tool would have to access the database in a way completely independently of PXData so that all database queries do not automatically receive the "CompanyID = X" in the where clause.
It was mentioned that you might do something with impersonating other users, but I don't have any experience with that. I'm not sure if it would allow cross-tenant data access, but I don't believe it would allow viewing more than 1 tenant even if it does let you view another tenant at all.
My understanding is that the first option is the preferred method to stay within Acumatica in a supported way. The third option could be valid if you already use other analytics tools like Cognos.
Background
What is the best way to apply granular right level restriction in ASP.Net core. I've have already set up authentication and my application issues tokens that that expire after a certain amount of time.
My web app also makes use of roles and rights, where a certain role is can be associated with a set of rights. I've seeded the rights and restricted access to them in that even admin users cannot change, create or deleted any (i.e. read-only). The roles on the other hand are dynamic, though the super-admin and admin are fixed. Any user with a super-admin access role has the power to create new roles and assign rights to that role.
What I am trying to do is to restrict access to all the other controllers in my application based on these rights.
I am considering using Policy-based authorization where each right will be associated with a specific policy (i.e [Authorize(Policy = "delete users")]). Then I would embed all the rights the user has in the token I issue out on login.
I am reluctant to implementing it this way since, though the rights may be hard coded, they may/will increase in time, if I have a very large number of rights then I may be a bit inefficient to be embedding all of them into the token.
Is there a better to achieve this level of security???
If you need, in your own words,
granular right level restriction in ASP.Net core
You need to externalize your authorization rather than build it inside your code. The challenge is that existing frameworks (within .NET, Java...) give you roles and at times claims you can use in your code to determine whether a user should have access to a given function / transaction / data set.
But that forces you to write that code (in C# in your case) every time. And, of course, if your use cases change, you need to rewrite your code. it also forces you to create an data model / information model in your database where you create links between users and roles and maybe one day permissions. And then you end up wondering how to handle segregation-of-duty or delegation or other scenarios which neither your code nor your information model allow for.
An alternative is to externalize your authorization to an externalized authorization manager / API that will process authorization requests for you. This is called ABAC (or attribute-based access control; abac). ABAC gives you:
an architecture (see below)
a policy language (xacml or alfa)
a means to query the authorization engine
either via a Yes/No Permit/Deny request/response flow e.g. "Can Alice view item #123?" "Yes, permit"
or via an open-ended interface e.g. "What can Alice view?" "documents in sales"
The Architecture
In ABAC, you choose to build your apps / APIs / solutions in a way that they only focus on the core business logic of the app e.g. serving medical records.
The app itself will not do any decision making as to who can view which medical records. You delegate the decision making to an external authorization engine known as a Policy Decision Point (PDP).
To delegate the authorization, you use an interceptor called a Policy Enforcement Point (PEP). That interceptor can be within your app code or - better yet - sitting in front of well-known interfaces so that it can intercept your transactions / data flows. For instance, if you have an API e.g. /myservice/records then you would have the PEP sit in front of the API intercepting the flow (JSON, XML...)
The PEP sends requests to the PDP e.g.:
Can Alice view medical record #123?
Can Bob edit the SSN field of medical record #34?
Can Carol print record #123?
The PDP replies with Permit, Deny based on policies that use attributes. And this brings us to the second part: policies.
Attributes & Policies
In ABAC (and XACML), you can write any number of policies you like that use any number of attributes you can think of. Attributes are, simply put, key-value pairs e.g.
role=="manager" (yes, role can be an attribute).
dateOfBirth = 1901/04/01
citizenship = "German" and "Canadian"
Attributes can be about users (as above) or resources or actions or even contextual information e.g. time.
record owner, size, classification, department are all attributes of the resource.
Once you've defined your attributes, you can start defining your policies. Assuming the use case is to control access to medical records, you may have authorization requirements e.g.
Doctors can view the medical records of patients they are assigned to.
Other medical staff can view medical records of patients in their unit.
A patient can view their own medical record
A patient can view the medical record of another patient if they are the legal guardian for that patient.
A doctor A can view another doctor (B)'s patients' medical records if B is on vacation and A is on B's delegate list.
No one can view a medical record if they are outside the hospital.
As you can see, you can write any number of policies and you don't need to touch your apps at all. All you need to do is edit your policies.
It gets better: this approach is not specific to ASP.NET. You can use the same approach and architecture for other languages (Kotlin, Java...), layers (API, data, UI...), and so on.
HTH,
David.
Further Reading
Benefits of ABAC
ABAC on Wikipedia
XACML on Wikipedia
I'm also searching for granular right level restriction in ASP.NET Core. Found Casbin library. It supports RBAC and ABAC and PERM instead of XACML. Simple and fast.
Good afternoon - I have a pretty general question today - I've been tasked with creating a web application to manage some basic information on customers. It's a very simple application, but what I don't know is what to keep in mind to develop the site around supporting multiple users at their own domains or subdomains of our url?
How would I restrict users from logging in to each others portion of the app?
I've seen mention of database scoping in similar questions on Stack Overflow, could anybody elaborate on best practices for an implementation like this?
Are there any new features in MVC3 to support multi-tenancy? I am facing this issue with MVC2 and my eCommerce site where we decided we wanted it white-labeled and customizable for multiple shop owners, and don't know where to begin in implementing these features in an existing application. Any input is appreciated.
edit
To elaborate on multi-tenancy, what I mean - in the context of a store for example, multiple users sign up for their own store at www.mystore.com and are each given a unique subdomain to access their own instance of the store, at user1.mystore.com, user2.mystore.com etc. Each store would have customers with order histories, and those customers would have logins. I would need to restrict customers of user1.mystore.com from logging in at user2.mystore.com without a new account, and likewise prevent user2.mystore.com from accessing user1.mystore.com's customer history.
I implemented a complete MVC multi-tennant app. Here are some links I found handy and some sample apps:
http://msdn.microsoft.com/en-us/library/aa479086.aspx
http://codeofrob.com/archive/2010/02/14/multi-tenancy-in-asp.net-mvc-controller-actions-part-i.aspx
http://www.developer.com/design/article.php/10925_3801931_2/Introduction-to-Multi-Tenant-Architecture.htm
http://msdn.microsoft.com/en-us/library/aa479086.aspx#mlttntda_cc
http://lukesampson.com/post/303245177/subdomains-for-a-single-application-with-asp-net-mvc
http://code.google.com/p/multimvc/
http://www.paulstovell.com/widgets
http://www.agileatwork.com/bolt-on-multi-tenancy-in-asp-net-mvc-with-unity-and-nhibernate/
http://ayende.com/blog/3530/multi-tenancy-approaches-and-applicability
http://weblogs.asp.net/zowens/archive/tags/Multi-tenancy/default.aspx
http://cloudsamurai.codeplex.com/
http://cloudninja.codeplex.com/
http://msdn.microsoft.com/en-us/library/hh534484.aspx
http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx
http://blog.tonywilliams.me.uk/asp-net-mvc-2-routing-subdomains-to-areas
Even starting from scratch, you are in for a world of hurt. The MVC framework does very little to help you address the issues.
Most likely you are about to spend a fair amount of time restructuring your database.
The first step is that you are going to create a table to house your "Tenant" list. Then you need to add this TenantId to just about every table in your system to make sure no one steps on each other. You can skip any tables that are global in nature. One example might be a list of Status Codes.
However, everything from users to the data they have etc will have to have this ID. Also, modify all of your indexes to take tenantid into account.
Once you have that, you'll need to modify all of your queries to take the tenantid into account.
One column of the tenants table should be the portal url. Like customername.oursite.com or whatever. This way you could point multiple urls to the exact same code. When the site needs to use the current tenantid just look it up based on the URL the passed in.
If I was doing this, I'd plan to spend about 1 to 2 hours per table in the database to make it "multi-tenant". Obviously some tables (and their queries) will go faster; others will take longer.
Incidentally, this doesn't cover things like customizing the UI (look / feel) per tenant or anything of that nature. If you need to do this then you'll have to either create a directory on the server for each tenant to hold their style sheets or load it directly from the DB (which has it's own issues with regards to caching).
Typically, you design for this at the beginning of the project. Refitting an already (or almost) complete project is a PITA.
Finally, test, test, test and do more testing. You will have to make sure that every single query pulls only the data it absolutely needs to.
There has been some talk of multi-tenancy support in Sharp Architecture (based on MVC 3) found here: http://www.yellowfeather.co.uk/2011/02/multi-tenancy-on-sharp-architecture-revisited/
Not sure if that really helps you with your existing application, porting over would be a bit of a job.
I have got a requirement from a client. They need three blogging web application for three different regions. Each application have its own data and posts. Probably they want to share user information between these applications. User interface of these application will be same except css level changes (color, font and styles) and little bit layout changes in home page for each blog. That brought lot of questions to my mind.
Three seperate site approah
1. Is that good to develop three different websites for each region and deploy them in three subdomains?
2. Am I going to use same database or individual database for each region?
3. If there are three web sites, how am I going to overcome caching, session sharing and user signon(single sign-on), multiple deployment, duplication of code issue?
Single Site Approach
1. Create a single site, seperate the regions like sitename/regionname?
2. If it is single site, how the performance and scalability is going to be?
3. Just use singe database, that would be shared between three regions. Is that good approach?
There could be many more possiblities. Now I need your guidance that what are all other unknown problems would occur and how would I approach this problem one by one and come to a conclusion that which is best?
We may implement this solution in C#.
EDIT: The sites will be in English language
You have a lot of choices to make here, so you need to get some good information from the client.
You mention that there will be layout changes between the sites. This part right here says that you might be better off with three different sites for the user interface. It's probably a good assumption that they are going to want to change the UI's to each site on an individualized basis. Building all of that into a single engine is difficult.
All three could share a single database, you just need to make sure that each post, config piece, etc all have a SiteId associated with them. Also you'll need to make sure that every query you write uses that SiteId value. This situation is called a Multi Tenant architecture.
Caching will be handled just like caching for a single site.
After writing all of this, it occurs to me that you might be better served by simply taking an existing product like WordPress or something similar and creating templates for it for your purposes.
I've had a similar design-issue recently, so let me share with you my approach (however wrong or right you think it is!). I went with a single site, single database coupled with host headers.
The first thing I did was to create a domain table. It kind of looked like this:
_domains:
_id INT IDENTITY NOT NULL
_domain_name NVARCHAR(255) NOT NULL
_id_category_root INT NOT NULL (foreign key to _categories::_id)
This allowed me to specify a top-level domain for content categories. Content categories belonged to the domains.
_categories:
_id INT IDENTITY NOT NULL
_category_name NVARCHAR(64) NOT NULL
_id_parent INT NULL (foreign key to _categories::_id)
_theme_root NVARCHAR(64) NOT NULL
The _theme_root field specified the default theme folder within the root. This allows each category to (optionally) have a different css and, if it so desires, a different master page. This allows content categories to look completely different (CSS, images and layout) or even just the CSS using the default master page.
And, thusly, content belonged to a category:
_id INT IDENTITY NOT NULL
_id_category INT NOT NULL (foreign key to _categories::_id)
_content_title
-- other fields
I abstracted it this way because you can have multiple domains for the same category level:
enGB.mysite.com -> category 1
www.enGB.mysite.com -> category 1
frFR.mysite.com -> category 2
etc
In my code, I look at the host header and pick the category appropriately, serving content and other tables that branch of that made category table. If the host header does not match, I fall back on a default (The english site).
EDIT: Added notes on theming.
It is not good to develop 3 different web sites. The maintenance will quickly become a nightmare and the code will be very cumbersome.
Break it down into Services (SOA) Service Oriented Architecture. This is language agnostic. So if you use C#, PHP, Java, or Python the general idea is the same.
1.) Create a User Service to authenticate users.
2.) Create a Blog Service to handle storing, retrieving, and editing blogs.
3.) Create a single site to communicate with the services and use localization.
Using a service has the added benefit of being able to change the database design, DBMS, etc... without having to change the core application.
In the User Service store some kind of local identifier so that your single site can change based on localization rules. All the major languages have localization settings to do most of the work for you such as date format, currency, etc...
Note: It is best to get the Region name during the User Registration - not the Sign-In.
A design like the one described above makes the code much easier to maintain - compared to 3 separate sites.
It should be a single site, and it should be a single database. Scalability is a whole other issue of it's own. What kind of traffic are you expecting?
Anyways, take a look at nvidia.com, this site is setup for different regions across the world. It's still all the same website in most cases. Some parts may be hosted in different countries, but they are probably connecting to the same database or set of synced databases.
The other most important thing, is do you want all the sites to be exactly the same but just in a different language? If so this will just be simple text replacement, or your database would just be setup to where your application can easily switch out content from different languages.
Your project certainly needs a lot of time in the planning stages. You need to make sure you know exactly what your client needs because that can often be different from what they want. Plan some options for your client and present the pros and cons of these options. Then let them decide.
There may be a single site... and with that single site u can also use it with different url ...
My Mean to say website is a single and all users uses this site with different url so they fell that they have their own site .. but actually there is only one site.....with one database ....
its possible .. and its a best way .....