WCF -> ILM -> Web Services -> SQL Server - c#

My employer currently has most of its access to the database through C# sqlDataAdapters and sqlCommands on a WebServices server or components in applications. These are mostly Windows Forms apps that are ran on intranet and internet depending on their functionality.
I have been researching WCF quite a bit and I feel it would be a good fit for our us. Also my manager has a copy of ILM(MS Identity Lifecycle Management Server) that he would like to use to to provide SSO support for authentication and authorization for all of our applications.
Our applications request data from the database and it is returned in dataTables primarily. I know collections are better, it is just the established practice used. So I am trying to find a solution that will be secure, authenticate through ILM and return data to the client in a dataset(at first, migrate to collections later) from webServices server.
My question is will this work or will it be too slow?
Client calls routine on WCF requesting data
WCF server checks with ILM to see if its ok to do so
WCF calls webServices server to get the data
Dataset or collection is passed back to the client.
If this is feasible how would I go about connecting to ILM for authentication. Is there a slick way to do it in the Web.Config file or would I have to do it on the message level on my own?
Thanks in advance.

I am familiar with ILM. It's not an authentication service. ILM means Identity Lifecule Manager and it's a pretty good description of what it can do. It can provision new users, deprovision old users and allows you to copy identity data between identity stores. It also provides a password synchronisation service. You still use Active Directory or AD LDS (ex-ADAM) or some other directory for AuthN and AuthZ.
Whilst ILM stores a whole load of data about your users, you are strongly discouraged from accessing that data directly.
[EDIT]
ILM does not provide LDAP services. Think of it as a manager: it doesn't do any work itself, it just rearranages things periodically. As your manager moves round data in the form of emails, it moves round data in the form of account details.
ILM is a tool for managing identities across directories and databases. It doesn't make sense to consider ILM in the context of a single store, SQL, AD or any other - its job is to marshall data between stores. It wouldn't have anything to do if there was only a single store.
Here's a typical scenario: you create a SQL table called People containing columns for firstName, lastName, jobTitle, department, a uniqueID, startDate and endDate. ILM is hooked into this table. It does a daily import and there is a new row. ILM uses the data in this row to create a userID in AD, another in Domino and another in a different SQL Database. It uses the jobTitle and department fields to assign group membership in AD, mailing lists in Domino and permissions in SQL.
The user starts and works for a few weeks and then resigns. You set the endDate in the table and ILM notices this change on its next import. It updates the AD account to expire on that date and stores a delayed action to delete it after 90 days. 90 days later, it deletes the account. Likewise with the other accounts.
You can use your personnel system instead of the SQL table but (a) it's not usually in the right format or maintained timely enough and (b) they're often itchy about letting you have access to their data.

I'm not hugely familiar with ILM, but I'm guessing that it is pretty granular to specific data queries. With WCF you can hook your own identity-provider by implementing IAuthorizationPolicy (like so) and providing your own "principal". I suspect it would be pretty easy to write a principal that works against ILM, but this would presumably be for pretty broad checks - "do I have CustomerAudit access", rather than "can I access CustomerAudit for customers in the north-east".
A nice thing about using a principal is that you can also use [PrincipalPermission] checks on methods, so you don't need to add broad security checks to your code (the CLR enforces [PrincipalPermission] directly).

Related

Mentally trying to sort out password<->Db scheme - how is this usually done?

Okay so my problem is this:
Firstly, user access to the SQL database is controlled by windows authentication, but the app is doing a second check to set user privilege levels within the app.
When I create a new user in my WinForm client App it asks for a password which I then hash with a random salt, these data are then stored in the users table of my SQL database thusly:
users
username, firstName, lastName, pHash, pSalt, accessLevel etc.
When that user, in a later session, tries to log in he gives his password. I pull the salt out of the database and hash the given password.
Now this is my problem: I'm obviously insecure if I pull the hash from the database and compare it with the computed hash locally.
My App maintains a 'user' object that sets a flag for 'authenticated' and has a property that is set based on the 'accessLevel' column in the users table in the database.
There must be a usual way of doing this - or is my answer, you need to be using the SQL Server access facilities to do this not trying to re-invent it in managed code?
You're right in that you can't trust the client to do authentication or authorization. That must be done on the server side.
In your case when you are accessing the SQL server directly from the client you would have to use SQL servers built in functionality for protecting different database objects.
That's usually quite hard to do in a good way though, so a more normal architecture is to create a separate server application such as a WCF service. The clients access the WCF service, which does the authentication and then is in charge of all database operations.

ASP.NET Multi tenant application with tenant specific roles

