Allowing all users to impersonate any user in liferay - liferay

I have a requirement where I have to allow all of my regular users to impersonate a user of their choice.
I haven't been able to make this work. This is what I've done so far:
Added the following properties to portal-ext.properties:
portal.jaas.enable=false
portal.impersonation.enable=true
Created a role for the purposes of impersonation
Defined permissions for this new role: Portal > Users and organizations > View & Impersonate
Assigned this role to a non-administrator user (user A)
I don't need my users to see the list of users they can impersonate, I just want liferay to impersonate a user if ?doAsUserId=x is present in the url (which does work if you are an administrator).
When I try to impersonate user B using user A, nothing happens. I get this error in the tomcat log:
1ERROR [http-bio-8180-exec-85][PortalImpl:5990] User 80413 does not have the permission to impersonate 25105
(User 80413 is my User A, the one attempting to impersonate user B [25105])
Am I missing something else?

There is a condition in Lifeary, which checks the permission on the list of organizations for the impersonation. So, the user who is impersoneting the other user, must have a permission for "impersonation" in all the organisation of which, these users are part of.
if (doAsUser.isDefaultUser() ||
UserPermissionUtil.contains(
permissionChecker, doAsUserId, organizationIds,
ActionKeys.IMPERSONATE)) {
request.setAttribute(WebKeys.USER_ID, new Long(doAsUserId));
return doAsUserId;
}
So, those 2 users must be part of same organization and must be having impersonation permission for that organization.

Related

How do I specify Permissions in a custom app consent policy?

I have successfully made a Custom App Consent Policy using New-AzureADMSPermissionGrantConditionSet and following the MS docs. I specified ClientApplicationIds and it works great.
Now I also want to specify the permissions that must match. On Permissions, the docs say:
I need help understanding (and accessing) the permission IDs in the "OAuth2Permissions property of the API's ServicePrincipal object".
What ServicePrincipal is the doc referring to? The one in the application’s Home Tenant, or one in the Tenant that is using the application? If the app has not been consented to yet, then there is no ServicePrinciple in the Tenant using the app so I have a chicken-and-egg problem.
And what are the Permissions I'm expecting to get? I'm wondering why MS didn't just let us pass the scopes as strings e.g. email, mail.read etc. I don't understand exactly what the Permissions are in this particular context.
I need help understanding (and accessing) the permission IDs in the "OAuth2Permissions property of the API's ServicePrincipal object".
The permission ID means the id of the Delegated permission of the API( i.e. oauth2Permissions defined in the API) you added in the client app registration.
For example, you created a multi-tenant client app in tenant A, you added the Mail.Read Delegated permission of Microsoft Graph, by default, there would also be a User.Read Delegated permission automatically, so there are two permissions totally in the API permissions of your client app.
Now, you want to use the custom app consent policy in tenant B, you want the user to consent the two permissions, then the -Permissions should be the id of the two permission defined in Microsoft Graph, to find it easily, just navigate to the client app in tenant A -> Manifest, then you can get the ids like below.
The complete command should be
New-AzureADMSPermissionGrantConditionSet `
-PolicyId "joy-custom-policy" `
-ConditionSetType "includes" `
-PermissionType "delegated" `
-ResourceApplication "00000003-0000-0000-c000-000000000000" `
-Permissions #("e1fe6dd8-ba31-4d61-89e7-88639da4683d","570282fd-fa5c-430d-a7fd-fc8dc98a9dca")
In another scenario, you use the custom API(created in tenant A) in the client app instead of a Microsoft API.
If so, you need to grant admin consent for the API App in tenant B first, otherwise you will get an error The app needs access to a service (\"api://tenantA/myapi\") that your organization (tenant B) has not subscribed to or enabled, or you can use the admin account to run New-AzureADServicePrincipal -AppId <appid of the API app> in tenant B, it will also work, after consent, the normal user will be able to consent the permission you defined in the policy.
Note: Sometimes, you may get an error This app may be risky like below.
This means Microsoft detects a risky end-user consent request, the request will require a step-up to admin consent instead, if you still want the user to consent the permission, you need to disable the risk-based step-up consent first, then the user will be able to consent the permission.
Here's an example for how you would get the permission IDs for three delegated permissions for Microsoft Graph, using Azure AD PowerShell:
# The appId for the client application
$clientAppId = "{client-app-id}"
# The claim values for the Microsoft Graph delegated permissions to include
$claimValues = #("User.Read", "Mail.Send", "User.ReadBasic.All")
# Get the service principal for Microsoft Graph
$resource = Get-AzureADServicePrincipal -Filter "servicePrincipalNames/any(n:n eq 'https://graph.microsoft.com')"
# Get the delegated permission IDs for the given claim values
$permissionIds = $resource.OAuth2Permissions `
| ? { $claimValues.Contains($_.Value) } | select -ExpandProperty Id
# Use these permission IDs in a condition set for a custom permission grant policy
New-AzureADMSPermissionGrantConditionSet `
-PolicyId "my-custom-policy" `
-ConditionSetType "includes" `
-ClientApplicationIds #($clientAppId) `
-PermissionType "delegated" `
-ResourceApplication $resource.AppId `
-Permissions $permissionIds

