Azure AD/Office 365: Create similar groups for two different domains - azure-active-directory

I have two domains registered in Azure AD, domainA.com and domainB.com, and I want to create two similar Groups for them:
support#domainA.com
support#domainB.com
How can I do that?
Im trying code like below via Microsoft Graph, and first Group is created successfully. However there is an error when adding the second group for domain B:
"Another object with the same value for property mailNickname already
exists"
public async Task CreateSupportGroups()
{
// Create the group for domain A
await UpdateDefaultDomain("domainA.com");
await AddNewGroup("Support group for Domain A");
// Create the group for domain B
await UpdateDefaultDomain("domainB.com");
await AddNewGroup("Support group for Domain B");
}
public async Task AddNewGroup(String groupName)
{
var group = new Group
{
Description = "Testgroup",
DisplayName = groupName,
GroupTypes = new List<String>()
{
"Unified"
},
MailEnabled = true,
MailNickname = "support",
SecurityEnabled = false,
Visibility = "Private"
};
await graphClient.Groups
.Request()
.AddAsync(group);
}
public async Task UpdateDefaultDomain(String domainID)
{
var domain = new Domain
{
IsDefault = true
};
await graphClient.Domains[domainID]
.Request()
.UpdateAsync(domain);
}

I have tested in my environment.
Please make domainA.com as primary and create a group with displayname support A and mailnickname as support
Then make domainB.com as primary and create a group with displayname support B and mailnickname as supportB because if you create with mailnickname as support, it will throw below error :
After creation of Support B Group, edit the primary mail of the group to support#domainB.com. Even though it throws error, the primary mail of the group is updated.
Please refer below screenshot :

Related

What is the best way to update a department name in Active Directory and Azure for 100+ users?

Azure is currently setup to sync from on
prem. Active Directory. What is the best way to update the department name
in Active Directory and Azure for these users? Below is a sample of the list.
Name
Old Department Name
New Department Name
Larry Lue
Collections
Collector Members
Erica Anderson
Collections
Collector Members
Mary Lee
Collections
Collector Members
You can use ms graph api to do the update by code. But this api doesn't provide a batch operation, so you have to update user profile one by one. Here's my test result:
Before updating the department, the original department look like this:
After update it by code. it will be changed to the new value.
Here's the code snippet:
using Microsoft.Graph;
using Azure.Identity;
public async Task<IActionResult> IndexAsync()
{
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_id";
var clientSecret = "azure_ad_app_client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
//query user information
var user = await graphClient.Users["user_id"]
.Request().Select("displayname, department").GetAsync();
//update user information
var userDept = new User
{
Department = "Collector Members"
};
await graphClient.Users["9a8ae89f-711a-434a-8d08-43e1f7d29af2"]
.Request()
.UpdateAsync(userDept);
}

How To Update MS Graph Client Service Principal AppRoleAssignments

I am attempting to update a user's AppRole assignments via the Graph Client. As per MS documents I am attempting to do it from the service principal side rather than the user side.
var sp = await _graphServiceClient.ServicePrincipals[objectId].Request().GetAsync();
ServicePrincipal newSp = new ServicePrincipal
{
Id = objectId,
AppId = _configuration["AzureAd:AppId"]
};
newSp.AppRoleAssignedTo = new ServicePrincipalAppRoleAssignedToCollectionPage();
newSp.AppRoleAssignedTo.Add(new AppRoleAssignment
{
PrincipalId = new Guid(u.Id),
ResourceId = new Guid(objectId),
AppRoleId = new Guid(r)
});
await _graphServiceClient.ServicePrincipals[objectId].Request().UpdateAsync(newSp);
I am getting 'One or more property values specified are invalid' but of course no real info on what property or even which object is the problem.
Anyone see anything obvious? I'm guessing on the syntax for the client usage bc I don't see much documentation or examples for it.
I test with same code with yours and met same issue and do some modification but still can't solve the issue. For your requirement of update user's AppRole assignment, I'm not sure if we can do it by the code you provided, but I can provide another solution which is more directly.
The code you provided is new a service principal and add the role assignment into it, then update the service principal. Here provide another solution, it can add the app role assignment directly:
var appRoleAssignment = new AppRoleAssignment
{
PrincipalId = Guid.Parse("{principalId}"),
ResourceId = Guid.Parse("{resourceId}"),
AppRoleId = Guid.Parse("{appRoleId}")
};
await graphClient.Users["{userId}"].AppRoleAssignments
.Request()
.AddAsync(appRoleAssignment);
The code above request this graph api in backend.