We have a multi-tenant ASP.NET application. So far tenants have been isolated from each other, however now we have Agencies that manage multiple tenants and want to be able to manage all their tenants with a single user account. I'm trying to figure out the best way to accomplish that, hopefully without much change to the existing technologies that we are using.
Relevant technical details:
AspNetSqlMembershipProvider for both membership and roles
C# 4.0 (soon to be 4.5)
Forms Authentication
Both aspx and MVC (v3) pages
Assume 100 or more tenants, so any solution needs to support that
I believe the requirements are very similar to the security model for SQL Server. We have one set of logins which represent all the users that can login to the system. Users should be able to be given roles to one or more databases (tenants). Example: User Bob has admin role in company A, but only user role in company B. We also have a "sysadmin" role for my company's employees which allow us access to any tenant as well as specialized administrative privileges such as create/delete tenants, etc.
I've done a lot of research into various libraries, frameworks, etc, and I haven't found any convincing evidence that some other library or framework will be better than what we currently have. So I'm currently thinking of just figuring out how to make Sql Membership provider do what I want, unless someone can point me in a better direction. I'm also not sure I know the best terms to search for in this.
I've got 2 options I'm considering:
Add only a handful of roles to the membership provider and handle all the questions of "does the current user have this role in this tenant" outside of membership provider. Membership provider would be used to handle basic access to the system.
Add tenant specific roles to membership provider. We would have (# of roles) x (# of tenants) total roles in the system. Each new tenant would add another set of roles to the system, e.g. "Tenant A:Admin", "Tenant A:User", etc. Would need some additional tables to manage the relations as well as probably some custom code to ensure that access is requesting the correct tenant-specific role from the membership provider.
Are either of these options good? Or should I be looking elsewhere for support for this?
I don't think you are going to be able to shoehorn multitenancy into any out of the box role provider, so you might as well keep using SqlMembershipProvider (and SqlRoleProvider). Even the newest Microsoft.AspNet.Identity still assumes a vanilla many-to-many between users and roles. What you really need is to add a 3rd column to the primary key of that many-to-many table, which will id your tenant, i.e.:
user: 6
role: 4
tenant: 17
user: 6
role: 9
tenant: 18 (and so on)
...with this, you are able to have users with different privileges for different tenancies, all using the same set of role names.
If you went with option #2, then your [Authorize] attributes would explode. Imagine this:
[Authorize(Roles = "TenantA:Admin", "TenantB:Admin", ...)]
public ActionResult Post(int id, SomeViewModel model) {}
... all of those attributes would have to be written at compile time unless you went with a custom AuthorizeAttribute, which you could do. But even then you are left creating a new set of roles each time you add a tenant to the system, which should not be necessary.
I work on a big multi-tenancy application. We came to the conclusion that it was easier to maintain separate databases per tenant, and have the web application automatically switch database contexts, rather than try and use an over-complicated database schema to model different tenants.
The benefits
Tenant data is compartmentalized by default into different databases
Tenant data can be exported as a database dump for client MI
Database design is vastly simplified
The drawbacks
You have to manage multiple databases - operations challenge
You have to develop database switching code
Implementation using multiple databases
We used a configuration database that has client settings based on an account code. That account code can come from a login screen or you can map subdomain to client code.
When the app starts you load all tenants into cache (containing connection strings)
On every request you have to determine the client and then switch the db context
I have also developed a multi-tenant application that uses a single database. You quite quickly have problems making sure that you don't cross tenant data. Every query needs to include a tenant id filter. The database queries are therefore always slower as a result, although you can index everything you can to try and improve the situation.
With regards to the Membership question, you can install the membership schema into each tenant database.
What doesn't work
The ideal alternative would be to dynamically switch the ApplicationName, but although it seems to work, ApplicationName is not thread safe, therefore this would not be reliable:
Because a single default membership provider instance is used for all
of the requests served by an HttpApplication object, you can have
multiple requests executing concurrently and attempting to set the
ApplicationName property value. The ApplicationName property is not
thread safe for multiple writes, and changing the ApplicationName
property value can result in unexpected behavior for multiple users of
an application. We recommend that you avoid writing code that allows
users to set the ApplicationName property, unless you must. An example
of an application where setting the ApplicationName property may be
required is an administrative application that manages membership data
for multiple applications. Such an application should be a single-user
application and not a Web application.
Alternative: MembershipReboot
Multi-tenancy is hard in .Net. An open source alternative to using the built in Membership is to use MembershipReboot, written by Brock Allen. It has some excellent features including multi-tenant support out-of-the-box:
single- or multi-tenant account management
flexible account storage design (relational/SQL or object/NoSql), samples using both EF and RavenDB
claims-aware user identities
support for account registration, email verification, password reset, etc.
account lockout for multiple failed login attempts (password guessing)
extensible templating for email notifications
customizable username, password and email validation
notification system for account activity and updates (e.g. for auditing)
account linking with external identity providers (enterprise or social)
supports certificate based authentication
proper password storage (via PBKDF2)
configurable iterations
defaults to OWASP recommendations for iterations (e.g. 64K in year 2012)
two factor authentication support via mobile phone SMS messages or client certificates
The most common use case will be to integrate this into an ASP.NET or
ASP.NET MVC application, though the library can also be used over a
network as a service.
Alternative: ServiceStack REST
Another alternative if you are building modern web applications that heavily use JavaScript MVC frameworks such as AngularJS, EmberJS or BackboneJS is to use ServiceStack REST services. ServiceStack has a long list of Authentication features, and from my experience of SS, I find it has an extremely well thought out API model.

Shared Application

I am creating an application to be accessed by multiple clients, but
each customer will have a different database, only access the
same application in IIS, I'm using DDD, C # and MvC3 and Entity Framework 4.1 CF. Does anyone have any example or an idea of how best to configure the connection string
specific to each client?
First, you need to identify whether it's a database per client (machine?), user identity authenticating, or some other identifier. For example, if it's per account, then two machines may be able to authenticate as that account and get the same storage.
Once you have that identifier, you'll need a master table somewhere with a map of account to database connection string. You'll probably also want to cache that table in memory to avoid two db roundtrips on every request.
That global configuration information is typically stored in a database. You could go as simple as a file but that would cause problems if you ever wanted to scale out your front end servers, so common storage is best.

How do you secure your sql servers accessed by C# applications

Simple and contrived example:
C# desktop application talks to SQL Server database. All orders exist in Orders table.
Application views, creates and amends orders. In this example a user can only amend their own orders.
Concerns:
Storage of connection string if using dedicated sql credentials.
Even if user credentials are used, application security could be bypassed by connecting directly through Excel or Access.
Solutions:
Provide access to SQL through web service/middleware only. Good, but not necessarily viable in this case.
Encrypt connection string in application somewhere. Not hugely secure, security through obscurity.
Secure database by granting access to specific stored procedures, views, etc and no access to actual tables. SP's and views take into account the user's rights/credentials. Pretty awful. Ok for simple examples (Select where user , becomes complicated once you introduce users in different groups, manager relationships, etc.
Alternatives:
How would you approach this?
Thanks
Even if user credentials are used, application security could be
bypassed by connecting directly through Excel or Access
what do you mean? you should not allow users to connect to SQL Server directly or with Excel or Access. They should NOT know the sa or other password.
After this, surely you could encrypt some sections of your app,config so that nobody can see its content.
I would really have the logic that a user can only modify his/her own Orders at the application level. Could be done also in the stored procedures I guess but it depends and more details should be known about this to suggest the best or most appropriate approach.
Use windows authentication instead of sql authentication.
To allow users to see only their data you can create view and filter data based on the currently logged in user by using SYSTEM_USER to get the data for the current user only and deny select permission on the table itself.
You can't do row level security in SQL Server (well you can, but it's not straightforward). So your only choice to be totally secure is to go through a data-layer which controls access. You can store your credentials encrypted, but that's not totally secure, as you say. It depends what you need.
Well in our application we handle we store the connection string encrypted in a file.
So the user has no direct access to this file.
We also use sql connection only to our database and grant the user for this only.
If you use Windows Credentials to access it and want to prevent any manipulation you can disallow write access to table.
For reading the data you can build queries or access the tables.
For writing/adding/manipulating data you can create stored procedures. One of the parameter is the username. Inside the procedure you build your bussiness logic, impersonate to a user that has write access to finally write/update the data.
There you have your "layer" inside the SQL server.
But I wouldnt suggest to go this way :) It is possible but to many business logic inside the database imho. So the safest way is to find a good encryption class in your language, use sql auth only and store those data inside your code.

