after entity update entity framework still gives me old info? - c#

i have a strange problem, i'm building a Single Page Application with AngularJs and Web API in the server, I'm using Entity framework, i use Code First approach everything is going good, until i want to implement Change password for a user, the updating goes right, but when the user tries to reconnect with his new credentials, entity framework gather the old password !!
public class AuthenticationFilter : ActionFilterAttribute
{
private MyDbRepository repo;
public KhbyraAuthenticationFilter()
{
repo = new MyDbRepository(new MyDbContext());
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
//Login code accessing database by repo object !!
//Here where Entity framework gather old info
}
}
Thats the login Action in SecurityController
[EnableCors("*", "*", "*")]
public class SecurityController : BaseApiController
{
//other actions
[AuthenticationFilter]
[Route("Token")]
[HttpPost]
public IHttpActionResult Login([FromBody]User user)
{
if (user == null)
{
Unauthorized();
}
return Ok();
}
}
Edit
this is where the change pass
[EnableCors("*", "*", "*")]
[KhbyraAuthorizeAttribute]
public class UserController : BaseApiController
{
private int CurrentUserID;
public UserController():base(new KhbyraRepository(new KhbyraContext()))
{
}
//.. other actions
//..
[Route("User/ChangePassword")]
[HttpPost]
public IHttpActionResult ChangePassword([FromBody]ChangePasswordModel model)
{
// here where i save the new password
}

You must instantiate a new repository inside the OnActionExecuting method in AuthenticationFilter. The filter is a singleton so you're keeping one DbContext instance that has the old values cached.
public class AuthenticationFilter : ActionFilterAttribute
{
public KhbyraAuthenticationFilter()
{
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
using(var repo = new MyDbRepository(new MyDbContext()))
{
//Login code accessing database by repo object.
}
}
}
This also makes the code thread safe (which it isn't currently).

Related

Ninject to Simple Injector: Register ActionFilter with Controller Attribute (with params)

I have an WebApi application that uses Simple Injector and I'm trying to configure a particular filter with controller attribute (with parameters). I have this configuration working in another project that uses Ninject, but I don't know how to do this on Simple Injector.
public enum UserType {
Director,
Developer,
Leader
}
My controller:
[RequiresAtLeastOneOfUserTypes(UserType.Developer, UserType.Leader)]
public class MyController : Controller
{
...
}
My Attribute:
public sealed class RequiresAtLeastOneOfUserTypesAttribute : Attribute
{
public UserType[] TypesToBeVerified { get; set; }
public RequiresAtLeastOneOfUserTypesAttribute(params UserType[] typesToBeVerified)
{
TypesToBeVerified = typesToBeVerified;
}
}
My Filter:
public class RequiresAtLeastOneOfUserTypesFilter : IActionFilter
{
private readonly IUser _user;
private readonly UserType[] _typesToBeVerified;
protected RequiresAtLeastOneOfUserTypesFilter(IUser user, params UserType[] typesToBeVerified)
{
_user = user;
_typesToBeVerified = typesToBeVerified;
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
bool authorized = _user.HasAtLeastOneOfTypes(_typesToBeVerified);
if (!authorized)
{
throw new ForbiddenUserException();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// do nothing
}
}
And finally my Ninject configuration:
this.BindFilter<RequiresAtLeastOneOfUserTypesFilter>(FilterScope.Controller, 0)
.WhenControllerHas<RequiresAtLeastOneOfUserTypesAttribute>()
.WithConstructorArgumentFromControllerAttribute<RequiresAtLeastOneOfUserTypesAttribute>(
"typesToBeVerified",
attribute => attribute.typesToBeVerified);
My question is: How can I do this configuration using Simple Injector?
The Simple Injector Web API integration packages don't contain an integration feature for action filters as Ninject's integration package does. But such integration can be built in a few lines of code.
There are a few options here. The first option is to revert to resolving services directly from inside your action filter, as demonstrated inside the documentation. This approach is fine when you have a single filter class, but isn't the cleanest approach, and would force you to make changes to your already created filter attribute.
As a second option you can, therefore, create a action filter proxy class, that is able to forward the call to your real filter class, which can than be resolved by Simple Injector:
public class ActionFilterProxy<T> : IActionFilter
where T : IActionFilter
{
public ActionFilterProxy(Container container) => _container = container;
public void OnActionExecuting(ActionExecutingContext filterContext) =>
_container.GetInstance<T>().OnActionExecuting(filterContext);
public void OnActionExecuted(ActionExecutedContext filterContext) =>
_container.GetInstance<T>().OnActionExecuted(filterContext);
}
Using this proxy, you can make the following configuration:
GlobalConfiguration.Configuration.Filters.Add(
new ActionFilterProxy<RequiresAtLeastOneOfUserTypesFilter>(container));
container.Register<RequiresAtLeastOneOfUserTypesFilter>();
This still forces you to make a change to RequiresAtLeastOneOfUserTypesFilter, because Simple Injector can't provide the attribute's information (the UserType[]) to RequiresAtLeastOneOfUserTypesFilter's constructor. Instead,you can change RequiresAtLeastOneOfUserTypesFilter to the following:
public class RequiresAtLeastOneOfUserTypesFilter : IActionFilter
{
private readonly IUser _user;
public RequiresAtLeastOneOfUserTypesFilter(IUser user) => _user = user;
public void OnActionExecuting(ActionExecutingContext filterContext)
{
// Get the attribute from the controller here
var attribute = filterContext.ActionDescriptor.ControllerDescriptor
.GetCustomAttribute<RequiresAtLeastOneOfUserTypesAttribute>();
bool authorized = _user.HasAtLeastOneOfTypes(attribute.TypesToBeVerified);
if (!authorized)
{
throw new ForbiddenUserException();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
}
A third option to use is the one referred to in the documentation, which is described in this blog post, which discusses a model where you place your filters behind an application-specific abstraction and allow them to be Auto-Registered. It uses the a similar proxy approach. This method is useful when you have multiple/many filters that need to be applied (where their order of execution is irrelevant).

how can i get model object in exceptionFilter Asp.NetCore?

I am working with a WEB application in ASP .NET Core 2.0 where I have a custom ExceptionAttribute filter that inherits from ExceptionFilterAttribute.
How can I access the Model object passed to a action in POST call.
The mentioned method is passed a ExceptionContext but I could not find an easy and reliable way to get Model object from it and pass to ViewResult.
The filter I have, looks like the following:
public class ApiCallExceptionAttribute: ExceptionFilterAttribute
{
private readonly IModelMetadataProvider _modelMetadataProvider;
public ApiCallExceptionAttribute(
IModelMetadataProvider modelMetadataProvider)
{
_modelMetadataProvider = modelMetadataProvider;
}
public override void OnException(ExceptionContext context)
{
//how can i accesss model object here and pass to ViewResult
result.ViewData = new ViewDataDictionary(_modelMetadataProvider,context.ModelState);
context.Result = result;
}
}
and the controller looks like the following:
[HttpPost]
[ServiceFilter(typeof(ApiCallExceptionAttribute))]
public async Task<IActionResult> Activation(ActivationViewModel model)
{
//throw exception in controller content
}
Can't find any easy way to do that.
The approach I would take is to implement IActionFilter also on your class.
Read the model's info in onActionExecuting() and store it in HTTPContext.Items.
Then read it from HttpContext.Items when there is an exception.
Resist the urge to store this information as a private field in your class because MVC do not create a new instance of it's filters for every request!
public class LogExceptionFilterAttribute : Attribute, IExceptionFilter, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Items["ActionArguments"] = context.ActionArguments;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnException(ExceptionContext context)
{
var model = context.HttpContext.Items["ActionArguments"];
}
}

How to get the authenticated user from a separate class library in .Net Core

I have an MVC core app that references a .NET Core class library. All of the data access and business logic is in the class library. How can I can I access the authenticated user from the class library?
In the past using .NET Framework you could use
string UserName = System.Web.HttpContext.Current.User.Identity.Name
To get the username from inside a method in the class library. In .NET Core, it appears that HttpContext no longer has a Current or User property.
Here's a simple use case. Suppose I have a data entity and service that "stamps" entities with the date and username before saving them to the database.
These would be in the external class library:
public interface IAuditable{
DateTime CreateDate{get;set;}
string UserName{get;set;}
}
public class MyEntity:IAuditable{
public int ID{get;set;}
public string Name{get;set;}
public string Information{get;set;}
}
public static class Auditor{
public static IAuditable Stamp(IAuditable model){
model.CreateDate=DateTime.UtcNow;
model.CreatedBy=System.Web.HttpContext.Current.User.Identity.Name;
return model;
}
}
public sealed class MyService:IDisposable{
MyDb db=new MyDb();
public async Task<int> Create(MyEntity model){
Auditor.Stamp(model);
db.MyEntities.Add(model);
return await db.SaveAsync();
}
public void Dispose(){
db.Dispose();
}
}
Then in my MVC controller I'd have a post action that calls the service:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(MyEntity model)
{
await service.Create(model);
return RedirectToAction("Index")
}
I would like a way to replace that line in Auditor.Stamp since there's no HttpContext.Current in .NET Core, apparently.
This post gives an example of how to get the username in Core:
public class UserResolverService
{
private readonly IHttpContextAccessor _context;
public UserResolverService(IHttpContextAccessor context)
{
_context = context;
}
public string GetUser()
{
return await _context.HttpContext.User?.Identity?.Name;
}
}
But I'm left with another version of the same problem: how do I get a IHttpContextAccessor object from inside the class library?
Most of my search results only deal with the question of how to get the User name from inside an MVC controller method. In the past I've passed a User object into every method for every service but that's a lot of extra typing--I'd rather have something I can type once (maybe inside Startup?) And then forget about it.
I do want something I can mock for unit tests, but honestly I think wrapping System.Web.HttpContext.Current.User.Identity.Name in something that can be mocked was pretty darn easy.
The same flexibility still exists in this version.
Inject the IHttpContextAccessor and you have access to what you need.
refactor the static Auditor to be more injectable
public interface IAuditor {
IAuditable Stamp(IAuditable model);
}
public class Auditor : IAuditor {
private readonly IHttpContextAccessor accessor;
public Auditor(IHttpContextAccessor accessor) {
this.accessor = accessor;
}
public IAuditable Stamp(IAuditable model){
model.CreateDate = DateTime.UtcNow;
model.CreatedBy = accessor.HttpContext.User?.Identity?.Name;
return model;
}
}
The service would then depend on the new abstraction
public interface IMyService : IDisposable {
Task<int> Create(MyEntity model);
}
public sealed class MyService : IMyService {
MyDb db = new MyDb();
private readonly IAuditor auditor;
public MyService(IAuditor auditor) {
this.auditor = auditor;
}
public async Task<int> Create(MyEntity model) {
auditor.Stamp(model);
db.MyEntities.Add(model);
return await db.SaveAsync();
}
public void Dispose() {
db.Dispose();
}
}
You should really also be injecting the MyDb as well but that is outside of the scope of the current question.
Lastly you configure you library to be able to setup the services during start up
public static IServiceCollection AddMyLibrary(this IServiceCollection services) {
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuditor, Auditor>();
services.AddScoped<IMyService, MyService>();
//...add other services as needed
return services.
}
and then you can call it in Start up from the root project
public void ConfigureServices(IServiceCollection services) {
//...
services.AddMyLibrary();
//...
}
With these abstraction and using DI app parts are decoupled and can be tested in isolation.

How to implement Permission Based Access Control with Asp.Net Core

I am trying to implement permission based access control with aspnet core. For dynamically managing user roles and permissions(create_product, delete_product etc.), they are stored in the database. Data Model is like http://i.stack.imgur.com/CHMPE.png
Before aspnet core (in MVC 5) i was using custom AuthorizeAttribute like below to handle the issue:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
private readonly string _permissionName { get; set; }
[Inject]
public IAccessControlService _accessControlService { get; set; }
public CustomAuthorizeAttribute(string permissionName = "")
{
_permissionName = permissionName;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
var user = _accessControlService.GetUser();
if (PermissionName != "" && !user.HasPermission(_permissionName))
{
// set error result
filterContext.HttpContext.Response.StatusCode = 403;
return;
}
filterContext.HttpContext.Items["CUSTOM_USER"] = user;
}
}
Then i was using it in action method like below:
[HttpGet]
[CustomAuthorize(PermissionEnum.PERSON_LIST)]
public ActionResult Index(PersonListQuery query){ }
Additionally, i was using HttpContext.Items["CUSTOM_USER"] in views to show or hide html part:
#if (CurrentUser.HasPermission("<Permission Name>"))
{
}
When i decided to switch aspnet core, all my plan was failed. Because there was no virtual OnAuthorization method in the AuthorizeAttribute. I tried some ways to solve problem. Those are below:
Using new policy based authorization(i think it is not suitable for
my scenerio)
Using custom AuthorizeAttribute and AuthorizationFilter(i read this
post https://stackoverflow.com/a/35863514/5426333 but i couldn’t change it properly)
Using custom middleware(how to get AuthorizeAttribute of current
action?)
Using ActionFilter(is it correct for security purpose?)
I couldn’t decide which way is the best for my scenerio and how to implement it.
First question: Is MVC5 implementation bad practice?
Second question: Do you have any suggest to implement aspnet core?
Based on the comments, here an example on how to use the policy based authorization:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionRequirement(PermissionEnum permission)
{
Permission = permission;
}
public PermissionEnum Permission { get; }
}
public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IUserPermissionsRepository permissionRepository;
public PermissionHandler(IUserPermissionsRepository permissionRepository)
{
if(permissionRepository == null)
throw new ArgumentNullException(nameof(permissionRepository));
this.permissionRepository = permissionRepository;
}
protected override void Handle(AuthorizationContext context, PermissionRequirement requirement)
{
if(context.User == null)
{
// no user authorizedd. Alternatively call context.Fail() to ensure a failure
// as another handler for this requirement may succeed
return null;
}
bool hasPermission = permissionRepository.CheckPermissionForUser(context.User, requirement.Permission);
if (hasPermission)
{
context.Succeed(requirement);
}
}
}
And register it in your Startup class:
services.AddAuthorization(options =>
{
UserDbContext context = ...;
foreach(var permission in context.Permissions)
{
// assuming .Permission is enum
options.AddPolicy(permission.Permission.ToString(),
policy => policy.Requirements.Add(new PermissionRequirement(permission.Permission)));
}
});
// Register it as scope, because it uses Repository that probably uses dbcontext
services.AddScope<IAuthorizationHandler, PermissionHandler>();
And finally in the controller
[HttpGet]
[Authorize(Policy = PermissionEnum.PERSON_LIST.ToString())]
public ActionResult Index(PersonListQuery query)
{
...
}
The advantage of this solution is that you can also have multiple handlers for a requirement, i.e. if first one succeed the second handler can determine it's a fail and you can use it with resource based authorization with little extra effort.
The policy based approach is the preferred way to do it by the ASP.NET Core team.
From blowdart:
We don't want you writing custom authorize attributes. If you need to do that we've done something wrong. Instead you should be writing authorization requirements.
I had same requirement and i have done it as below and it works fine for me. I am using .Net Core 2.0 Webapi
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Method
, AllowMultiple = true
, Inherited = true)]
public class CheckAccessAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private string[] _permission;
public CheckAccessAttribute(params string[] permission)
{
_permission = permission;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = context.HttpContext.User;
if (!user.Identity.IsAuthenticated)
{
return;
}
IRepository service =
(IRepositoryWrapper)context.HttpContext.RequestServices.GetService(typeof(IRepository));
var success = service.CheckAccess(userName, _permission.ToList());
if (!success)
{
context.Result = JsonFormatter.GetErrorJsonObject(
CommonResource.error_unauthorized,
StatusCodeEnum.Forbidden);
return;
}
return;
}
}
In Controller use it like below
[HttpPost]
[CheckAccess(Permission.CreateGroup)]
public JsonResult POST([FromBody]Group group)
{
// your code api code here.
}
For a solution that doesn't require you to add a policy for each permission see my answer for another question.
It lets you decorate your Controllers and Actions with any custom attributes you wish, and access them in your AuthorizationHandler.

Early returning from a base web api controller

I have this controller:
public class TestController : ODataControllerBase<TestModel, Test>
{
public IEnumerable<TestModel> Get()
{
var results = Tests.Get();
return new PageResult<TestModel>(results);
}
}
Which has this base controller:
public abstract class ODataControllerBase<TModel, TEntity> : ODataController
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
if (!HttpContext.Current.User.IsInRole("Test"))
{
base.Ok(new List<TModel>());
}
}
}
This base is inherited from multiple controllers and it all works.
Except the part where it checks if the user is in the right role. When the user is not it goes in the base.Ok(new List<TModel>()); part, but thats it. It skips by and then continues with the Get() action and returns the results anyway.
How can I make sure that the base controller set the response context and prevents any further actions from running?

Categories

Resources