Which authentication and authorization schemes are you using - and why? - asp.net

We're beginning to design a whole bunch of new services to create (WCF, ADO.NET Data Services, possibly in the cloud at some point) and one question that pops up is what authentication and authorization scheme to use - there are quite a few!
We basically need to be able to identify users (actual people, and "virtual" application/service users) on a wide variety of protocols - HTTP, HTTPS, TCP - and we need to assign them at least a bunch of roles / permission to see certain data and/or do certain operations.
We definitely can't use Windows group membership alone - we have plenty of external consumers of our services and we don't want to have to set up a domain account in our internal domain for everyone of them.
So there's mainly three options, I think:
Using the ASP.NET membership system - create users and assign roles there
Use AzMan (Authorization manager) which seems to be a more granular, more mature, more elaborate system (with users, tasks, groups - three levels, not just user + roles)
Roll our own
First of all - which of these three would you recommend? Any why?
Secondly - are there more options that I'm missing?
Thanks for any hints, pointers, opinions!
Marc
PS: seeing the answers so far, I'm amazed at the amount of folks voting for option #3. I would have thought that MS would be able to design something reusable that could handle all of these requirements....

Actually, the answer is probably a combination of 1 and 3.
You can take advantage of a lot of the tools and features that the framework provides for you by writing a membership, role or profile provider if the default options don't quite go as far as you'd like.
We've done just that on a number of client sites - for example one of our clients has most of their users stored as Commerce Server users, and use the Commerce Server profile system, so we wrote a membership and profile provider to talk to those datastores - a fairly simple excercise.
Most people are probably going for 3 because of the need to authenticate over raw TCP - this introduces a layer beyond that of the standard ASP.NET membership providers.
Most of what MS produce is "ok" or "good enough", but there will always be edge cases where you want to do something "not quite standard" that mean you end up rolling your own. I guess to have something beyond "Basic Auth" or "Windows Auth" that was simple for your average developer to understand, they took the sensible option of "lets just build this for the web".
If you take a look at the numerous ways you can authenticate against a WCF service, you'll see what I mean - these are designed to handle different transport mechanisms, and are therefore much more complex.
That said, the default roles and profile providers are fairly limited (roles: no hierarchy, so you need to check for each possible role, or explicitly assign each role to the user; profiles: all stored in one field as comma seperated values - not easy to find all users who've got a value set).

We use (3). Actually that helped us in an integration scenery to have accounts in sync with
business processes
Other systems (not all on the same technology stack (ASP.NET))

On a recent project we extended the ASP.NET membership provider (wrote a custom provider) with the intent of using some of the role based controls for managing permissions. Now that the project has matured sufficiently, we're finding that the controls are not flexible enough for our requirements, and to some extent we're regretting going down the MS membership path. Rolling your own authentication if you have the time to architect it correctly is going to be the best option.
It sounds like your app is a bit of a hybrid in that you're serving internal and external customers, but perhaps also give some consideration to integrating OpenID for your external customers. There are some great ASP.NET OpenID controls that really makes handling new accounts for external customers a no brainer. This of course depends on how 'public' your application is.

Ldap anyone? It's free, cross-plaftorm, easy to use and administer remotely, has bridges to other auth schemes, and bindings in more languages that you knew existed...

Isn't AZMan from 2003?
I would recommend 1 or 3. Personally I've always gone for 3. There's a lot of functionality that 1 has that I don't use or care to use.

I would stay away from AzMan. We went down that road once and didn't like the section of town we broke down in. We've always done AD-based logins that use the SID of the current user to link to a user in the database, then taken the permissions from there. Given your setup this may not be possible (or practical), but I'd stay away from AzMan in any event.

I'm not an ASP or .NET developer, but my gut says (3). You really don't want a public-use web-app to have any sort of access to your corporate network, much less be able to put auth credentials anywhere near AD.

You seem to provide too much and too extensible to stick to one technological solution
Solution 3.
I would base the whole application around a User class
You would just simply have to model it so that it will provide you with the needed flexibility and extensibility
Something like:
[ClassAttribute ( "Yordan Georgiev", "1.0.2", "20090302", "20090415" , false )]
public class User
{
#region DomainName
private string _DomainName;
public string DomainName
{
get { return _DomainName; }
set { _DomainName = value; }
} //eof property DomainName
#endregion DomainName
#region Status
private int _Status;
public int Status
{
get { return _Status; }
set { _Status = value; }
} //eof property Status
#endregion Status
#region Password
private string _Password = Resources.GV.Pass;
public string Password
{
get { return _Password; }
set {
_Password = GenApp.Utils.Security.Encryptor.Encrypt ( value,
GenApp.Conf.GenAppSettings.Instance.EncryptionAlgorithm );
//debug_Password = value; //unencrypted
}
} //eof property Password
#endregion Password
#region ListUserRoles
private List<UserRole> _ListUserRoles;
public List<UserRole> ListUserRoles { get { return _ListUserRoles; } set { _ListUserRoles = value; } }
#endregion ListUserRoles
#region UserSettings
private GenApp.Conf.UserSettings _UserSettings;
public GenApp.Conf.UserSettings UserSettings
{
get {
if (_UserSettings == null)
_UserSettings = (GenApp.Conf.UserSettings)GenApp.Conf.GenAppSettings.Instance;
return _UserSettings;
}
set { _UserSettings = value; }
} //eof property UserSettings
}

Related

ASP.NET Identity - Steps for custom authentication

Envrionment: Visual Studio 2013, ASP.NET MVC 5
On the new MVC5-based project I will be working on, I need to use a custom database that stores usernames, passwords, and roles in its own way. I am searching the Internet to look for an example for custom authentication. Looks like the old-style "membership provider" classes have been replaced by the new "Identity" mechanism.
However, finding a good step-by-step example has proven to be futile. There are a few links (published this year) that talk about implementing custom IPrincipal and DbContext classes. Some other links talk about implementing IUserLoginStore and IUserPasswordStore. A few others hinted on implementing IUser, IUserStore interfaces.
Maybe the last option is what is needed. Can someone please guide me with the steps or point me to any link that has a simple example? Something like:
Implement MyUser based on IUser
Implement MyUserStore based on IUserStore
Modify web.config to use MyUserStore
Remove DefaultConnection from web.config as it is not required
Regards.
First, stop. Stop thinking about "custom authentication". You don't need custom authentication, you just need custom storage of authentication data.
ASP.NET Identity has abstracted out the storage mechanism of authentication from the process of authentication. There are several interfaces that follow the pattern IxxxStore.. Such as IUserStore, IRoleStore, etc...
You can find more information about this here, along with custom implementations for various databases which you can probably convert to your own needs.
http://odetocode.com/blogs/scott/archive/2014/01/20/implementing-asp-net-identity.aspx
As an example, here is a RavenDB implementation that uses all the various interfaces in a single class.
https://github.com/tugberkugurlu/AspNet.Identity.RavenDB/blob/master/src/AspNet.Identity.RavenDB/Stores/RavenUserStore.cs
However, all this assumes you really truly a need to store data totally differently. If you just need to store the data in different columns, then it may simply be as easy as overriding OnModelCreating in your IdentityContext and changing the names of the columns in use.
ad.1.
public class ApplicationUser :IUser
{
public string Id
{
get;
set;
}
public string UserName
{
get;
set;
}
}
ad.2.
public class MyStore : IUserStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser>, IUserEmailStore<ApplicationUser>
{
... //implement all interfaces here
}
ad. 3.
Now you can create your applicationUserManagerService (you will need IdentityMessageService, and IDataProtectionProvider):
var applicationUserManagerService = new ApplicationUserManagerService(new MyStore(), emailService, dataProtectionProvider);
Try to use IoC and register your IUserStore (I did it this way - link below):
unityContainer.RegisterType<IUserStore<ApplicationUser>, MyStore>();
check also my answer here (i'm using int as UserId there):
AspIdentiy ApplicationUserManager is Static, how to extend so it participates in my IoC framework?

ASP.NET Identity

I'm currently building a new ASP.NET MVC 5 project which I want to release around September. I need to choose a membership system, but I'm currently quite confused about which direction should I take. The current SimpleMembership works well, but will apparently be incompatible with the upcoming ASP.NET Identity. ASP.NET Identity on the other hand is absolutely new with zero documentation and can change anytime. Finally it seems that string based IDs are used here, which seems like a very unnecessary overhead compared to integer based IDs, which SimpleMembership supports. Is there a good, future proof way I can choose?
I would advise against using SimpleMembership as well. You can still use int IDs in your database, you would just need to ToString() the ID when plugging in your database entity, i.e.:
public class MyUser : IUser {
[Key]
int UserID { get; set; }
string IUser.Id { get { return UserId.ToString(); } }
}
In my opinion if you start your project with asp.net mvc 5 you should use the new membership system since it is well integrated with http://owin.org/ standards.
I would either use the newest version of identity or build your own Account system completely. ASP.NET Identity now uses a GUID ( NVARCHAR(128) - in the db ) for the ID, however you can still use a int if you want to. I know people still using identity 1.0 with no issues I believe they used int for the Id back then.
Either way an Id shouldnt ever clash whether its a int or a guid. as the above post said you can just Id.ToString();
Whatever route you take I dont think it will make much of a difference.
I believe ASP.NET is quite good framework and provide almost all required functionality for an applications. It also provide feasibility to choose type of Id column as per your choice. I created basic a wrapper over ASP.NET identity and published a nuget, so that it would be easily use. You can take a look on code at github

How to setup single-code multiple-database ASP.NET SaaS application

I am building a SaaS application and I would like to retain the single code base I have. I would like to be in separate sub-domains cust1.saascompany.com, cust2.saascompany.com, etc.
However, I don't have any TenantID's and would prefer for multiple reasons to stay with separate databases for each customer (primary one is that it's already coded that way and doesn't make sense to change it until usage warrants). The database has the user login membership within it.
I'm guessing I would need separate web.configs for connection strings? Or should I create a separate database that stores all the connection strings and any application level variables/constants? Eventually, I would like to be able to automate this provisioning (again, when usage warrants it).
Are there some articles or posts that anyone can point me to regarding how to set this up with steps? I haven't been able to find what I'm looking for.
Technically, this is simple. We do this for years. Although we use a different convention (my.domain.com/cust1, my.domain.com/cust2 plus url rewriting) this doesn't change anything.
So, this is what you do. You create an abstract specification of a connection string provider:
public interface ICustomerInformationProvider
{
string GetConnectionString( string CustomerId );
... // perhaps other information
}
then you provide any implementation you want like:
public class WebConfigCustomerInformationProvider : ICustomerInformationProvider { ... }
public class DatabaseConfigCustomerInformationProvider : ICustomerInformationProvider { ... }
public class XmlConfigCustomerInformationProvider : ICustomerInformationProvider { ... }
and you map your interface onto the implementation somehow (for example, using an IoC Container of your choice).
This gives you the chance to configure the provider during the deployment, for example, a one provider can be used by developers (reads connection strings from a file) and another one in the production environment (reads connection strings from a database which can be easily provisioned).
If you have other questions, feel free to ask.

Switch to SQL membership provider from AD membership provider runtime

In my asp.net application admin functionality, I am trying to combine AD authentication and form authorization for creating the users, roles and Assign users to roles etc. I have configured MembershipADProvider and AspNetSqlMembershipProvider in my web.config with MembershipADProvider as the default one. After user logs in using AD authentication, I need to switch/assign my membership object to use AspNetSqlMembershipProvider in order to get all the users from membership object (from dbo.aspnet_Users table). How do I switch the provider during run time? I have tried different approaches after searching for this issue and none of that seem to work for me so far.
Here are couple of approaches I tried:
1. foreach (MembershipProvider mp in Membership.Providers)
{
if (mp.Name == "MembershipADProvider")
{
Membership.Providers.Remove(MembershipADProvider");
MembershipUserCollection users = Membership.GetAllUsers();
ddlUsers.DataSource = users;
ddlUsers.DataBind();
break;
}
}
Membership.Providers.Remove(MembershipADProvider"); - doesn't work as it's not supported..
Also, tried to clear the Membership.Providers and then add only the type of AspNetSqlMembershipProvider which are also not supported.
I can't set Membership.Provider with value from
Membership.Providers["AspNetSqlMembershipProvider"] as Membership.Provider is a read only property.
I tried to swtich the connection string between 2 providers, which didn't swtich the provider, as both are different types of providers..if both were sqlserver providers this would have worked I believe.
Please let me know if anybody has successfully implemented or if at all this is a plausible approach. Thank You!
You would pass an explicit provider to your code, rather than taking a dependency on Memebership directly (which just wraps the one flagged as default in the config). There is no need to swap them in and out at runtime, think how this would affect thread safety.
So rather than saying Membership.GetAllUsers(); you would do something like (I don't have a compiler to hand):
public UserSerivce : IUserService
{
private MembershipProvider provider;
public UserService(MembershipProvider provider)
{
this.provider = provider;
}
public IEnumerable<MembershipUser> GetUsers()
{
return provider.GetAllUsers();
}
public void DoSomethingElseUseful()
{
...
}
}
And then to use it for a particular provider:
var service = new UserService(Membership.Providers["mySqlMembershipProvider"]);
var users = service.GetUsers();
Or if using AD specific code:
var service = new UserService(Membership.Providers["myADMembershipProvider"]);
var users = service.GetUsers();
Using DI in this way also helps keep code testable.
If all you need a list of users in the aspnet_Users table, just connect to your database with System.Data.SqlClient objects and query the table. There is no reason (that you mentioned) you need to use a membership provider to get that data.
Having said that, your membership/authentication scheme sounds like it may have some design issues, perhaps best tackled in a different question, but I think it might be useful to you if you sought comment on what you are trying to accomplish overall with the multiple membership providers.
Edit: I found some potentially useful posts on using multiple membership providers. It looks like the general idea is to implement custom code handling the Login.Authenticate event on your Login control, and use Membership.Providers["ProviderName"].ValidateUser to attempt authentication with each provider.
http://www.stevideter.com/2008/03/20/using-two-membership-providers-for-aspnet-logins/
http://forums.asp.net/p/1112089/1714276.aspx

ASP.NET MVC, Account Model : How to make relations to it?

I've created a new MVC 3 Internet Application, and it comes with the Account model/controller, etc.
Those are stored in a MDF database.
I'd like to create new models for my application, and make relations from these to my account model.
I did not find anything about it, maybe I looked for the wrong thing... So I was wondering, is there anybody who could point me in the right direction about how to do so?
Thanks!
Ah there in lies a problem with using the built in providers and aspnet default db.. In that database there is a unique id for each row - you in theory CAN use that to link to your databasse - but realize this is completely separate. One alternative many people do is to use a Custom Membership Provider (for example custom sql membership provider)
There are tons of articles/blogs out there on that - for starters see:
http://blogs.syrinx.com/blogs/dotnet/archive/2007/12/14/a-simple-custom-sql-membership-provider-part-1.aspx
This enables you to keep everything in your own database and its fairly easy to implement.
I found this as well:
https://github.com/anderly/SimpleMembership.Mvc3
I guess it's another alternative.
The answer I was looking for is exactly this:
In your model, link to the Membership User like this:
public virtual Guid UserGuid { get; set; }
public virtual MembershipUser User
{
get
{
return Membership.GetUser(UserGuid);
}
}

Resources