Get Username of Currently interacting User in WCF both Rest Endpoint and MVC3 with Windows Authentication - asp.net-mvc-3

In an MVC3 project that I'm working on we're trying to move a lot of our logic that is currently in the controllers into a service layer and expose it as a REST Service in WCF.
So in our Global.asax we create a Service Route like so:
RouteTable.Routes.Add(new ServiceRoute
("Exampleservice", new WebServiceHostFactory(), typeof(ExampleService)));
and our controllers access the service something like this:
public class ExampleController : Controller {
private IExampleService service;
public ExampleController() {
this.service = new ExampleService();
}
public ActionResult Index() {
var results = service.GetAll();
return View(results);
}
}
The main point here being that we use the service class directly (without making requests over the network with an HttpClient).
Our website uses Windows Authentication (it's an intranet site) and we would like to keep it that way. My Question is, is there a way that I can get the User's Identity in the service class that will work both for how we have the Controllers using the service, and the way that WCF uses the service?
For example:
[ServiceContract]
public interface IExampleService
{
[WebGet(UriTemplate = "/")]
List<Results> GetAll();
}
public class ExampleService : IExampleService
{
List<Results> GetAll() {
// Get User Name Here
// In ASP.Net I would use User.Identity.Name
// If I was just worrying about the the REST service I would use
// ServiceSecurityContext.Current.WindowsIdentity.Name
}
}

The instruction suggested by #Ryand.Johnson is correct. The point here is that the controller do not send any credentials to the web service because it run under the asp.net user indentity not the identity of the currently loggedd user. The only way to pass the identity to the proxy is by embedding the call to the web service within an impersonation context this way:
using (WindowsImpersonationContext impersonatedUser = (User.Identity as System.Security.Principal.WindowsIdentity).Impersonate()){
//your proxy call here }
If still this way you get null you have to set manually the default credentials to your proxy

Yes, in the service security context...
OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name

Related

How are Exrin services registered to their appropriate models?

After creating a service for a model, how do I tell the model to use that service?
Within the sample Tesla app, there exists constructors which call for a service as an argument:
private readonly IClimateService _service;
public ClimateModel(IExrinContainer exrinContainer, IAuthModel authModel, IClimateService service)
: base(exrinContainer, new ClimateModelState())
{ _service = service; }
I searched but never found where the model receives the service, but I did find this:
protected override void InitServices()
{
RegisterTypeAssembly(typeof(IService), new AssemblyName(nameof(TeslaService)));
base.InitServices();
}
Exrin automatically loads Services, via reflection, if they inherit from
Exrin.Abstraction.IService

Masstranist - Access properties from middleware

I use Masstransit in multi-tenant application. On Web Api part I use Owin middleware to resolve tenant ID from DNS. I can access it globaly from services using OWIN environment.
I've created a Masstransit middleware to intecept the message and get tenant ID. In some cases I need to access it.
Since the bus is singleton-scoped, how can I access it?
I tried with IConsumeObserver.PreConsume, in debug I see private properties from the consumer, but I can't access them.
UPDATE:
Each message has TenantId property. We use Entity Framework global filter to filter all queries by TenantId. It is set on Unit of Work that we inject into consumer:
public class MyConsumer : IConsumer<IMyCommand>
{
private readonly ITenantConfiguration _tenantConfiguration;
private readonly IUnitOfWork _uow;
public MyConsumer(ITenantConfiguration tenantConfiguration, IUnitOfWork uow)
{
_tenantConfiguration = tenantConfiguration;
_uow = uow;
}
public Task Consume(ConsumeContext<IMyCommand> context)
{
return Task.FromResult(true);
}
}
The problem is that Unit of work is instantiated before I get TenantId from the message. I use Ninject and if I set unit of work to .InTransientScope() it solves my problems.
If I use Web Api, I get tenantId from Owin Middleware startup class:
var domain = context.Request.Host.Value.ToLower();
context.Set<object>("tenantId", tenantId);
Later, I can access it from services:
var owinContext = HttpContext.Current.Request.GetOwinContext();
var owinEnvVars = owinContext.Environment;
var currentTenantInfo = owinEnvVars["tenantId"]
Is it possible to have something like that when Masstransit messages?

WebApi External Bearer Authentication and Injecting User into respositories

I have a webapi project and a repositories project.
I have configured to use oauth, which uses owin middleware bearer token authentication.
I have a unitofwork with multiple repositories.
Inside the repositories I want to filter data based on the logged on user.
I would like all repositories to get the logged in user via dependency injection.
I can access the logged on user in the webapi action, but I am struggling to work out if/how I can inject the current user using DI; because the authorization is happening via the webapi Authorize?:
[Authorize(Roles = "User")]
public IQueryable<Folder> Folders()
{
// return UnitOfWork.FolderRepository.All().OrderBy(o=>o.FolderId).Skip(10).Take(50);
var test = HttpContext.Current.GetOwinContext().Authentication;
//test is populated with the logged on user here, but I don't want to set the user details of the UOW in every action in my controllers
return UnitOfWork.FolderRepository.All();
}
So in the action Folders the Authorize annotation logs the user on. But I have already instantiated the unit of work in the controller constructor with DI:
public FolderController(IUnitOfWork uow, UserManager<IdentityUser,int> usermanager)
{
UnitOfWork = uow;
UserManager = usermanager;
}
IOC container:
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
x.For<HttpContextBase>()
.HybridHttpOrThreadLocalScoped()
.Use(() => new HttpContextWrapper(HttpContext.Current));
x.For<IUnitOfWork>().HttpContextScoped().Use(
() => new UnitOfWork(new BreezeValidator
(new UserManager<AspNet.Identity.SQLServer.IdentityUser, int>(new UserStore(new SqlDatabase()))))
);
}
}
I had tried to pass in HttpContext.Current.GetOwinContext(), but at that point the authorization hasn't taken place and so the Principal has not been set.
I have looked at actionfilters (which are run after the authorization filter), but can't figure out how I would return a new unit of work instance with the logged on user set, back to the controller.
...Or whether I can set a property on the controller from an action filter?
So the question is really, how can I set the user details in all my controller's unitofwork, without lots of duplication?
Thanks
EDIT: I have a working solution, but still not sure it's the right way to go:
I created an action filter and then from there get the controller and set a UserPrincipal property on the controller's unitOfWork property.
using Project1.Web.Controllers;
using System;
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace Project1.Web.Filters
{
public class InjectUserAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var action = actionContext.ControllerContext.Controller;
UowApiController ctrl = (UowApiController)actionContext.ControllerContext.Controller;
ctrl.UnitOfWork.UserPrincipal = actionContext.RequestContext.Principal;
}
}
Then, in my UnitOfWork setter of the UserPrincipal I set the UserPrincipal in the contained repositories:
public IPrincipal UserPrincipal
{
get
{
return this.userPrincipal;
}
set
{
this.userPrincipal = value;
((Repository<Folder>)FolderRepository).UserPrincipal = value;
}
}
This works now, but it doesn't achieve dependency injection.
Also I would like to know if this is a "right" way to do it, or what would be a better approach?
I was searching for the same thing and decided on this. I think this answer will be relevant to you as well.
Proper way to dependency inject authenticated user to my repository class
I've just added a getter to the service classes that accesses the user identity at request time.
public class MyService
{
//ctor...
public IEnumerable<Results> GetResults()
{
return _ResultRepository.GetResultsByUser(UserIdentity);
}
IIdentity UserIdentity
{
get { return Thread.CurrentPrincipal.Identity; }
}
}