How to retrieve the userid from userprincipalname in azure active directory?

My client has synchronization set up between an on-premises Active Directory (AD) and Azure Active Directory (AAD).
I am able to retrieve user information from AAD using Microsoft Graph without a problem but, I specifically need to get the AD UserID, ie ({domain}/{userid}).
I tried calling https://graph.microsoft.com/v1.0/users/firstname.lastname#domain.com/$select=userId but it did not work.
My questions are, is it possible? And in that case what is the actual attribute name? I have been looking around but haven´t been able to find a complete list of attributes.
EDIT:
After receiving one answer from Marilee I am including the C# code I have been using, ish. Both the calls do work for receiving user information from AAD, but not the AD UserID, ie ({domain}/{userid}) that I am looking for.
Attempt no 1
var requestUri = GraphBaseUri + $"/v1.0/users/{upn}?$select=userId";
var response = await _httpClient.GetAsync(new AuthenticationHeaderValue("Bearer", accessToken), requestUri).ConfigureAwait(false);
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
dynamic responseObj = JsonConvert.DeserializeObject(content) as JObject;
return responseObj.UserId; //NOT WORKING
Attempt no 2
var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) => {
requestMessage
.Headers
.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return Task.FromResult(0);
}));
// Retrieve a user by userPrincipalName
var user = await graphClient
.Users[upn]
.Request()
.GetAsync();
return user.ObjectId; //NOT WORKING
The attribute you're referring to is the objectID. From Graph API you can use UPN like you said:
GET /users/{id | userPrincipalName}
You can look up the user in a few different ways. From the /users endpoint you can either use their id (the GUID assigned to each account) or their userPrincipalName (their email alias for the default domain):
// Retrieve a user by id
var user = await graphClient
.Users["00000000-0000-0000-0000-000000000000"]
.Request()
.GetAsync();
// Retrieve a user by userPrincipalName
var user = await graphClient
.Users["user#tenant.onmicrosoft.com"]
.Request()
.GetAsync();
If you're using either the Authorization Code or Implicit OAuth grants, you can also look up the user who authenticated via the /me endpoint:
var user = await graphClient
.Me
.Request()
.GetAsync();
From Powershell you can query Object IDs:
$(Get-AzureADUser -Filter "UserPrincipalName eq 'myuser#consoso.com'").ObjectId
The way to do this is;
var requestUri = GraphBaseUri + $"/v1.0/users/{upn}?$select=onPremisesSamAccountName";
var response = await _httpClient.GetAsync(new AuthenticationHeaderValue("Bearer", accessToken), requestUri).ConfigureAwait(false);
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var responseObj = JsonConvert.DeserializeObject<ResponseObj>(content);
return responseObj.OnPremisesSamAccountName;
Notice the select where we collect the onPremisesSamAccountName. Though, I haven´t found a comprehensive list of all attributes possible to retrieve which would have been nice.

Create OAuth2PermissionGrant for Resources via Graph

