Use currently authorized user in resource attribute during create request - spring-security

I have entity which does have MyUser author; attribute. I use also this class in custom authorization process to create MyUserPrincipal instance. (I have taken inspiration from Callicoder blog post and repository.)
Snippet of logging procedure part:
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
#Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
// He I use myUserRepository, to load MyUser instance and than return MyUserPrincipal which implements OAuth2User, UserDetails...
}
}
Now I have repository for Book entity for example. Book can look like this:
#Entity
#Getters // project lombook magic here
#Setters
public class Book {
private MyUser author;
private String title;
}
I can create new resource using POST request to http://localhost/api/books with data like this:
{
"author":"api/authors/42",
"title":"stackoverflow forever"
}
My question: Is it possible to easily (without custom controller) make use of "authentication.principal.userId" from SecurityContext to fill in author ow newly created resource/entiry? I would like to forbid for user of my API to send author field at all.

Well, I don't know what you mean by "custom controller", but the #RestController behind your /api/books URI can make use of #AuthenticationPrincipal. Then you don't have to send in your author id anymore, if it is part of MyUserPrincipal.
#PostMapping("/api/books")
public SomeDTO saveBook(#AuthenticationPrincipal MyUserPrincipal principal) {
if (principal != null) { // user is logged in and not e.g. anonymous
// principal.getId(); use this to save your book
}
}

Related

Activity based Authorization in ASP.NET Core

