Custom .NET authentication, membership, profile provider for portlets? - forms-authentication

I am wondering if it is possible to leverage the Authentication, Membership, and/or Profile provider features in .NET to help integrate .NET web apps into my company's enterprise portal. In a nutshell, the portal sends custom header values to any application that is 'behind' the portal for fields like the username, user profile data, and some access rights. One issue that we have with the portal is that we aren't able to leverage many of the .NET apps available on the web because they weren't designed to be "portal aware", primarily to trust that the user has already authenticated.
Would it be possible to somehow write a custom authentication provider (or maybe leverage forms auth somehow) to just look at the header (plus the IP) and automatically "authenticate" as that user? My thinking is that by writing a profile provider, possibly a membership provider, and somehow adding authentication I would be able to download cool components like the Oxite blog (.net mvc demo that i found), switch providers to my custom one, and leverage it behind my company's portal with minimal code changes.
Does this make any sense? I feel that I might not be understanding how these components fit into the puzzle.

I don't think you can do this with zero changes to the .Net app, but I think you might be able to do it with minimal changes. Please note that I'm assuming that the portal Gateways everything that is going to the .Net web application. That is, the portal gets every HTTP request from the browser, adds its own headers to it, submits the request to the .Net app, gets a reply from the .Net app, rewrites things some more, and then returns info to the browser.
I'm guessing that what happens now (the reason you wrote this question) is you embed this .Net app into a portlet on your portal, but when someone tries to browse to it, even though they are logged into your portal, they see the external .Net login screen inside the portlet box. Not very nice.
There are two steps that need to be taken here:
Re-do the login page for the .Net app to auto-login portlet users
Create a custom membership provider that works along with #1
1. Re-do the login page for the .Net app to auto-login portlet users
Find the login page for the .Net app. It'll probably be something like login.aspx. Copy it (and any associated codebehind files) to portallogin.aspx and portallogin.cs.
Open up the portallogin.aspx and portallogin.cs files. Get rid of all of the controls and code in there. Replace it with something like what you see below. Please note that everywhere you see PORTAL_SomeFunctionName, you'll need to replace that with code from your Portal's SDK that makes the appropriate function call.
const string specialpassword = "ThisPasswordTellsTheBackendSystemThisUserIsOK";
Page_Load()
{
if (PORTAL_IsLoggedInToPortal())
{
string username = PORTAL_GetCurrentUserName();
// Authenticate the user behind the scenes
System.Web.Security.FormsAuthentication.SetAuthCookie(username, false);
System.Web.Security.FormsAuthentication.Authenticate(username, specialpassword);
}
else
{
throw new Exception ("User isn't coming from the Portal");
}
}
Next, edit web.config for the .Net application and tell it that the login page is portallogin.aspx instead of login.aspx.
That should take care of automatically attempting to log the user in.
2. Create a custom membership provider that works along with #1
This is where you will need to create a custom membership provider. In order for this to work, the .Net application you are working with has to make use of membership providers and allow for a custom membership provider to be used.
Create a new Membership Provider. You need to create a class and inherit from System.Web.Security.MembershipProvider. At a minimum, I think you'll need to implement the GetUser and ValidateUser functions and ApplicationName property. Below are some ideas for how they could look. The are many more functions that need to be overridden, but the stubs (with the accompanying NotImplementedException(s)) can probably be left alone.
public override string ApplicationName
{
get
{
return "Portal";
}
set
{
;
}
}
private const string specialpassword =
"ThisPasswordTellsTheBackendSystemThisUserIsOK";
public override bool ValidateUser(string username, string password)
{
// If the password being passed in is the right secret key (same
// for all users), then we will say that the password matches the
// username, thus allowing the user to login
return (password == specialpassword);
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
string email = PORTAL_getemailfromusername(username);
System.Web.Security.MembershipUser u = new MembershipUser(
this.name, username, username, email, "", "", true, false,
DateTime.Now(), DateTime.Now(), DateTime.Now(),
DateTime.Now(), DateTime.Now(), DateTime.Now()
);
return u;
}
You can also do similar implementations for the .Net RoleProvider and ProfileProvider if that functionality would be helpful in integrating with this .Net app. (the Role provider will provide group membership information, and the ProfileProvider will provide extra bits of profile info such as email address, zipcode, or whatever other properties you want it to provide for each user. This information would have to be lookuped up from a database or from the portal HTTP header information.
Other Considerations
Since you're using a third party authentication provider for this external .Net application, you need to figure out how you can tell this .Net application which users/groups are administrators. I can't tell you that - you'll have to find that out from the third party .Net application. This is needed if there are any permissions that are needed to do anything in this .Net application beyond having an account.
Since you're using this in a portal, there are a couple of ways it can be used. You can just have one big portlet that shows the entire .Net web application. You could also have lots of little portlets that show bits and pieces of the .Net web application. Either way, you'll have to consider that the portal might or might not render things properly when it puts a full .Net application inside a little portlet box on a portal page. If you get HTML that looks or works weird, it'll be annoying to fix it. You can either try to fix the original .Net web app to spit out different HTML, or you can add a module to IIS to rewrite the HTML on the fly (I'm not completely sure it's a module... you'll have to dig some on IIS to figure out how you might do this).
Whew!
I know this doesn't cover everything, but I've worked with setting up the Plumtree Portal (now BEA's Aqualogic User Interaction) as the authentication source for Microsoft's SQL Server Reporting Services, and I've implemented a Custom Authentication Provider for IIS based on user membership stored in a Dynamics NAV table. Hopefully my experience with these projects will be helpful to you in your integration of this external .Net application with your portal.
Tim

I think that's a great idea. You definately want the Membership provider, and ensure authentication is set to 'forms' for all the .Net web apps you download.
Also check out IIS7 because its newly constructed pipeline means you can leverage .Net based authentication types in any handler (CGI, etc). So for example, you can use Windows Authentication for your PHP applications.

One minor point that the other answers are missing, is that forms authentication in asp.net supports cross authentication.
The forms authentication tag has domain and cookie name properties.
matching these & using the same machine key, will allow cross authentication between apps.
Your membership provider for each site will need to point to the same datastore though.

Related

ASP.NET Identity - Windows Authentication and Web Services

ASP.NET Identity - Windows Authentication and Web Services
All of the web applications I create for my job I do for the Intranet so we use Windows Authentication. However, in order to get any other information for the current user (email, phone, office) I need to consume a web service that is provided by another department. To get the information I pass the User's Name property to the web service and use a class I've written to store the information. I then store this object in a session and use it whenever needed.
While this works fine I know there must be a better way. I've recently looked into the identity framework and while it looks great I'm not exactly sure if it's the right fit for my situation. Most of the examples I look at have it work with a database to register and log in users. My users will never need to log in nor will they need to be created, at least not within the application. I basically just need to be able to store the data from the web service in the identity. Is this possible?
After enough looking around I was able to solve my problem. Using these links I figured out where I needed to load my user data, set my claims, and then how to use the claims to authorize my controllers.
http://www.mytechnotes.me/2015/08/04/56/
http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/

Securing WCF service in an ASP.net financial application

I have an MVC4 ASP.net financial application with a WCF service. The current scenario isn't secure enough and I need you help with that.
The current scenario:
The user login using a login form, and I send his login details using a JSON object containing the UserID and the Password to the WCF service:
http://example.com:22559/Login
This returns a JSON object with a true or false.
If it's true, I use the ASP function
FormsAuthentication.SetAuthCookie(loginModel.UserID, loginModel.RememberMe);
to set authorization cookies to use it later.
When the user adds a new Transaction I send a JSON object containing the transaction details without the password to:
http://example.com:22559/AddTransaction
I depend here that the MVC controller will not allow the user to access the transaction page if he isn't logged in.
The problem is anyone can now sneak-out and add a transaction without entering the password!, using the URL:
http://example.com:22559/AddTransaction
What I need to do now, is to make the WCF service itself secured, but I don't know how to do that without making the user enter his username and password each time he adds a new transaction!, so, what is the proper way to do that?
Thanks in advance.
MVC 4's controllers typically use MemberShipProvider for authentication and RoleProvider for authorization. So your WCF services may share the providers.
For authentication, you don't need to do anything in WCF codes. For authorization, it is handy to decorate respective operation implementation function (not interface) with PrincipalPermissionAttribute with the Role name defined. The rest will be done in config and by runtime.
For more details, just search "membershipprovider wcf", you will find a lot articles/tutorials in MSDN, CodeProject and StackOverflow.
Please be mindful that in MVC 5 if you will be moving to MVC5, Identity 2.0 is used by default, and MembershipProvider and RoleProvider will not be their by default. Nevertheless, your WCF codes should remain unchanged, and only some elements under ServiceModel will need to adapt the new custom authentication and authorization, and the client codes should remain the same as well, no config change needed.

Need help understanding ASP .Net MVC user authentication/authorization

I have been going around in circles trying to properly understand this.
I have an ASP .Net MVC project I am working on and need to implement user logins that authorize and authenticate against en external system (via webservice).
I can't seem to get my head around MembershipProvider and AuthorizeAttribute in the context that I require.
Which do I need to use (I believe its both) and where do I need to customize to provide the authentication against an external system.
There is one additional thing I also require on top of the default ASP .Net user principals in that the external webservice will return a session ID upon successful login that would be used for subsequent requests to external services.
Would someone be able to point me in the direction of some useful example of this sort of set up?
MembershipProvider is used to provide the users that may login the system. The RoleProvider is used to tell which roles a user has. They are used during the authentication process. i.e. identifying the user. You can read about membership vs roles
The [Authorize] attribute on the other hand is used during authorization. i.e. to check if the user is allowed to do something.

Limiting access to a WCF REST (webHttpBinding) Service using the ASP.NET Membership Provider?

I have found a lot of material on the web about using the ASP.NET Membership Provider with the wsHttpBindings, but I haven't seen any reference to using it with webHttpBindings.
I am looking for a system that will work in two scenarios:
The user is logged into an asp.net website and the website is making calls to the service.
The user accesses the service directly via REST.
Is this possible using the built in framework (i.e. just through configuration)? If so how do I configure the service? And how does the user pass the credentials to the REST service?
The best source I've found is here: http://www.leastprivilege.com/FinallyUsernamesOverTransportAuthenticationInWCF.aspx
The site also has tons of other information about setting up HTTP Modules to handle basic authentication (which I'm guessing you'll be using since it is kind of the standard).
The HTTP Module authentication method is located on Codeplex with sample code and everything here: http://www.codeplex.com/CustomBasicAuth
ADO.NET Data Services you mean?
You can build a QueryInterceptor for an entity and limit the access to it.
For example:
[QueryInterceptor("foo_entity")]
public Expression<Func<foo_entity, bool>> FilterMembership()
{
MembershipUser user = Membership.GetUser();
Guid userGuid = (Guid)user.ProviderUserKey;
return c => c.UserId == userGuid;
}

How to grab AD credentials from client machine in a web application?

Is it possible to grab activedirectory credentials for the user on a client machine from within a web application?
To clarify, I am designing a web application which will be hosted on a client's intranet.
There is a requirement that the a user of the application not be prompted for credentials when accessing the application, and that instead the credentials of the user logged onto the client machine should be grabbed automatically, without user interaction.
Absolutely. This is especially useful for intranet applications.
Since you did not specify your environment, I'll assume it is .NET, but that isn't the only way possible of course.
Active Directory can be queried easily using LDAP. If you're using .NET, you can do something like in this code example or my example below. You can also do it within SQL environments as well.
If you just need Windows to handle authentication, you can set, for example, a .NET Web app up for Windows Authentication. Be sure to turn off Anonymous Logins within IIS for your application. Once done, you'll be able to access the user's Windows logon name and use it to make further security checks (for example, their group/role membership in AD).
You can also simplify the whole mess using something like Enterprise Library's Security Application Block.
Here is a short C# example: (convert to VB.NET here)
using System.DirectoryServices;
/// <summary>
/// Gets the email address, if defined, of a user from Active Directory.
/// </summary>
/// <param name="userid">The userid of the user in question. Make
/// sure the domain has been stripped first!</param>
/// <returns>A string containing the user's email address, or null
/// if one was not defined or found.</returns>
public static string GetEmail(string userid)
{
DirectorySearcher searcher;
SearchResult result;
string email;
// Check first if there is a slash in the userid
// If there is, domain has not been stripped
if (!userid.Contains("\\"))
{
searcher = new DirectorySearcher();
searcher.Filter = String.Format("(SAMAccountName={0})", userid);
searcher.PropertiesToLoad.Add("mail");
result = searcher.FindOne();
if (result != null)
{
email = result.Properties["mail"][0].ToString();
}
}
return email;
}
You do not have to specify a domain controller. Performing the empty/default constructor for DirectorySearcher will cause it to attempt to look one up automatically — in fact, this is the preferred method.
Maybe .NET has a more direct way to do it, but with PHP I just access our Active Directory server as an LDAP server.
I'm not sure what adjustments to the server are required to do this. I didn't setup the server, I just query it.
I'm not suggesting you use PHP either. I just find it easier to deal with LDAP then trying to tie directly into Active Directory.
Windows Integrated Authentication, user has to use IE, AND the site has to be in the user's trusted sites. If these things are true, then IE will pass your windows security token to the web site and it will authenticate with it. We do this with SharePoint on our intranet otherwise it's a pain to access anything restricted -- you'd get prompted every time you click on a document.
No, of course not. Can you imagine the havoc that would result in random web apps being able to get your AD username and password?
Now, if you just want the username - that's in REMOTE_USER if you're using integated windows auth. And, windows auth will auto login the user to your site - assuming you share a domain (or trust).
Edit: IWA works in an intranet scenario, since IE - by default - includes intranet sites in the Intranet security zone. Also, a sysadmin can use GPO to set other trusted sites. Firefox also supports NTLM, as does Opera and Chrome. All in all, it's not a bad way to setup an intranet.
Note, though - that you don't get credentials. You negotiate a token with the client, which is what keeps IWA secure (and my above point relevant).

Resources