We got a ADAL premium license and we are able to assign more then one role to a user successfully. But we can across this problem where a user 'Rob' is in 2 different groups i.e. (Group A and Group B) and we assigned Group A to 'Spanish Translator' and Group B to 'Chinese Translators'. So what we though was the user 'Rob' will be getting multiple roles assigned to him via group membership.But for some reason we are only getting one role 'Chinese Translators'.
Code Snippet that fetches user's role:
ClaimsIdentity claimsId = ClaimsPrincipal.Current.Identity as ClaimsIdentity;
var appRoles = new List<String>();
foreach (Claim claim in ClaimsPrincipal.Current.FindAll(claimsId.RoleClaimType))
{
appRoles.Add(claim.Value);
}
Just to make sure ,I also verified the user in portal and I did see the user getting assigned with two roles. But for some reason I'm only getting one role when the user signs-in.
Nikhil, thanks for reporting this. We've identified the issue and are working on a fix - I shall update the thread as soon as it rolls out.
Related
I am trying to configure my Airflow (version 2.10) LDAP authentication with RBAC.
UI access is restricted by the AD groups (multiple groups for Python Developer, ML Developer, etc.)
Members belonging to a particular group only should be able to view the DAGs created by fellow group members while the other group members shouldn't be.
Able to provide access to users via AD groups but all the users are able to see all the DAGs created. I want to restrict this access based on the defined set of owners, (this can be achieved by switching off the LDAP and creating users directly in Airflow, but I want it with AD groups.)
added fiter_by_owner=True in airflow.cfg file, seems nothing is effected.
Any thoughts on this.
EDIT1:
From FAB,
we can configure roles & then map it to AD groups as below:
FAB_ROLES = {
"ReadOnly_Altered": [
[".*", "can_list"],
[".*", "can_show"],
[".*", "menu_access"],
[".*", "can_get"],
[".*", "can_info"]
]
}
FAB_ROLES_MAPPING = {
1: "ReadOnly_Altered"
}
And to use this, I assume we need to have the endpoints created from the application end similar to can_list, can_show .
In the case of Airflow, I am unable to find the end-points that provides access based on owner (or based on tags). I believe if we have them, I can map it to roles & then to AD groups accordingly.
With newer versions of Airlfow you can map LDAP groups to Airflow Groups.
Owner is an old and currently defunct feature which is deprecated.
You can see some examples about FAB configuration (Flask Application Builder implements all authentication features):
https://flask-appbuilder.readthedocs.io/en/latest/security.html
See the part which starts with:
You can give FlaskAppBuilder roles based on LDAP roles (note, this requires AUTH_LDAP_SEARCH to be set):
From the docs:
# a mapping from LDAP DN to a list of FAB roles
AUTH_ROLES_MAPPING = {
"cn=fab_users,ou=groups,dc=example,dc=com": ["User"],
"cn=fab_admins,ou=groups,dc=example,dc=com": ["Admin"],
}
# the LDAP user attribute which has their role DNs
AUTH_LDAP_GROUP_FIELD = "memberOf"
# if we should replace ALL the user's roles each login, or only on registration
AUTH_ROLES_SYNC_AT_LOGIN = True
# force users to re-auth after 30min of inactivity (to keep roles in sync)
PERMANENT_SESSION_LIFETIME = 1800
See here about roles (including custom roles) https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html
This is regarding an application where we are using Azure B2C tenant for authentication. There is a requirement to get lists of users which would support filtering, pagination and users have to be from a particular TenantId. We are using Graph API SDK that i.e., microsoft.graph and microsoft.graph.Auth packages.
Steps I have done
Created graph client with ClientCredentialProvider with TenantId.
Getting users using the below code
var users = await graphClient.Users
.Request()
.Top(100)
.Filter("identities/any(c:c/issuer eq 'contoso.onmicrosoft.com')")
.Select("displayName,id,identities")
.GetAsync();
This gets all users for a given issuer or tenant. Now, there is an issue I cannot filter users using this option .Filter("identities/any(c:c/issuer eq 'contoso.onmicrosoft.com') and startswith(displayName,'a') i.e., get all users whose display name starts with 'a' and belong to this issuer 'contoso.onmicrosoft.com'. As per Microsoft, Graph API does not currently support complex queries on Identities. They show this message Message: Complex query on property identities is not supported.
Now, right now my thoughts are limited to this option of loading entire user table for this tenant onto memory. I think this would be not the best approach, because we will have more tenants and I don't know how much users we can store in memory.
Anyone who has more understanding on these type of scenarios, please share your inputs. I wanted to know various other alternatives we could take.
As the message says, "Complex query on property identities is not supported", it's also not supported in Microsoft Graph SDK. You could only check the users with String.StartsWith() method in C#.
var users = await graphClient.Users
.Request()
.Top(100)
.Filter("identities/any(c:c/issuer eq 'contoso.onmicrosoft.com')")
.Select("displayName,id,identities")
.GetAsync();
List<User> userResult = new List<User>();
foreach(var user in users)
{
if (user.displayName.StartsWith(a)) {
userResult.add(user);
}
}
I'm trying to enable service to service auth using AAD tokens. My plan is to validate "groups" claim in the token to make sure the caller is a member of a security group that we created.
For example, we will create group1 for readers and group2 for writers. Then based on "groups" claim, I will figure out the right access level.
I use AAD app to issue the tokens (not a user), so I need that app to be a member of the security group. Azure AD powershell doesn't seem to accept application ids as group members. How to solve this? are there any other recommended patterns when the caller is another AAD app?
Command used:
https://learn.microsoft.com/en-us/powershell/module/azuread/Add-AzureADGroupMember?view=azureadps-2.0
Error:
Add-AzureADGroupMember : Error occurred while executing AddGroupMember
Code: Request_BadRequest
Message: An invalid operation was included in the following modified references: 'members'.
RequestId: 0441a156-3a34-484b-83d7-a7863d14654e
DateTimeStamp: Mon, 11 Dec 2017 21:50:41 GMT
HttpStatusCode: BadRequest
HttpStatusDescription: Bad Request
HttpResponseStatus: Completed
At line:1 char:1
+ Add-AzureADGroupMember -ObjectId "9c2cdf89-b8d6-4fb9-9116-7749adec85c ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-AzureADGroupMember], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.AddGroupMember
Unfortunately, you cannot add an application as a member of Azure AD group.
Though the official document for the Powershell cmdlet Add-AzureADGroupMember doesn't make clear you cannot use Application's ObjectId as the RefObjectId, absolutely you cannot use it.
You cannot add an application as a member of Azure AD group neither.
For example, we will create group1 for readers and group2 for writers.
Then based on "groups" claim, I will figure out the right access
level.
For your scenario, I'm afraid that you couldn't achieve this for now. I understand why you need this. According to your request, my thought is assigning your application from Enterprise Application to Groups or users and manger users with different access rights. However, you cannot choose more roles for the selected group. The only one role is default access If want to define more roles for the app, you can refer to this documentation.
I also tried to use Azure AD RBAC and create new conditional access for my test app,but all don't have read only this choice.
You can also put your idea in Azure Feedback Forum, azure team will see it. Also, I will upvote your idea.
Update:
Currently, you can add a service principal to an AAD Group:
Example:
$spn = Get-AzureADServicePrincipal -SearchString "yourSpName"
$group = Get-AzureADGroup -SearchString "yourGroupName"
Add-AzureADGroupMember -ObjectId $($group.ObjectId) -RefObjectId $($spn.ObjectId)
Updated 2:
Recently, I also see lots of users want to assign roles to a service principal to let the service principal have some permissions to access to the app with a role.
I want to make clear here. Role-based authorized should be used for users, NOT applications. And it's not designed for applications. If you want to give some different permissions you may consider to assign application permissions to your service principal instead.
You can expose your Web App/API with application permissions by editing the Manifest in app registrations.
You can go to Azure portal > Azure Active Directory > App registrations > Select your App > Manifest.
In appRoles, you can insert content like this:
{
"allowedMemberTypes": [
"Application"
],
"displayName": "Access to the settings data",
"id": "c20e145e-5459-4a6c-a074-b942bbd4cfe1",
"isEnabled": true,
"description": "Administrators can access to the settings data in their tenant",
"value": "Settingsdata.ReadWrite.All"
},
Then, you can go another app registration you want to give permission > Settings > require permissions > Add > Search the application name you want to access > Choose the application permission you created before.
Therefore, your sp can obtain a token with that application permissions in token claims.
Also, for authorization from the resource, you need to add code logic to give control policy for that token with Settingsdata.ReadWrite.All claim.
Update 3
Currently, you can add the service principal to one AAD Group directly in Azure portal:
Following Update 3 in the answer of #Wayne Yang, I've successfully implemented this using C# and the MS Graph SDK.
But I think the same should be possible using Powershell and simple REST API calls.
// create new application registration
var app = new Application
{
DisplayName = principal.DisplayName,
Description = principal.Description,
};
app = await _graphClient.Applications.Request().AddAsync(app);
// create new service Principal based on newly created application
var servicePrincipal = new ServicePrincipal
{
AppId = app.AppId
};
// add service principal
servicePrincipal = await _graphClient.ServicePrincipals.Request().AddAsync(servicePrincipal);
// add service principal to existing security group
await _graphClient.Groups[groupId].Members.References.Request().AddAsync(servicePrincipal);
We have added a AD group to SharePoint users group. Now when we login with user, we want to check permission for the logged in AD user.
I have added Ad group (example) managers in SharePoint.
Now I want show some URL links to only the group(managers).
When user logged in, how can I check whether user is manager or not? (Using
CSOM or JSOM)
Unfortunately, the SPGroup.ContainsCurrentUser property that you would use for this in server-side code is not accessible through the JavaScript client object model (at least not in SP2010 and 2013).
Option 1: Use group membership visibility as a workaround
One potential workaround is to exploit a combination of two properties that you can access on groups via the JavaScript client object model: OnlyAllowMembersViewMemberhip and CanCurrentUserViewMembership.
If the current user can view group membership for a group that is only set to allow group members to do so, we can assume the user is a group member.
var clientContext = new SP.ClientContext();
var groupId = 5; // the group membership ID for the group you want to check
var group = clientContext.get_web().get_siteGroups().getById(groupId);
clientContext.load(group,"CanCurrentUserViewMembership");
clientContext.load(group,"OnlyAllowMembersViewMembership");
clientContext.executeQueryAsync(
function(sender,args){
var isMemberOfGroup = group.get_canCurrentUserViewMembership() && group.get_onlyAllowMembersViewMembership();
if(isMemberOfGroup){
doSomething();
}
},
function(sender,args){alert("Whoops! "+args.get_message());}
);
This approach will only work if you've set the groups to only be visible to members, and it'll always return a false positive if you have elevated access, such as if you're a site collection administrator or the group owner.
How to Iterate Through All Site Groups
If you want to apply the above logic to check the current user's membership in all groups on the site (instead of specifying a group by its ID), you can use the modified JavaScript code below.
var clientContext = new SP.ClientContext();
var groups = clientContext.get_web().get_siteGroups()
clientContext.load(groups,"Include(CanCurrentUserViewMembership,OnlyAllowMembersViewMembership,Title)");
clientContext.executeQueryAsync(
function(sender,args){
var groupIterator = groups.getEnumerator();
var myGroups = [];
while(groupIterator.moveNext()){
var current = groupIterator.get_current();
var isMemberOfGroup = current.get_canCurrentUserViewMembership() && current.get_onlyAllowMembersViewMembership();
if(isMemberOfGroup){
myGroups.push(current.get_title()); // this example adds group titles to an array
}
}
alert(myGroups); // show the array
},function(sender,args){"Whoops! "+alert(args.get_message());});
Option 2: Use Audience Targeting as a workaround
For your requirements you may not even need programmatic access to the group membership. You could just set audience targeting on the web parts that you want to be visible only to certain groups; audience targeting should respect AD group membership.
We are using Azure Active Directory and Azure Access Control Services (ACS) to authenticate users in a SharePoint 2010 instance. The users and groups in Azure AD are synched from an on-prem AD directory using Azure AD Connect.
We've gotten almost everything working to authenticate users, but what's not clear is how to control SharePoint access using the groups in Azure AD. We figured out the way to enable the group claim to be passed through per these instructions, but the object ID of the group (e.g., 244728b5-8b9e-4e2f-8703-9853366cd431) is passed, which is meaningless in SP.
Is there a way to pass the group name or should we be using the group ID? Is there a better way to manage group access in SP when authenticating against Azure AD?
Thanks for the help.
You should use the group identifier. To see it,
go to the azure management portal https://manage.windowsazure.com
choose active directory from the list of services on the left
click on your active directory from the list
click on "groups" from the menu at the top
click on the group you want to see the id for in the list
click "properties" from the menu at the top
Copy the ObjectID field from the list of properties
in your code, you can declare a string constant using the objectID
private static string myGroupName = "xxxxxxxx-your-objectID-xxxxxxxxxx";
Then just use "myGroupName" to compare your group to the list of group claims
var isMember = IsGroupMember(myGroupName);
Here is how to look at the claims:
public static bool IsGroupMember(string groupName)
{
var principal = ClaimsPrincipal.Current;
// Look for the groups claim
var supportClaim = principal.Claims.FirstOrDefault(
c => c.Type == "groups" &&
c.Value.Equals(groupName, StringComparison.CurrentCultureIgnoreCase));
return null == supportClaim ? false : true;
}