We have an asp.net mvc application which I'm porting to aspnet core mvc.
In the old solution authentication is done using Windows authentication.
On top of that we have an "activity based authentication" (like http://ryankirkman.com/2013/01/31/activity-based-authorization.html); a user is connected to roles and the roles are connected to rights. The users roles and corresponding rights is stored in a separate application that serves as authorization service for our application and handful of other systems.
A query to the authorization service api for the rights of user "Jon Doe" would get a response like this:
{
Email:"Jon.Doe#acme.com",
FirstName:"Jon",
LastName:"Doe",
Resources:
[
"CanAccessWebApplication",
"CanCopyAppointment",
"CanEditAppointment",
"CanEditContact",
"CanSaveContact"
...
]
Alias:"1234567",
UserId:"1234"
}
In our current application these rights are checked using attributes (that we have implemented our selves) on the controller methods:
public ContactController
{
[ActionUserAccess("CanSaveContact")]
public ActionResult SaveContact
{
...
}
}
The current legacy implementation of the ActionUserAccessAttribute filter looks like this:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class ActionUserAccessAttribute : ActionFilterAttribute
{
private readonly string _accessRight;
public ActionUserAccessAttribute(string accessRight)
{
_accessRight = accessRight;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
throw new InvalidOperationException("ActionUserAccessAttribute can not be used for controllers or actions configured for anonymous access");
}
base.OnActionExecuting(filterContext);
var securityService = ContainerResolver.Container.GetInstance<ISecurityService>();
var hasResource = securityService.HasAccess(_accessRight);
if (!hasResource)
{
filterContext.Result =
new HttpStatusCodeResult(
403,
string.Format(
"User {0} is not authorized to access the resource:'{1}' ",
filterContext.HttpContext.User.Identity.Name,
_accessRight));
}
}
}
}
Porting the attribute/filter to aspnetcore seems quite straightforward, but according to this answer https://stackoverflow.com/a/31465227/1257728 by "asp.net security person" #blowdart we shouldn't.
If not porting the custom filter to aspnetcore, what would be the best fit to implement here?
Maybe we could use the Role based authentication https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?
We could create a middleware that populates the users access rights from the authorization service api and flatten the rights and add them as ClaimTypes.Role to the users' ClaimsIdentity ? Then we would use on the method above like:
[Authorize(Roles = "CanSaveContact")]
public ActionResult Save()
The misfit of this approach is that this is not really about roles, but more about the access rights.
I've also looked at the Policy based authorization:
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies
Which could look like this in the controller:
[Authorize(Policy = "CanSaveContact")]
public ActionResult Save()
But as I read the code in microsoft's policy based example above I would then have to add all available access rights that exists in the security service api as policies in the ConfigureService method of the Startup class to be able to use them. I think seems awkward (pseudo code):
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
IEnumerable<string> allAccessRights = _securtiyService.GetAllAccessRights();
services.AddAuthorization(options =>
{
foreach(var accessRight in allAccessRights)
{
options.AddPolicy(accessRight, policy => policy.Requirements.Add(new AccessRightRequirement(accessRight));
}
});
services.AddSingleton<IAuthorizationHandler, AccessRightHandler>();
}
The AccessRightHandler would then be resposible to validate the access right for the user. Writing an AccessRightHandler is ok, but it seems unnecessary to have to add all the rights as policies.
What would be the best approach to implement this kind of authorization in our aspnetcore application?
Great question, and I think a number of people would have the same problem upgrading to ASP.NET Core.
Barry Dorrans (#blowdart) is absolutely correct, you shouldn't write your own custom authorize attributes - Authorization in ASP.NET Core has been greatly improved, and you can definitely mould it to your needs.
It would of course greatly depend on your current application, and what roles do you have, so I'll make some assumptions based on the snippets you provided above.
Before I start, I REALLY recommend you read through the new Authorization docs for ASP.NET Core, as well as Barry Dorran's Authorization workshop on GitHub. I highly recommend you go through the latter, and he has a .NET Core 2.0 branch there as well.
Depending how you want to implement it, you could either go with Claims based authorization, or go resource based.
Looking at your roles, it seems like Resource based auth could actually work great in your case!
For example:
Identify possible operations (the operation Name is to be picked up from your Resources):
public static class Operations
{
public static OperationAuthorizationRequirement Access = new OperationAuthorizationRequirement { Name = "Access" };
public static OperationAuthorizationRequirement Copy = new OperationAuthorizationRequirement { Name = "Copy" };
public static OperationAuthorizationRequirement Edit = new OperationAuthorizationRequirement { Name = "Edit" };
public static OperationAuthorizationRequirement Save = new OperationAuthorizationRequirement { Name = "Save" };
public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = "Delete" };
}
Create a base resource authorization handler:
public abstract class BaseResourceAuthorizationHandler<TResource> : AuthorizationHandler<OperationAuthorizationRequirement, TResource>
{
private readonly string _resourceType;
public BaseResourceAuthorizationHandler(string resourceType)
{
_resourceType = resourceType;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, TResource resource)
{
if (context.User.HasClaim("Resources", $"Can{requirement.Name}{_resourceType}"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Implement specific resource based handlers. The resources are binding objects in your application to entities in your Resources. This class will be the glue between your current resource roles, the Operations, and the authorization system in ASP.NET Core. These can also be extended to add extra logic for any specific resource types/operations
For example, for Appointments:
public class AppointmentAuthorizationHandler : BaseResourceAuthorizationHandler<Appointment>
{
public AppointmentAuthorizationHandler() : base("Appointment") { }
}
Which you then register:
services.AddSingleton<IAuthorizationHandler, AppointmentAuthorizationHandler>();
Then in your controllers:
public class AppointmentsController : Controller
{
IAppointmentsRepository _appointmentsRepository;
IAuthorizationService _authorizationService;
public AppointmentsController(IAppointmentsRepository appointmentsRepository,
IAuthorizationService authorizationService)
{
_appointmentsRepository = appointmentsRepository;
_authorizationService = authorizationService;
}
public IActionResult Edit(int id)
{
var appointment = _appointmentsRepository.Get(id);
if (appointment == null)
{
return new NotFoundResult();
}
if (!(await _authorizationService.AuthorizeAsync(User, appointment, Operations.Edit)))
{
return new ChallengeResult();
}
return View(appointment);
}
}
You can also do the same in views, to check whether the user is allowed to see the Edit button, for example:
#using Microsoft.AspNetCore.Authorization
#model IEnumerable<Appointment>
#inject IAuthorizationService AuthorizationService
<h1>Document Library</h1>
#foreach (var appointment in Model)
{
if (await AuthorizationService.AuthorizeAsync(User, appointment, Operations.Edit))
{
<p>#Html.ActionLink("Appointment #" + appointment.Id, "Edit", new { id = appointment.Id })</p>
}
}
P.S. Just to add a note - yes, you lose the ability to filter by attributes, but in the end it's better this way. First and foremost - you move away from String based roles, you request permissions based on an operation type and resource type. Secondly, you can handle permissions in a much better (and intelligent way), as well as combine multiple permission checks.
It looks more complex, but it's also MUCH more powerful :)
Going to play the devil's advocate here, and suggest an alternative to my other answer - this could be a simpler option based on #mortb's request, and could fit some people that are migrating from their current systems.
Based on your situation, the Policy based auth really wouldn't fit your usecase - it's a more powerful option, you're not really using any of it, other than checking for the existence of a Resource string from your API.
On the other hand, I wouldn't discard the Roles approach. The resource list you get from the external API isn't strictly resources, but at the same time it maps quite perfectly to your needs. At the end of the day, all you're trying to do is to check whether the user has one (or more) Resource access permissions for a specific request.
Like you mentioned on your post, you'd have to extend your authorization to populate the roles from your external API. Don't forget that your ClaimsIdentity has a RoleClaimType property, which marks the type of the claim used to store the roles. It'll usually be set to ClaimTypes.Role, but not always.
You could even go ahead, and create custom auth attributes, not unlike this:
public class AuthorizeAccessAttribute : AuthorizeAttribute
{
public AuthorizeAccessAttribute(string entity)
{
Roles = "CanAccess" + entity;
}
}
public class AuthorizeEditAttribute : AuthorizeAttribute
{
public AuthorizeEditAttribute(string entity)
{
Roles = "CanEdit" + entity;
}
}
So you could use it as follows:
[AuthorizeEdit("Appointment")]
public IActionResult Edit(int id)
{
return View();
}

StackOverflowException in spring-data-jpa app with spring-security AuditorAware

I have a really nasty StackOverflowException in my spring backend, that I need help with. This is not going to be solved easily. I really hope to find some help here.
Most parts of my backend work. I can query my REST interface for models, they are nicely returned by spring-hateoas, GET, PUT and POST operations work. But one exception: When I try to update an existing DelegationModel, then I run into an endless StackOverflowException.
Here is my DelegetionModel.java class. Please mark, that delegation model actually doesn't have any property annotated with #CreatedBy!
#Entity
#Data
#NoArgsConstructor
#RequiredArgsConstructor(suppressConstructorProperties = true) //BUGFIX: https://jira.spring.io/browse/DATAREST-884
#EntityListeners(AuditingEntityListener.class) // this is necessary so that UpdatedAt and CreatedAt are handled.
#Table(name = "delegations")
public class DelegationModel {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
/** Area that this delegation is in */
#NonNull
#NotNull
#ManyToOne
public AreaModel area;
/** reference to delegee that delegated his vote */
#NonNull
#NotNull
#ManyToOne
public UserModel fromUser;
/** reference to proxy that receives the delegation */
#NonNull
#NotNull
#ManyToOne
public UserModel toProxy;
#CreatedDate
#NotNull
public Date createdAt = new Date();
#LastModifiedDate
#NotNull
public Date updatedAt = new Date();
}
As described in the Spring-data-jpa doc I implemented the necessary AuditorAware interface, which loads the UserModel from the SQL DB. I would have expected that this AuditorAware interface is only called for models that have a field annotated with #CreatedBy.
#Component
public class LiquidoAuditorAware implements AuditorAware<UserModel> {
Logger log = LoggerFactory.getLogger(this.getClass()); // Simple Logging Facade 4 Java
#Autowired
UserRepo userRepo;
#Override
public UserModel getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
log.warn("Cannot getCurrentAuditor. No one is currently authenticated");
return null;
}
User principal = (org.springframework.security.core.userdetails.User) authentication.getPrincipal();
UserModel currentlyLoggedInUser = userRepo.findByEmail(principal.getUsername()); // <<<<======= (!)
return currentlyLoggedInUser;
} catch (Exception e) {
log.error("Cannot getCurrentAuditor: "+e);
return null;
}
}
}
Now I update a DelegationModel in my UserRestController. The functional "Scrum User Story" here is:
As a user I want to be able to store a delegation so that I can forward my right to vote to my proxy.
#RestController
#RequestMapping("/liquido/v2/users")
public class UserRestController {
[...]
#RequestMapping(value = "/saveProxy", method = PUT, consumes="application/json")
#ResponseStatus(HttpStatus.CREATED)
public #ResponseBody String saveProxy(
#RequestBody Resource<DelegationModel> delegationResource,
//PersistentEntityResourceAssembler resourceAssembler,
Principal principal) throws BindException
{
[...]
DelegationModel result = delegationRepo.save(existingDelegation);
[...]
}
[...]
}
For some reason, that I cannot see, this actualy calls the AuditorAware implementation above. The problem is now, that my LqiuidoAuditorAware implementation is called again and again in and endless loop. It seems that the query for the UserModel inside LiquidoAuditorAware.java calls the LiquidoAuditorAware again. (Which is unusual, because that is only a read operation from the DB.)
Here is the full ThreadDump as a Gist
All the code can by found in this github repo
I'd really apriciate any help here. I am searching in the dark :-)
The reason for the behavior you see is that the AuditorAware implementation is called from within a JPA #PrePersist/#PreUpdate callback. You now issue a query by calling findByEmail(…), which triggers the dirty-detection again, which in turn causes the flushing to be triggered and thus the invocation of the callbacks.
The recommended workaround is to keep an instance of the UserModel inside the Spring Security User implementation (by looking it up when the UserDetailsService looks up the instance on authentication), so that you don't need an extra database query.
Another (less recommended) workaround could be to inject an EntityManager into the AuditorAware implementation, call setFlushMode(FlushModeType.COMMIT) before the query execution and reset it to FlushModeType.AUTO after that, so that the flush will not be triggered for the query execution.