Insufficient privileges error when trying to fetch signed in user's group membership using Azure AD Graph API

I need to be able to get the signed in user's group membership so that I can verify whether he is part of a specific group. However I am getting "Insufficient privileges to complete the operation." exception using the Azure AD graph API client library.
I am a co-admin of a subscription and I have created a new Azure AD application to authenticate against the default directory and configured the "Permission to Other application" section as in the below screenshot.
Azure AD Application Configuration
I am able to fetch the signed in user details, but when I try to call MemberOf function, then I get the above exception. Please let me know what I am missing here. Thanks in advance!
string objectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; // object id of the signed in user
ActiveDirectoryClient client = AuthenticationHelper.GetActiveDirectoryClient();
IUser user = await client.Users.GetByObjectId(objectId).ExecuteAsync();
var userFetcher = (IUserFetcher)user; // able to fetch the signed in user
IPagedCollection<IDirectoryObject> pagedCollection = await userFetcher.MemberOf.ExecuteAsync(); // getting error here - "Insufficient privileges to complete the operation."
The problem here was that I had selected the permissions outside the 'personal scope' (Access the directory as the signed in user, Read directory data).
Hence, it needed consent from the service administrator of the subscription associated to the directory. Once the admin logs into the app and approves the consent screen, the code should stop giving insufficient privileges exception.

Why Azure AD fails to login non-admins in multi-tenant scenario?

Environment:
Two Azure ADs: Company, Customers
Company publishes an ASP.NET5 web app called Portal, the app is setup to be multi-tenant.
Customers have 2 user: user (who is just a user) and admin (who is a Global Administrator in the directory).
Portal, is initially set up to ask for 1 Application Permission: Read Directory Data
-
Here comes the flow that I went through, and I believe Azure AD misbehaves at multiple steps. Please point out if I am missing something.
I open the web app, and first try to sign in as admin
I have to consent to the Read Directory data permission, so I do that
Application appears (I have no roles assigned yet, which is fine) -- so far everything works.
I re-open the web-app in a new incognito session, and try to sign in as the user
Now, I get [AADSTS90093: This operation can only be performed by an administrator. Sign out and sign in as an administrator or contact one of your organization's administrators.] -- the admin already consented, so why do I get this??
I go to Company AD and change the application permissions to include Read & Write Directory data
I go to Customer AD check the app Portal and the dashboard already shows the new permission listed. No one had to consent! The admin do not see any change even on next login. How is this not a security hole?
My understanding of https://msdn.microsoft.com/en-us/library/azure/dn132599.aspx is that Application Permissions are not deprecated.
UPDATE
My configuration in the WebApp:
app.UseOpenIdConnectAuthentication(options =>
{
options.ClientId = Configuration.Get("ActiveDirectory:ClientId");
options.Authority = String.Format(Configuration.Get("ActiveDirectory:AadInstance"), "common/"); //"AadInstance": "https://login.windows.net/{0}"
options.PostLogoutRedirectUri = Configuration.Get("ActiveDirectory:PostLogoutRedirectUri"); //"PostLogoutRedirectUri": "https://localhost:44300/"
options.TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
// The following commented-out line should work according to
// http://stackoverflow.com/questions/29317910/why-does-the-role-claim-have-incorrect-type
// But, it does not work in ASP.NET5 (currently), so see the "Hack." down below
// RoleClaimType = "roles",
ValidIssuers = new[] { "https://sts.windows.net/a1028d9b-bd77-4544-8127-d3d42b9baebb/", "https://sts.windows.net/47b68455-a2e6-4114-90d6-df89d8468abc/" }
};
options.Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = (context) =>
{
// This ensures that the address used for sign in and sign out is picked up dynamically from the request,
// which is neccessary if we want to deploy the app to different URLs (eg. localhost/immerciti-dev, immerciti.azurewebsites.net/www.immerciti.com)
string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
context.ProtocolMessage.RedirectUri = appBaseUrl;
context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
return Task.FromResult(0);
},
AuthorizationCodeReceived = async context =>
{
// Get Access Token for User's Directory
try
{
var identity = (ClaimsIdentity)context.AuthenticationTicket.Principal.Identity;
// Hack. TODO: keep an eye on developments around here
foreach (var claim in identity.FindAll("roles"))
{
// Readd each role with the proper claim type
identity.AddClaim(new Claim(identity.RoleClaimType, claim.Value, claim.ValueType, claim.Issuer, claim.OriginalIssuer));
}
}
catch (AdalException)
{
context.HandleResponse();
context.Response.Redirect("/Error/ShowError?errorMessage=Were having trouble signing you in&signIn=true");
}
}
};
};
Thanks for the information you've provided. I'm going to answer #7 first, because it looks pretty alarming. It does at first glance look like a security hole, but it's not. It's a bug in the Azure Management Portal that we are working to fix. In the "customers" tenant view, the UX is showing the permissions that the application (defined in the company tenant) is requesting. It should be showing the permissions actually granted in the "customers" tenant. In this case, if your app actually tries a call to write to the Graph API it'll get an access denied error. Anyways - not a security hole - but can sure understand why it looked that way to you - so sorry about this. We'll try to get this fixed as soon as we can.
On to some of your other questions about consent behavior... BTW this is something we are looking to improve in our documentation. Anyways, I'll try and answer this broadly in terms of the design behavior, because it looks like you've changed your app config multiple times.
If you pick any app permissions (not delegated permissions), the consent UX defaults to the "consent on behalf of the organization" experience. In this mode the consent page ALWAYS shows, whether the admin consented previously or not. You can also force this behavior if you make a request to the authorize endpoint with the QS parameter of prompt=admin_consent. So let's say you went down this path AND the only permission you have is app-only "Read Directory" and the admin consents. Now a user comes the user doesn't have any grant that allows them to sign in and get an id_token for the app (Read Directory app-only is not currently good for this), so the consent dialog tries to show the admin on behalf of org consent, but this is a non-admin so you get the error.
Now, if you add the delegated "sign me in and read my profile" permission for the app, and have your admin reconsent, you'll see that now the user will not be prompted for consent.
What I'll do is go back to our team and see whether ANY directory permission (app only or delegated) should allow any user to get a sign in token. One could argue that this should be the case.
HTHs,

