How to "un-impersonate" (un-delegate?) in Kerberos - asp.net

I have a web application using Kerberos to access an external resource useing ASP.NET 3.5 and IIS.
When a user connects with the application, Kerberos authentication auto-magically allows me to connect to external resources acting as the user using delegation. This was not easy to do. It is nice, but I've a problem. Sometimes I need to connect to an external resource using an account with more rights than the user. The service account which the app-pool is running under has the addition rights I need. How can I remove the user's Kerberos identification and connect with Kerberos using the service account running the application pool?
UPDATE
I'm not sure why I am getting no responses at all. I've never seen that before. Please post questions, they may clarify the problem (to me too).
Woring in Kerberos and need an overview of delegation? Read the first part of this answer: https://stackoverflow.com/a/19103747/215752.

I have a class:
public class ProcessIdentityScope : IDisposable
{
private System.Security.Principal.WindowsImpersonationContext _impersonationContext;
private bool _disposed;
public ProcessIdentityScope()
{
_impersonationContext = System.Security.Principal.WindowsIdentity.Impersonate(IntPtr.Zero);
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
_impersonationContext.Undo();
_impersonationContext.Dispose();
_disposed = true;
}
else
throw new ObjectDisposedException("ProcessIdentityScope");
}
#endregion
}
And I use it like so:
using(ProcessIdentityScope identityScope = new ProcessIdentityScope())
{
// Any code in here runs under the Process Identity.
}
This code is based on this MSDN article: http://msdn.microsoft.com/en-us/library/ms998351.aspx

Related

Can I have application listening in multiple ports? (one for public and one for private use)

I have a .NET MVC application which has multiple features.
Can I host this application in IIS as single application by configuring different ports as shown below?
Website to view product localhost:80/index.cs
API exposed for internal usage localhost:23004/Listporducts();
Is it possible?
Real time scenario: I am hosting application in Azure IaaS VM. My internal applications will use the API and customers shall use public website
In my opinion, the most easily thing is you could prevent the Azure VM's not open the 23004 port. Details, you could refer to this article.
If you don't want to use Azure MV, you could consider using a custom filter Attribute in the web api to check if the request is local. If the request is not sent from local, then you could directly return the 404 not found error.
More details about how to use custom Filter Attribute, you could refer to this article.
public class CustomActionAttribute : FilterAttribute, IActionFilter {
public void OnActionExecuting(ActionExecutingContext filterContext) {
if (filterContext.HttpContext.Request.IsLocal) {
filterContext.Result = new HttpNotFoundResult();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext) {
// not yet implemented
}
}

Calling webapi only when client has install certificate in his machine

I wanwt to add a layer of security via certificate to access a hosted ASP.NET WebAPI.
I want only those clients who have installed the certificate in their machine to have access to that WebAPI.
Can anyone provide me a way to achieve this behavior?
You can configure IIS to require client certificates without writing a single line of code. Just follow these instructions, specifically these:
Click SSL settings in the middle panel and select Require SSL and Require for Client certificates.
Double click the Authentication icon and disable all the Authentication method.
Make sure the IIS Client Certificate Mapping Authentication is installed.
Click the Configuration Editor in the middle panel and set the one to one mappings refer to this link
Just as suggested in comments, a quick google search could lead to interesting results.
Nevertheless a possible solution is the implementation proposed in the following Microsoft article :
public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
{
ReasonPhrase = "HTTPS Required"
};
}
else
{
base.OnAuthorization(actionContext);
}
}
}
You would then decorate your ApiController action :
public class SomeController : ApiController
{
[RequireHttps]
public HttpResponseMessage Get() { ... }
}

Pass User info to WCF Web service with WCF method vs with Soap header

My WCF Webservice provide all data manipulation operations and my ASP .Net Web application present the user interface.
I need to pass user information with many wcf methods from ASP .Net app to WCF app.
Which one in is better approach regarding passing user info from web app to web service?
1) Pass user information with SOAP header?
ASP .Net Application has to maintain the number of instances of WCF Webservice client as the number of user logged in with the web application. Suppose 4000 user are concurrently active, Web app has to maintain the 4000 instances of WCF webserice client.
Is it has any performance issue?
2) Pass user information with each method call as an additional parameter?
Every method has to add this addtional paramter to pas the user info which does not seems a elegant solution.
Please suggest.
regards,
Dharmendra
I believe it's better to pass some kind of user ID in a header of every message you send to your WCF service. It's pretty easy to do, and it's a good way to get info about user + authorize users on service-side if needed. And you don't need 4000 instances of webservice client for this.
You just need to create Behavior with Client Message Inspector on client side(and register it in your config). For example:
public class AuthClientMessageInspector: IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
request.Headers.Add(MessageHeader.CreateHeader("User", "app", "John"));
return null;
}
}
public class ClientBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
foreach (var operation in endpoint.Contract.Operations)
{
operation.Behaviors.Find<DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = Int32.MaxValue;
}
var inspector = new AuthClientMessageInspector();
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
And extract it from your service-side:
var headers = OperationContext.Current.IncomingMessageHeaders;
var identity = headers.GetHeader<string>("User", "app");

Building ASP.Net custom authorization against database without MVC