MVC 3 Forms authentication with IOC container

I have a problem implementing forms authentication with an IOC container in my ASP.NET MVC 3 project. We have stored our user information in the database and has a lot of custom properties.
I have an interface of my user definition registrated to the IOC container for development purposes. This interface is given to each controller so the controllers has current user information.
This al works fine until i remove the dummy user registration in the Application_Start
I receive this error:
The current type, ...CurrentUserInformation.IUserInformation, is an interface and cannot be constructed. Are you missing a type mapping?
I don't want to work with a dummy user object because I think this is not the best practice.
Can sombody help me or is there a better way to do this custom authentication?
edit added some code
BaseController
public class BaseController : Controller
{
private readonly IUserInformation _userInformation;
public BaseController(IUserInformation userInformation)
{
_userInformation = userInformation
}
}
Bootstrapper Initialize called from Application_Start
public static void Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
//register all services en repositories
//here i put my dummy user wich i want to remove
container.RegisterInstance<IUserInformation>(
new UserInformation
{
UserId = 1,
...
});
return container;
}
You can use InjectionFactory:
container.RegisterType<IUserInformation, UserInformation>(
// User information is destroyed when the request ends.
// You could use an HttpSessionLifetimeManager as well, if it fits your needs
new HttpRequestLifetimeManager(),
new InjectionFactory(container => {
UserInformation userInfo = // TODO: build your userInformation from custom authentication
return userInfo;
}));