Injecting ParseUser object to Controller

I'm trying to use parse's .net client in an mvc web application.
and couldn't find a proper way to inject ParseObject, ParseUser and ParseUser.CurrentUser
what is the nice way of injecting static objects?
web app has a Forms authentication setup.
and ioc container register components or services LifestylePerWebRequest()
my problem occured when I want to update the user object,
only if the ParseUser.CurrentUser logged in we can update. (https://parse.com/docs/dotnet_guide#users-security)
but this is a static object and I get the latest signed in user...
now I'm thinking to create a user2 table in parse and keep all profile data in there...
Is there a better way to go?
public async Task<bool> UpdateUser(string id, string name, string surname)
{
//var user = ParseUser.CurrentUser;
var user = await ParseUser.Query.GetAsync(id);
if (user == null) return await Task.FromResult(false);
user.Name = name;
user.Surname = surname;
await user.SaveAsync();
return await Task.FromResult(true);
}
what is the nice way of injecting static objects?
You hide them behind an application-defined abstraction. You define a narrow interface that describes the functionality that your application needs (and ideally without the interface leaking the external framework). For instance:
public interface IUserRepository
{
// Throws an exception on failure.
void UpdateUser(string id, string name, string surname);
}
Now you can hide the static class behind an implementation of IUserRepository:
public class ParseUserRepository : IUserRepository
{
public void UpdateUser(string id, string name, string surname)
{
// call the static Parse functionality.
}
}

Strategy to guard against malicious data changes

Looking for ideas to guard against malicious data changes: userA manipulating (editing or deleting) data that belongs to userB. Since we are creating entities on the client, we need to assign them (or at least some of them) to the authenticated user.
For example:
var newItem = ds.createNewItem();
newItem.OwnerId(22); //this is the problem that I see.
newItem.Name("New Item");
newItem.Description("I just changed your item!");
... //and so on
ds.saveChanges();
Assuming we know the identity of the user calling SaveChanges on our API, how do we validate our entities (new or modified) against this user?
The first thought that comes to mind is to subclass EFContextProvider, override BeforeSaveEntity and examine the entities OwnerId property against the identity of our user. For example:
if (entityInfo.Entity.GetType() == typeof(Item)
&& (entityInfo.EntityState == EntityState.Added
|| entityInfo.EntityState == EntityState.Modified)
&& ((Item)entityInfo.Entity).OwnerId != _currentUserId) {
return false
... //and so on
If using this approach, does it make sense to establish _currentUserId in the constructor of our new EFContextProvider class?
An ideas or perhaps a better way to approach this problem?
I think you are on the right track. I've been noodling this myself and have gone down much the same path.
Let's assume you've handled authentication and there's an IPrincipal available. You've got yourself a custom IIdentity too (call it AppIdentity) where you can stash the UserId for the authenticated user.
The Web Api's base ApiController class makes the ambient IPrincipal available via its User property. We will leverage that in your custom Breeze Web Api controller which might begin like this:
[Authorize]
[JsonFormatter, ODataActionFilter]
public class BreezeApiController : ApiController
{
private readonly AppContextProvider _context;
public BreezeApiController() {
// pass 'User' IPrincipal to the context ctor
_context = new AppContextProvider(User);
}
...
// one of the Query action methods
[HttpGet]
public IQueryable<Foo> Foos() {
return _context.Foos
}
...
Your custom EFContextProvider might begin like this:
public class AppContextProvider : EFContextProvider<AppDbContext>
{
public AppContextProvider(IPrincipal user)
{
UserId = ((AppIdentity) user.Identity).UserId;
}
public int UserId { get; private set; }
...
Now you probably want to prevent UserB's entities from being seen by UserA. So instead of allowing every Foo to go out the door, your custom EFContextProvider could filter accordingly.
public DbQuery Foos
{
get
{
// Here the 'Context' is your EF DbContext
return (DbQuery) Context.Foos
.Where(f => f.UserId == UserId);
}
}
Looking back at the controller, we see that its Foos GET action method is oblivious to the filter ... as it should be. We want our controllers to be light and move the business logic to the custom EFContextProvider and its helpers.
Finally, a highly simplified, general purpose BeforeSaveEntity could look like this:
private bool BeforeSaveEntity(EntityInfo info)
{
var entity = info.Entity;
if (info.EntityState == EntityState.Added)
{
entity.UserId = UserId;
return true;
}
return UserId == entity.UserId || throwCannotSaveEntityForThisUser();
}
...
private bool throwCannotSaveEntityForThisUser()
{
throw new SecurityException("Unauthorized user");
}
Notice that the custom context provider on the server is responsible for setting the UserId of added entities. We wouldn't trust the client to do that anyway. And of course it is responsible for verifying the UserId of modified and deleted entities.
Hope this helps. Remember, this is only a sketch. The real deal would have greater sophistication and be refactored into helpers.

Struts2 - Implementing ModelDriven - Create an interceptor that accesses the model properties

I'm relatively new to Struts2.
I've started using ModelDriven to reduce overhead in development.
I wanted to write an interface to modify a property before it gets to the action but I don't see how you can access the properties of a class that implements ModelDriven for the Model.
I can see how things like validate() can work as they are in the actual action class.
I changed the design to encapsulate the logic behind the service anyways but still would like to know if this is possible.
We're doing everything by ajax/json so I find modeldriven helps quite a lot - not sure if there is a better alternative though!
Edit - code example:
Trying to replace a message with a message in a template to use in an email body.
public class EmailActionImpl implements EmailAction {
private Email email=new Email();
private EmailService emailService;
public Email getModel(){
return email;
}
[... getters and setters ...]
public String execute(){
logger.info("Email action is sendind an email...");
try{
emailService.sendNewMail(email);
}catch(Exception e){
logger.error("Email not sent: " + e.getMessage());
return "failure";
}
return "success";
}
}
Email model something like this
#Entity
#Table(name="email")
public class Email {
private Long id;
private String from;
private String to;
private String message;
private String templateType;
[...]
}
I would like an interceptor preprocessor to replace email.message.
Should look something like this but action.getMessage/setMessage aren't available.
public class SimpleInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
EmailAction action = (EmailAction)invocation.getAction();
action.setMessage(MessageTemplateFactoryImpl(action.getMessage(), action.getTemplateType());
return invocation.invoke();
}
}
If you still want to implement an interceptor to work on a particular set of models then you will check if the Action implements ModelDriven. Via reflection (or Apache bean utils) you can derive the particular model in question, to determine if your interceptor applies and then act on it accordingly.

Resources