My scenario is to create app & spn via AAD Graph. That ist rather easy (with a redirect for browser-based consent), what I now want to do is consent the spn right away (like you can do in the portal). The code itself is straight-forward:
var g = new OAuth2PermissionGrant();
g.ClientId = thePrincipal.ObjectId;
g.ConsentType = "AllPrincipals";
g.PrincipalId = null;
g.ResourceId = ##resourceId##;
g.ExpiryTime = DateTime.Now.AddYears(10);
g.Scope = "User.Read";
await client.Oauth2PermissionGrants.AddOAuth2PermissionGrantAsync(g);
Now the part that I haven't figured out properly is ##resourceId##. This is supposed to be the resourceId - in the code sample, it should be Windows Azure Active Directory. How do I get the resourceId for eg the following required resource access (00000002-0000-0000-c000-000000000000):
RequiredResourceAccess =
new [] {
new RequiredResourceAccess() {
ResourceAppId = "00000002-0000-0000-c000-000000000000",
ResourceAccess = new [] {
new ResourceAccess() {
Id = new Guid("311a71cc-e848-46a1-bdf8-97ff7156d8e6"), // sign in and read profile (delegated perm)
Type = "Scope"
},
The lookup ResourceAppId -> resourceId (app to spn) is what I am missing. For eg AAD, Graph, manage.office.com et al.
From the documentation for the OAuth2PermissionGrant entity, the resourceId field of an OAuth2PermissionGrant is the objectId of the ServicePrincipal object for the resource:
Specifies the objectId of the resource service principal to which access has been granted.
So, from the tenant in which you are creating the OAuth2PemrissionGrant, you need to retrieve the ServicePrincipal object corresponding to the resource app you would like to grant permission to, and from that object, read the objectId property.
If you have the resource app's AppId, you can retrieve the corresponding ServicePrincipal object (if one exists) with:
GET https://graph.windows.net/{tenant}/servicePrincipals
?$filter=appId eq '{app-id-guid}'
&api-version=1.6
With Microsoft.Azure.ActiveDirectory.GraphClient (which I think is what you're using in your code), you would do this with:
graphClient.ServicePrincipals.Where(sp => sp.AppId == "{app-id-guid}")
If what you have to identify the resource app is not the Guid app ID, but a (somewhat) friendly identifier URI (e.g. "https://graph.microsoft.com"), you can retrieve the matching ServicePrincipal object by filtering on servicePrincipalNames.
With Azure AD Graph:
GET https://graph.windows.net/{tenant}/servicePrincipals
?$filter=servicePrincipalNames/any(n:n eq 'https://graph.microsoft.com'))
&api-version=1.6
With Microsoft.Azure.ActiveDirectory.GraphClient:
graphClient.ServicePrincipals
.Where(sp => sp.ServicePrincipalNames.Any(n => n == "https://graph.microsoft.com"))

Azure Graph service not finding newly created user

I have a web application that uses Azure ACS and Azure AD to handle our authentication.
We have a user management feature in the web application that allows a user to create new users. This takes the details such as username, password, email etc. and uses the graph service to create a user in azure.
var newUser = new Microsoft.WindowsAzure.ActiveDirectory.User
{
userPrincipalName = user.UserName,
mailNickname = user.MailNickname,
accountEnabled = true,
displayName = user.FirstName + " " + user.Surname,
givenName = user.FirstName,
surname = user.Surname
};
newUser.passwordProfile = new PasswordProfile
{
forceChangePasswordNextLogin = false,
password = user.Password
};
var graphService = GetGraphService(tenantName);
graphService.AddTousers(newUser);
graphService.SaveChanges();
We are then required to create a record in the web application database for this user. The record needs the object ID from azure. So we use the graphService to get the newly-created user details. This is where my problem lies. It doesn't find the user.
private string GetObjectIdFromAzure(string userName, string tenantName)
{
var graphService = GetGraphService(tenantName);
var users = graphService.users;
QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User> response;
response = users.Execute() as QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User>;
var user = response.FirstOrDefault(x => x.userPrincipalName == userName);
return user != null ? user.objectId : "";
}
My code was working without any issues for a few months and only today I am having issues. What frustrates me more it that I have another deployment of the same code where it works without any issues. Some differences between the two deployments are:
The deployments use different Access control namespaces in Azure
The deployments have separate applications in Azure AD
One is https, one is http
The users for both system are under the same Directory.
I have put in logging in both deployments to get the number of users returned by
users.Execute()
In both systems it reported 100 (they share the same users)
Any ideas of what would cause this to stop working? I didn't change any code relating to this recently, I haven't changed any configuration on Azure and I didn't change the web.config of the application
The problem was caused by the fact that I was filtering the users after retrieving them. The graph API was only returning a maximum of 100 users.
So the process was like so:
User created in Azure
Success message returned
Web App searches Azure for user to get Object ID
Graph Api only returns top 100 users. User was not in top 100 alphabetically so error thrown
The reason it was working on our second deployment was that I was prefixing the user name with demo_ (we use this site to demo new features before releasing). This meant that it was being returned in the top 100 users.
I changed the code as follows so it filters during the retrieval instead of after:
private Microsoft.WindowsAzure.ActiveDirectory.User GetUserFromAzure(string userName, string tenantName, out DirectoryDataService graphService)
{
graphService = GetGraphService(tenantName);
var users = (DataServiceQuery<Microsoft.WindowsAzure.ActiveDirectory.User>)graphService.users.Where(x => x.userPrincipalName == userName);
QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User> response;
response = users.Execute() as QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User>;
var user = response.FirstOrDefault();
return user;
}

Resources