How to setup a DAL RESTful service with EFCodeFirst for MVC applications?

For an MVC3 application I want to create a reusable DAL that is accessed as a service, as this will be used for other projects in the future.
I created all the entities with TT templates and EFCodeFirst in a separate project, then consumed it in a RESTful WCF service.
The structure of this service seems a bit different from other WCF services I have written where I have specified RESTful signatures and optional JSON responses as method decorators in the service's interface, ie:
[WebGet(UriTemplate = "GetCollection")]
public List<SampleItem> GetCollection()
{
// TODO: Replace the current implementation to return a collection of SampleItem instances
return new List<SampleItem>() { new SampleItem() { Id = 1, StringValue = "Hello" } };
}
[WebInvoke(UriTemplate = "", Method = "POST")]
public SampleItem Create(SampleItem instance)
{
// TODO: Add the new instance of SampleItem to the collection
throw new NotImplementedException();
}
Where this RESTful WCF service (created from the RESTful WCF option) differs is that there is no interface, and I can decorate the service methods with what I need - that's fine. The service will expose methods like GetUserByID(int id), etc.
The issue is that I want to use this in a MVC3 application, and am not clear on how to hook up the models to my service and would like some direction in accomplishing this.
Thanks.
Assume you want to expose an entity called Person. The WCF REST service may look as follows:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public partial class PeopleWebService
{
[WebGet(UriTemplate = "")]
public List<Person> GetCollection()
{
try
{
IPeopleRepository repository = ServiceLocator.GetInstance<IPeopleRepository>();
var people = repository.GetPeople();
// use automapper to map entities to Person resource
var result = Mapper.Map<List<Person>>(people);
return result;
}
catch (Exception exception)
{
// do logging etc
throw new WebFaultException(HttpStatusCode.InternalError);
}
}
/* other methods */
}
These services can be generated by T4 too.
Notice that there is no need for an interface on the WCF service itself. I generally do not expose any database entities directly in WCF services as my services evolve differently than my database entities. Once an API is published it should pretty much remain the same. This prevents me from changing my database schema to fit new requirements.
Instead I map my entities to resources. So Person may looks as follows:
[DataContract]
public class Person
{
[DataMember]
public string GivenName { get; set; }
/ * more properties */
}
It may be a good thing to use T4 to generate these as well. Routing is defined something like this:
public void Register(RouteCollection routes)
{
routes.AddService<WorkspaceWebService>("api/v1/people");
}
To consume it from the ASP.NET MVC project, you can share your resources (aka Person) as defined above as an assembly, or you can use T4 to generate a separate set of resources that are almost the same, but with some additional attributes needed for ASP.NET MVC, like those used for validation. I would generate it, because my ASP.NET MVC view models generally evolve independently to my REST resources.
Lets assume your REST service runs at https://api.example.com/ and your MVC website is running at https://www.example.com/. Your PeopleController may look as follows.
public class PeopleController : ControllerBase
{
[HttpGet]
public ActionResult Index()
{
return View(Get<List<Person>>(new Uri("https://api.example.com/api/v1/people")));
}
protected T Get<T>(Uri uri)
{
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = "GET";
request.ContentType = "text/xml";
using (var response = (HttpWebResponse) request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
Debug.Assert(responseStream != null, "responseStream != null");
var serializer = new DataContractSerializer(typeof (T));
return (T) serializer.ReadObject(responseStream);
}
}
}
}
From your question, I assume you want to use JSON. For that you just have to set the appropiate ContentType on the request and use the DataContractJsonSerializer rather than DataContractSeralizer. Note that there are some issues with dates and DataContractJsonSerializer. The WCF rest service will automatically return XML if the contenttype is "text/xml" and JSON if it is "application/json".
Notice that the MVC application has no knowledge of the database, the database entities or its database context. In fact there is no database logic in the MVC application. You will have to pay close attention to security, because the user context is missing from the WCF rest services. But, that is a whole different discussion.
The way to think about this is that your MVC app now only knows about your service. It has no clue that there's a DAL behind it. Basically, consider the service your "Persistence" layer. So, now your MVC model must populate itself using the service. So, just like any other application would populate a service, that is how your model will populate itself. Then your controllers will use your model return your views.
That wasn't the nitty gritty you may be looking for, but there are plenty of resources out there on how to consume RESTful services in .NET. Check those out and get those populating your model. Then get your model to your view.

Resources