How to assign a Site Administration role for a user in liferay programatically?

I am creating the user programatically by calling the UserLocalServiceUtil.addUser(....) and able to assign the site for the created user by calling UserLocalServiceUtil.addRoleUser(userSiteId, userId) It is working fine. I am able to assign the site membership for the user. But how can I assign the Site Administration permission for creates user. (So for I am able to assign user as site member but I need to assign user as a site administrator)
Any suggestions please..
Use UserGroupRoleLocalServiceUtil to assign "Site Administration" role under the Site roles.
Role role = RoleLocalServiceUtil.getRole(companyId, "Site Administrator");
long[] SiteroleIds = {role.getRoleId()};
UserGroupRoleLocalServiceUtil.addUserGroupRoles(userId, siteId, SiteroleIds);
You can use RoleLocalServiceUtil to get object of any role.
Role role = RoleLocalServiceUtil.getRole(roleId);
UserLocalServiceUtil.addRoleUser(role.getRoleId(), user.getUserId());
UserLocalServiceUtil.updateUser(user);

Microsoft CRM 2011 Impersonation

I want to know in CRM 2011, if I initiated the organization service with user (A) and then I impersonated with user (B).
Which user permissions will be used by CRM when I try to execute a request (i.e create account, ...)?
For example:
I have
User (A) who don't have permissions to act on behalf another user.
User (B) who have system administrator permissions and act on behalf another user permission.
I create the organization service based on Windows Authentication and log-in with user (A) as following:
Uri organizationUri = new Uri("http://localhost:5555/RMS/XRMServices/2011/Organization.svc");
Uri homeRealmUri = null;
ClientCredentials credentials = new ClientCredentials();
credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
OrganizationServiceProxy orgProxy = new OrganizationServiceProxy(organizationUri, homeRealmUri, credentials, null);
Then I impersonate like that
orgProxy.CallerId = userBGuid;
When I am trying to execute WhoAmIRequest; I get the following error:
System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: User does not have the privilege to act on behalf another user. (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).
When I give User (A) permissions to act on behalf of another user, this code pass successfully.
It looks it's expected behavior. If you set CallerId = userBGuid it means that even when you are logged as userA, all activities done on behalf of userB. UserA should have priviliges to do this.

Resources