Java EE 6 authorization: restrict to owner - security

Suppose I have a simple model, such as "Record":
#Model
public class Record {
private Principal owner; // presume getter/setters as well
}
Then I want to have a simple EJB that controls creating and deleting records. For the sake of argument let's only worry about deleting:
#EJB
#Named
#Stateless
public class RecordMgr {
#PersistenceContext private EntityManager em;
public void delete(Record r) {
em.remove(r);
}
}
I want to restrict access to RecordMgr#delete(Record r) to administrators and the owner: in other words, admins and the people who created the object, and only them, can delete it. I don't see how to accomplish both of these with declarative security. What's the right way to approach this problem?

You cannot do that with declarative security, because there is no way to have connection between role in #RolesAllowed and user that created entity.
Only way is programmatic security and checking that user is creator of bean or Administrator, or both.
Only part where you could utilize declarative security is to list roles that are aloud to create such a record, and administrator role. After that it have to be programmatically checked further that current user's role is administrator or that current user created record. In any case whole logic of declarative security is then duplicated in programmatic security.

Related

swagger - annotation for permissions?

Is there any way to document the permissions required for a Request? If I have annotations like
[Authenticate]
[RequiredRole("Admin")]
[RequiredPermission("CanAccess")]
public object Delete(DeleteAppUser deleteUserRequest)
{
// ....
}
in my service class or alternatively for my RequestDTOs
[Authenticate]
[RequiredRole("Admin")]
[Route("/appusers/{AppUserId}", "DELETE", Summary = "Delete an application user identified by its ID.")]
public class DeleteAppUser : IReturn<AppUserDto>
{
// ....
}
Can I make this somehow available in the swagger-ui documentation for users of my API automatically or do I have to write it in the Notes like:
[Route("/appusers/{AppUserId}", "DELETE", Summary = "Delete an application user identified by its ID.", Notes="Requires an authenticated session and membership in the Admin role.")]
No Swaggers UI doesn't have a concept of roles or permissions. This information is displayed on ServiceStack's /metadata pages but to display it in Swagger's UI you'd need to add it to the API's text description.

MvcSiteMapProvider not picking up roles for menu

I am using MVC5, windows authentication, structuremap DI and custom role provider.
MvcSiteMapProvider for MVC5 is not picking up the roles to show menu based on user role. When security trimming is enabled it shows only menu items which do not have any roles attribute defined.
I have ActionFilterAttribute implemented and used on controller for authorization. Controller correctly redirects the user to unauthorized page based on roles but menu is not picking the role attributes to hide the menu.
Custom RoleProvider has implementation for GetRolesForUser and GetUsersInRole.
Any suggestion will be helpful.
Also want to know where to look for roles attributes in SiteMapNodeModel. I am thinking of customizing to look for permission in the HtmlHelper while building the menu.
Note: Same implementation is working fine in MVC4. Once upgraded to MVC5 and it does not work.
Thanks
MvcSiteMapProvider for MVC5 is not picking up the roles to show menu based on user role. When security trimming is enabled it shows only menu items which do not have any roles attribute defined.
As per the documentation, the roles attribute is not for use with MVC. It is for interop with ASP.NET pages.
It only functions when the security framework implements IPrincipal and IIdentity as Membership and Identity do.
I have ActionFilterAttribute implemented and used on controller for authorization. Controller correctly redirects the user to unauthorized page based on roles but menu is not picking the role attributes to hide the menu.
This is most likely your issue. Security trimming only looks for AuthorizeAttribute and subclasses of AuthorizeAttribute. If you have subclassed ActionFilterAttribute, it will not be used to hide links from navigation.
Of course, for the standard AuthorizeAttribute to work, you need to implement IPrincipal and IIdentity or use one of the pre-built security frameworks that does the same.
Alternatively, you could build your own IAclModule or ISiteMapNodeVisibilityProvider if you have completely custom security.
Also want to know where to look for roles attributes in SiteMapNodeModel. I am thinking of customizing to look for permission in the HtmlHelper while building the menu.
You would not need to look for roles from the SiteMapNodeModel. Instead, you should get the roles from the current context and make the changes to the menu templates in /Views/Shared/DisplayTemplates/ accordingly.
If you are using a framework that supports IPrincipal and IIdentity, you could just use:
#if (User.IsInRole("SomeRole"))
{
...
}
Also see the following:
ASP.NET MVC 5 Customise Bootstrap navbar based on User Role
Implementing Role Based Menu in ASP.NET MVC 4
If you want to get the current roles that are configured for an action method, you can build an extension method to read the roles from the current AuthorizeAttribute. Again, the roles attribute is only for interoperability with ASP.NET and should not be used for pure MVC, since it means you need to duplicate your roles on AuthorizeAttribute anyway.
public static class ControllerContextExtensions
{
public static IEnumerable<string> Roles(this ControllerContext controllerContext)
{
var controllerType = controllerContext.Controller.GetType();
var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
var actionName = controllerContext.RouteData.Values["action"] as string;
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
var authorizeAttribute = FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor)
.Where(f => typeof(AuthorizeAttribute).IsAssignableFrom(f.Instance.GetType()))
.Select(f => f.Instance as AuthorizeAttribute).FirstOrDefault();
string[] roles = { };
if (authorizeAttribute != null && authorizeAttribute.Roles.Length > 0)
{
roles = Array.ConvertAll(authorizeAttribute.Roles.Split(','), r => r.Trim());
}
return roles;
}
}
Usage
In view:
{ var roles = this.ViewContext.Controller.ControllerContext.Roles(); }
In controller:
var roles = this.ControllerContext.Roles();
To get the roles from the SiteMapNodeModel:
var siteMap = MvcSiteMapProvider.SiteMaps.Current;
var siteMapNode = siteMap.FindSiteMapNodeFromKey(SiteMapNodeModel.Key);
var roles = siteMapNode.Roles;

