CQ5 querying node which has access for a particular user - aem

In geometrix site if I need to get the results for page which has only user X has access
Following query pulls all the records, but I need to restrict for only X user
http://myserver.com:4502/bin/querybuilder.feed?orderby=%40jcr%3acontent%2fjcr%3acreated&orderby.index=true&orderby.sort=desc&path=%2fcontent%2fgeometrixx%2fen&type=cq%3aPage
What are the parameters that need to be included in the url

ACL mechanism, responsible for authorization (deciding if a user has access to a resource) is quite complicated. Privileges are inherited from ancestor nodes, there are groups (and a group may be member of another group), etc. That's why it is not possible to write a query that will list nodes available for a particular user.
However, you may create a resource resolver working on behalf of any user and use it to query the repository - you'll get only resources available to the resource resolver "owner". Example:
final String user = "my-user";
final String query = "SELECT * FROM [cq:Page] AS s WHERE ISDESCENDANTNODE([/content/geometrixx/en]) ORDER BY [jcr:created]";
Map<String, Object> authInfo = new HashMap<String, Object>();
authInfo.put(ResourceResolverFactory.USER_IMPERSONATION, user);
ResourceResolver resolver = resourceResolverFactory.getAdministrativeResourceResolver(authInfo);
Iterator<Resource> result = resolver.findResources(query, "JCR-SQL2");

Related

Fetch user identities from TFS using C# REST API

In OM API as we used to fetch user identities and we can put search on multiple values for example:
when we set IdentitySearchFilter = IdentitySearchFilter.DisplayName we were able to give multiple user display names to fetch multiple users, how can we achieve this in C# REST API, because it is accepting only one display name to fetch its user?
IdentitiesCollection identities =
identityHttpClient.ReadIdentitiesAsync(IdentitySearchFilter.DisplayName, displayName[0]).Result;
I have a list of displayNames to fetch users in one call to TFS.
Below code will help you to fetch all the user list:
foreach(var displayName in displayNames)
{
var result = await client.ReadIdentitiesAsync(IdentitySearchFilter.DisplayName, displayName).Result;
}
OR
foreach(var displayName in displayNames)
{
IdentitiesCollection identities = identityHttpClient.ReadIdentitiesAsync(IdentitySearchFilter.DisplayName, displayName).Result;
}
Refer this similar SO Thread and MSFT documentation to get all the users in a given scope and this is for getting direct members in a group.

Keycloak java api fetch service account user for given client

I'm using Keycloak version 3.4.3.Final community version (I know it's an older version and cannot update it because of business reasons) and it's corresponding java client, I have created a client with flag serviceAccountEnabled set to true and need to assign realm-management client's roles to it i.e. from section service-account-roles.
I'm able to create client successfully but not able to assign realm-management client's roles to it as it requires fetching of service-account-user which is returning null everytime, below is my code snippet
Code to create client
KeycloakTransaction tx = session.getTransactionManager();
tx.begin();
ClientModel clientModel = myRealm.addClient("myClient-id");
clientModel.setClientId("myClient-id");
clientModel.setClientAuthenticatorType("client-secret");
clientModel.setStandardFlowEnabled(false);
clientModel.setWebOrigins(Collections.emptySet());
clientModel.setRedirectUris(Collections.emptySet());
clientModel.setDirectAccessGrantsEnabled(false);
clientModel.setImplicitFlowEnabled(false);
clientModel.setServiceAccountsEnabled(true);
clientModel.setPublicClient(false);
clientModel.setProtocol("openid-connect");
clientModel.setFullScopeAllowed(false);
//need to inject this from env
clientModel.setSecret("12345");
clientModel.updateClient();
commitOrRollbackTransaction(tx);
Code to assign realm-management roles to client's service-account-user
KeycloakTransaction tx = session.getTransactionManager();
tx.begin();
RealmModel myRealm = keycloakSession.realms().getRealmByName("myRealm");
ClientModel clientModel = myRealm.getClientByClientId("myClient-id");
ClientModel realmManagementClient = myRealm.getClientByClientId("realm-management");
Set<RoleModel> roles = realmManagementClient.getRoles();
UserModel serviceAccountUser = keycloakSession.users().getServiceAccount(clientModel);
if(serviceAccountUser != null){
roles.stream().forEach(r -> serviceAccountUser.grantRole(r));
}
tx.commit();
The issue is, I do not get service-account-user for the client I created in previous step, however I've verified that user got created, also I can fetch service-account-user for existing clients, it seems more like a transaction issue but I'm performing client creation and roles assignment in two different sessions.
Can someone please point me where I'm mistaking or point me to direction how to fetch service-account-user.
Got it working using RealmManager and ClientManager keycloak API.

Joining entities with #ManyToMany relationship