Saas with database per client - single point for entry for services. Performance overhead?

I'm building SaaS application where back end will be SQL Server and WCF Services.
Here is where I'm little worrying.. I'm planning to have separate database per customer (thats decided) and will authenticate users against their database. Thats decided as well.
There will be central database which will have customers info like what database is their and what endpoints to use.
Ideally, I want something like this:
a. Client hits main page ASP.NET or
Silverlight or open client app on
PC/mobile device/etc
b. Types in Customer ID, user name
and password
c. Call being made to main URL
d. I will pull endpoint and DB
information for this Customer ID. I
do want WCF endpoint info also be
configurable for future
expansions/upgrades
e. Need somehow pass information
about endpoint/database to user.
Multiple customers can share same WCF
endpoint.
f. Call endpoint from client and
login to specific database.
This way I can see how performance will be OK since I won't have to go through my "system" proxy on each call. Client will KNOW what endpoint and which database it deals with.
But I'm not sure how to implement this securely. Because database information in step "e" will flow back to customer. Technically, even if it's cracked on customer - still no access to DB itself from outside. But not nice..
What your thoughts are? Or should each call be made with companyID token and then main central service will route those calls? But that's like single point of failure. I'd rather see main server to work on on login.
We've done WCF sites connecting to multiple databases handling 1000 concurrent requests, there are fiddly bits in the WCF config that you need to tweak, but it should work fine.
I don't see why database information needs to 'flow' back to the user.
All of that could happily live server side. Then all decisions about what database to connect to can be made based on the user credentials.
If you want multiple endpoints to handle load, then you redirect to a relevant (or random) end-point after login. Then store the relevant routing/mapping data on the relevant endpoint (or all of them if you're using random).
All you need from them is their credentials to decide what database to use.
Tip: As with all performance issues: measure, measure, measure. You need to know if there is any benefit with multiple end-points under your expected load; so build a load test. Then you can see where the performance hit is. Over engineering before measuring sometimes works, but always wastes time.

Categories