How to get dropwizard to accept all security roles when invoking a protected resource

I'm running the dropwizard example from:
https://github.com/dropwizard/dropwizard/tree/master/dropwizard-example
which includes an example how to protect a resource using http basic authentication.
In the example the user must belong to a specific role to access the resource:
#Path("/protected")
#Produces(MediaType.TEXT_PLAIN)
public class ProtectedResource {
#RolesAllowed("ADMIN")
#GET
public String showSecret(#Auth User user) {
return String.format("Hey there, %s. You know the secret! %d", user.getName(), user.getId());
}
}
I have a scenario where I want to enforce authentication, through the filter, but once authenticated I want all users to access the resource.
So my question is: how to indicate that all roles should be allowed to access the resource? I've tried replacing #RolesAllowed with #PermitAll but I'm getting:
java.lang.RuntimeException: Cannot inject Custom principal into unauthenticated request
! at io.dropwizard.auth.AuthValueFactoryProvider$AuthValueFactory.provide(AuthValueFactoryProvider.java:77) ~[dropwizard-auth-0.9.0-SNAPSHOT.jar:0.9.0-SNAPSHOT]
This was not supported in the first implementation of io.dropwizard.auth.AuthDynamicFeature. #PermitAll support has been introduced in v0.9.0-rc3.

ServiceStack Tenant resolution by domain

I am looking for an example implementation for resolving tenants in a multi-tenant ServiceStack API layer.
If you've got your Api host setup and you've providing an implementation of AppHostBase, you can override the Configure method like so;
public class ApiHost : AppHostBase
{
public ApiHost() : base("Service Name", typeof(ApiHost).Assembly) { }
public override void Configure(Funq.Container container)
{
//resolve your tenant here..
}
}
Now you probably want some code to resolve your tenant. Say you were doing this via subdomain, you want something like this;
string subdomain = HttpContext.Current.Request.Url.Host.Split('.')[0].ToLower();
You should probably perform some checks to ensure validity of the url too. Then just use your repository or DAL to resolve your tenant with a relevant query.
After that you need to decide how you're going to pass your tenant about to your services and such. Question for another time, probably :)

How to assign Permissions to site page dynamically when created

In Liferay when a site page is added, it is assigned VIEW permission automatically for Owner role, Guest role and Site Member role.
Is it possible to assign VIEW permissions dynamically to custom role when page is created instead of manually assigning VIEW permission from Manage-permission tab of the site-page?
One of the possible way is Using LayoutListener via hook
For this you need to create hook (portal properties) and override following property:
value.object.listener.com.liferay.portal.model.Layout
See the following example:
value.object.listener.com.liferay.portal.model.Layout=com.smb.mypermissions.hook.listeners.LayoutListener
Here LayoutListener is the custom class created under package com.smb.mypermissions.hook.listeners to override default LayoutListener.
Signature for this class: public class LayoutListener extends BaseModelListener<Layout>
Now override the method
public void onAfterCreate(Layout model)throws ModelListenerException
to assign permission to the role, use following one liner:
ResourcePermissionLocalServiceUtil.setResourcePermissions(
companyId, Layout.class.getName(),
ResourceConstants.SCOPE_INDIVIDUAL,
String.valueOf(primKey), role.getRoleId(),
new String[] {
ActionKeys.VIEW
});
where role can be obtained from RoleLocalServiceUtil and primkey is the page unique id i.e plid
long primKey = model.getPlid();
long companyId = model.getGroup().getCompanyId();
Role role = RoleLocalServiceUtil.fetchRole(companyId, "<Your Role name here>");

Resources