I have these entities:
User
Role
Permission
A user has many roles and a role has many permissions.
What is the best way to retrieve a set of permission a user has?
I need a method to check if a User has a particular Permission.
This is what I have so far:
public boolean hasPermission(String permissionString) {
if (!authenticated) return false;
for (Role role : user.getRoles()) {
for (Permission permission : role.getPermissions()) {
if (permission.getName().equals(permissionString)) {
return true;
}
}
}
return false;
}
A second, but related question -- where should I put the code that checks if a user has a particular permission?
In the User entity?
In the UserBean EJB?
In the Authentication JSF Managed Bean?
It depends on your mappings, the number of objects in the list, if the lists have already been fetched, your database connections, the database tuning etc.
You would have to try with production data to determine what ways are best.
For instance, If your collections have been prefetched with a join query, then traversing them in Java is trivial. If they haven't, each access in the for loop would cause a query to populate the objects. If it is the last one all the time, it means your java code causes you to traverse your object graph in the worst way possible and it would have been better to fetch it upfront. So you would be losing any benefit of lazy access, and would be better of hitting the database once to query for the permission linked to this user with the permissionString name: "Select p from u User join u.roles r join r.permissions p where p.name = :permissionName".
Only testing on production data will give you the best answer for your situation, and numerous other decisions in the application and mappings change the outcome.

How to hide properties on Azure Mobile Service responses?

I have a Mobile Service with Model classes and DTO classes. I mapped these using Fluent API and got it to work to perform CRUD operations, but I have a problem with the JSON responses returned in some instances.
Take for example a User entity with user name and password. To register a user I have my PostUserDTO method like this:
// POST tables/UserDTO
public async Task<IHttpActionResult> PostUserDTO(UserDTO item)
{
string hashString = PasswordHash.CreateHash(item.Password);
item.Password = hashString;
UserDTO current = await InsertAsync(item);
current.Password = "";
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
On the method I read the password property sent from the client and then proceed to hash it with a salt, replace the value in the object sent and save it to the database, then I proceed to empty the password so the hashed result isn't returned.
In this case the best practice would be to omit the password property from the response, this also should happen when retrieving all of the users in the table, I only want to return specific information, some information generated by my server should stay out from the response.
How can I select or alter the information from the responses? Do I have to create other DTOs for every kind of response I desire?

Resource level authorization in RESTful service

Let /users/{id} be a resource url in RESTful service.
Basic authentication is enabled and only authenticated users are allowed to access the url.
Example Scenario:
User_1 & User_2 are authenticated users with userId 1 & 2.
Since both are authenticated, both of them are having access to,
/users/1
/users/2
But the expectation is User_1 should have access to /users/1 and not to /users/2 or other userId.
Question:
How to do resource level authorization in RESTful services?
Note: I am implementing RESTful using Jax-RS (with Apache CXF implementation), helpful if you could explain with Jax-RS.
-Barath
Edit:
As Donal mentioned, I am not looking for role based authorization rather resource level authorization.
To give an example, lets say /users/{id}/photos/{photoId} be another resource url. User_1 should be given access to the photos belong to him only. If photoId of 2 belonging to user_2, then we should give http_404 error code for user_1 when a request /users/1/photos/2 is requested.[Since User_1 is also authenticated user he can invoke /users/2/photos/2, so we must identify the user id based on authentication parameters than via resource url]
Only solution I can think of is, include the unique id which determines the authorization in each query like,
Instead of SELECT * FROM PHOTO_TBL WHERE PHOTO_ID=2;
use SELECT * FROM PHOTO_TBL, USER_TBL WHERE PHOTO_ID=2 AND USER_ID=1 AND USER_ID=PHOTO_ID;
with this resources are delivering data that belongs to specific user. [There should be a mechanism to prevent the modification of the unique id in client side which is used to decide on authorization(userId in this case), since all requests are STATELESS request]
Caveat: Each and every query should be intelligent enough to understand the security concerns and include extra join. This is a bad design to tie up security logic to every business function.
I am yet to look into Spring security and how it can be used in this use case.
I would recommend not having the user id in the url (as if it's being 'limited' by a Basic Auth header then you may as well just have it 'specified' by the Basic auth header). This will reduce the risk of introducing a Direct Object Reference Vulnerability - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References)
In this case you could have one of the following urls:
/users/CURRENT
/me
As photos is a sub resource then you could just create the photos with a "sequence number" within the user. In a sql database this would mean having a "compound key" across both user and photo columns.
/users/CURRENT/photo/{user_photo_seq}
/me/photo/{user_photo_seq}
Your SQL would then look something like:
SELECT * FROM PHOTO_TBL WHERE USER_ID=<BasicAuthUsername> AND PHOTO_ID=<path param value>;
A good explanation of "Basic Auth Headers":
http://en.wikipedia.org/wiki/Basic_access_authentication
JAX-RS specifies sub-resource where instead of handling request in a method, processing is delegated to other object - sub-resource.
Using sub-resources it's enought to take care of the root resource and nested ones will be secured as well.
In the example you can see UserResource and all it's sub-resources available only to authorized user.
#Path("/user/{userId}")
public class UserResource {
private final String userId;
public UserResource(#PathParam("userId") String userId, #Context SecurityContext securityContext) {
this.userId = userId;
boolean authorized = /* authorization code */;
if (!authorized) { throw new WebApplicationException(Status.UNAUTHORIZED); }
}
#Path("photo")
public PhotoResource getPhotoResource() {
return new PhotoResource(userId);
}
}
public class PhotoResource {
private final String userId;
public PhotoResource(String userId) {
this.userId = userId;
}
#GET
public Response listAll() { /* ... */ }
#GET
#Path("{photoId}")
public Response present() { /* ... */ }
}