SharePoint group claims through Azure Active Directory - azure

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;
}

Related

Can't Create Azure SQL Database Users Mapped to Azure AD Identities using Service Principal

As part of an Azure SQL database automation solution, I'm trying to create Azure SQL database users mapped to Azure AD Identities, using a service principal.
The result is an error message saying: Principal 'AAD_User_UPN_or_Group_Name' could not be found at this time. Please try again later.
The database users can be created using my own user account, following exactly the same procedure.
Please find more details below:
The service principal is a member of an Azure AD security group
The group is set as the Active Directory Admin of an Azure SQL server
My own user account is also a member of this group
The service principal has Directory Reader and Directory Writer role in the Azure Active Directory
My own user account is a regular member without any admin role in the Azure Active Directory
The service principal executes following T-SQL statement inside the Azure SQL database:
CREATE USER [AAD_User_UPN_or_Group_Name] FROM EXTERNAL PROVIDER;
The returned error message is:
Principal 'AAD_User_UPN_or_Group_Name' could not be found at this time. Please try again later.
When the same T-SQL statement is triggered by my own user account, it runs successfully and the user is created.
Your help or suggestions are highly appreciated.
I opened a ticket with Azure support and they gave me this solution.
The sql statement needs to be:
-- type X for AAD Group
create user [myAADGroupName] with sid = <sid>, type = X;
-- type E for AAD User or Service Principal/MSI
create user [myAADUserName] with sid = <sid>, type = E;
The sid needs to be generated from the AAD Principal ObjectID in most cases. However, for Service Principals/MSIs, it needs to come from the AppId. Here's a powershell script to generate the sid value:
param (
[string]$objectIdOrAppId
)
[guid]$guid = [System.Guid]::Parse($objectIdOrAppId)
foreach ($byte in $guid.ToByteArray())
{
$byteGuid += [System.String]::Format("{0:X2}", $byte)
}
return "0x" + $byteGuid

Add AAD application as a member of a security group

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);

.net core 2.0 single sign on with Azure - Active Directory Group Listing

Currently using .net core 2.0, OpenIDConnect Single Sign On with Azure AD. Trying to retrieve a list of the the Azure AD Groups assigned to the logged on user but am coming up blank. When looping through the claims on the User object, I don not see anything for groups ...
var claims = User.Claims.Select(c =>
new{
Type = c.Type,
Value = c.Value
});
So my issue was not code related ... I need to edit the Manifest file for my App Registration in Azure to set groupMembershipClaims = "All". After setting the groups scope on OpenIDCOnnect, I was able to access all of my Active Directory Groups via the User.Claims listing where type = "groups"

Grant an existing B2C app access to graph API

I have an existing B2C app that I want to give graph access to.
I set this up previously but now want to replicate it but everything i can find is for new apps. I ysed the older graph but i think the article I used has been moved as everything is talking about the new Graph api
Is there a specific article for this, also if anyone has seen an article that describes the process from moving from Azure graph to Microsoft Graph (the new version) for a B2C app that would be great
Thanks
Register the application for the Graph API
In addition to registering the application in the B2C directory,
we must also create an application registration for the graph API.
The three key/id values you will need are the tenantId, ObjectId,
and AppPrincipalId.
To get the tenantId, log into the azure ad b2c directory in the new portal.
https://portal.azure.com/
Be sure you have the correct directory selected after you login
(top right corner).
Click on the help button (a question mark inside a circle) near the
top right corner of the page. In the menu that appears, click the
"Show diagnostics" option. This will display a JSON formatted output in
a new popup/window. Look for the "tenants" array and find the entry
with the display name of the directory you wish to register with the
application. The "id" attribute of that entry is the tenantId.
Example:
{
"clientSessionStartDate": {
//stuff will be here ...
},
//
// more shtuff you don't care about will be here ...
//
"tenants": [
{
"id": "SomeUUIDwithlike36charactersSometime",
"domainName": "yourtenantname.onmicrosoft.com",
"displayName": "displanynameoftenant",
"isSignedInTenant": true
},
// ... snippity lemon
]
// ... snip some more
}
You will also need a unique application Secret and AppPrincipalId to be
generated for the new application.
Also, to set the correct permissions for the application, you will need
its "ObjectId".
The process for registering the application and generating those values
is more complicated, and requires a special module for PowerShell
and the online login module to be downloaded and installed.
Also, be sure you have the latest version of PowerShell installed for
your system, or you will not be able to use the azure module.
Sign-In assistant: https://www.microsoft.com/en-us/download/details.aspx?id=41950
Azure AD PowerShell Module: http://go.microsoft.com/fwlink/p/?linkid=236297
Create the application registration with PowerShell
This next section is an almost verbatim copy-paste fo the documentation.
https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-devquickstarts-graph-dotnet/
After you install the PowerShell module, open PowerShell and connect to
your B2C tenant.
> $msolcred = Get-Credential
After you run Get-Credential, you will be prompted for
a user name and password, Enter the user name and password
of your B2C tenant administrator account.
> Connect-MsolService -credential $msolcred
Before you create your application, you need to generate a new client
secret. Your application will use the client secret to authenticate to
Azure AD and to acquire access tokens. You can generate a valid secret
in PowerShell:
> $bytes = New-Object Byte[] 32
> $rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
> $rand.GetBytes($bytes)
> $rand.Dispose()
> $newClientSecret = [System.Convert]::ToBase64String($bytes)
> $newClientSecret
The final command should print your new client secret. Copy it somewhere safe. You'll need it later. Now you can create your application by providing the new client secret as a credential for the app:
> New-MsolServicePrincipal -DisplayName "My New B2C Graph API App" -Type password -Value $newClientSecret
Example output:
DisplayName : My New B2C Graph API App
ServicePrincipalNames : {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
ObjectId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AppPrincipalId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
TrustedForDelegation : False
AccountEnabled : True
Addresses : {}
KeyType : Password
KeyId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
StartDate : 1/1/2017 1:33:09 AM
EndDate : 1/1/2017 1:33:09 AM
Usage : Verify
If you successfully create the application, it should print out
properties of the application like the ones above, but with a mix of alpha-numeric characters. You'll need both
ObjectId and AppPrincipalId, so copy those values, too.
You will also need the tenant ID of the B2C directory.
After you create an application in your B2C tenant, you need to assign
it the permissions it needs to perform user CRUD operations. Assign the
application three roles: directory readers (to read users), directory
writers (to create and update users), and a user account administrator
(to delete users). These roles have well-known identifiers, so you can
replace the -RoleMemberObjectId parameter with ObjectId from above and
run the following commands. To see the list of all directory roles,
try running Get-MsolRole.
> Add-MsolRoleMember -RoleObjectId 88d8e3e3-8f55-4a1e-953a-9b9898b8876b -RoleMemberObjectId <Your-ObjectId> -RoleMemberType servicePrincipal
> Add-MsolRoleMember -RoleObjectId 9360feb5-f418-4baa-8175-e2a00bac4301 -RoleMemberObjectId <Your-ObjectId> -RoleMemberType servicePrincipal
> Add-MsolRoleMember -RoleObjectId fe930be7-5e62-47db-91af-98c3a49a38b1 -RoleMemberObjectId <Your-ObjectId> -RoleMemberType servicePrincipal
You now have an application that has permission to create, read,
update, and delete users from your B2C tenant.
I totally forgot this great answer exists and this is how you do it
Authorize By Group in Azure Active Directory B2C

User is part of an AD Group that is nested in the SharePoint group how to relate ad user with SharePoint group

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.

Resources