this is my first request, so don´t be too hard. :)
We are building an Sharepoint 2010 - Application, which consists of some Sharepoint Web Parts and many ASP.Net-Sites. Therefore we are limited to use ASP.Net without MVC. This decision is made and can´t be refused.
We are using Windows Authentification with Impersonation. The Users are stored in an application database. Along with the users there are roles which have rights to specific objects and specific actions. all these informations are stored in the custom database.
The database has a data access layer (EF 4.0). Because Sharepoint is limited to .NET Framework 3.5, the business logic consists of a WCF Data Service which is using the DAL and business logic libary which accessing the WCF Data Service to grab the required information.
The ASP.Net-Pages and Sharepoint Web Parts are directly accessing the business logic.
What i now need is some kind of a Manager-Class which is checking the user against the database to authorize him to access the specific objects. I dont want to do it programmaticly. I want to use annotations to specify if a method from the business layer can be called or not. Furthermore i want to hide some things in the ASP.Net Sites without an programmaticly if-clause.
Can someone give me a hint to achieve this? Is there a way do customize some part of the standard framework to realize it?
The user and his roles and rights i want to store in a session. Is this a good way? the application is accessible only in local network.
Welcome to stackoverflow! A few thoughts on this -
You may be better suited to ask these questions at the cousin site http://sharepoint.stackexchange.com.
This depends on your web farm architecture. If your web front end and data sources are on the same server, then it should be simple to use windows authentication to determine the current user. However, if your web front ends and data sources are on separate servers, then you've reached a limitation due to the "double hop" scenario, where the user's credentials cannot be shared to the server behind the sharepoint server - so to speak.
To work around, investigate using Kerberos authentication in your SharePoint environment, which allows SharePoint to track user credentials throughout the farm - http://blogs.technet.com/b/tothesharepoint/archive/2010/07/22/whitepaper-configuring-kerberos-authentication-for-sharepoint-2010-and-sql-server-2008-r2-products.aspx
Yet another alternative, don't use SharePoint as your application host. Create your web application and deploy it as its own website (http://mysupercoolsite.organization.com), and in SharePoint create a new "web part page", with a "full page vertical" layout. Then, add a "Page Viewer" web part to the page, supplying the url to mysupercoolsite.organization.com. This way, SharePoint is a "portal" to this application for your users, but all authentication, authorization, and structure are based on the application itself, and not at all in SharePoint.
We have stayed at sharepoint as application host.
I´ve implemented a Custom UserControl which implements all the security questions.
public partial class FMD_RoleEnabledControl : System.Web.UI.UserControl
{
public string EnabledRoles { get; set; }
public bool HasDataBinding { get; set; }
public string CurrentUserName
{
get { return Page.User.Identity.Name; }
}
protected override void OnPreRender(EventArgs e)
{
if (!HasDataBinding)
Visible = EnabledRoles.Split(',').Any(rolle => new FMDRoleProvider().IsUserInRole(CurrentUserName, rolle));
base.OnPreRender(e);
}
protected override void OnLoad(EventArgs e)
{
if(HasDataBinding)
Visible = EnabledRoles.Split(',').Any(rolle => new FMDRoleProvider().IsUserInRole(CurrentUserName, rolle));
base.OnLoad(e);
}
}
Custom-RoleProvider
public class FMDRoleProvider : RoleProvider
{
public const string SEPERATOR = ",";
...
public override string[] GetRolesForUser(string username)
{
if (username == null || username == "")
throw new ProviderException("Kein User-Name übergeben"); //TODO
string tmpRollen = "";
RechteManager rm = new RechteManager();
var rollen = rm.GetUserRollen(username);
foreach (var rolle in rollen)
{
tmpRollen += rolle.ROL_Name + SEPERATOR;
}
if (tmpRollen.Length > 0)
{
//Letzten seperator entfernen
tmpRollen = tmpRollen.Substring(0, tmpRollen.Length - 1);
return tmpRollen.Split(',');
}
return new string[0];
}
...
public override bool IsUserInRole(string userName, string roleName)
{
if (userName == null || userName == "")
throw new ProviderException("User name cannot be empty or null."); //TODO
if (roleName == null || roleName == "")
throw new ProviderException("Role name cannot be empty or null."); //TODO
RechteManager rm = new RechteManager();
return rm.IsUserInRolle(userName, roleName);
}
}
Usage
public partial class CustomControl: FMD_RoleEnabledControl
<custom:CustomControl ID="custom" runat="server" EnabledRoles="Admin" HasDataBinding="True" />
Its only the first approach to check against roles, but it works very well. As a second target i am going to implement extra security stuff like checking against speficic actions. Also the RoleProvider has to be registered in web.config. But time is short ;)

What is the preferred way to access ASP.NET profile in .NET n-tier application?

I have a WPF application which talks to a WCF service hosted in IIS. I am also using ASP.NET authorization and authentication to access the service methods. There is also a relatively thin web based interface to the system as well.
What I want is to make use of the ASP.NET Profiles. For example - load profile from server, make changes and then save back to the server. All that with WCF Service calls.
This is my sample User Profile class which is declared server side. I have also defined the appropriate entries in the web.config so it works properly.
public class UserProfile: ProfileBase
{
public static UserProfile GetUserProfile(string username)
{
return Create(username) as UserProfile;
}
public static UserProfile GetUserProfile()
{
return Create(Membership.GetUser().UserName) as UserProfile;
}
public int? XMLVersion
{
get
{
return this["XMLVersion"] as int?;
}
set
{
this["XMLVersion"] = value;
}
}
}
However I cannot pass it back to the client because ProfileBase is not serializable. Of course I can declare data transfer class which will transfer data back and forth from the profile but it does not look as a very good solution.
So far I am unable to find information how to implement it. Can someone help me with that or point me to another solution?
The WCF profile service does what you are asking for. Have a look at it here.
You can see the list of methods it provides in this MSDN page

Resources