Add user to Directory role in azure active directory via Microsoft graph SDK\API - azure-active-directory

I've created an API project in dotNet to get some data from microsoft.graph using SDK.
I managed to get all the users and all groups and see the role of each user (like Billing administrator / Application administrator, etc.), but I can not find a way to update or change the role to a user or group through the SDK / API.
I guess right now this option is not supported through API / SDK. Am I right?

You can do a HTTP request to the directory role using role-id or role-templateid for adding the user:
POST /directoryRoles/{role-id}/members/$ref
POST /directoryRoles/roleTemplateId={roleTemplateId}/members/$ref
Example :
POST https://graph.microsoft.com/v1.0/directoryRoles/fe8f10bf-c9c2-47eb-95cb-c26cc85f1830/members/$ref
or
POST https://graph.microsoft.com/v1.0/directoryRoles/roleTemplateId=88d8e3e3-8f55-4a1e-953a-9b9898b8876b/members/$ref
Content-type: application/json
{
"#odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/UserObjectID"
}
You can use C# to add user to directory role :
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var directoryObject = new DirectoryObject
{
Id = "bb165b45-151c-4cf6-9911-cd7188912848"
};
await graphClient.DirectoryRoles["{directoryRole-id}"].Members.References
.Request()
.AddAsync(directoryObject);
Reference :
Add user to directory role
Directory Role Id's

Related

How to get the resourceId when granting an appRoleAssignment to a ServicePrincipal in Azure AD?

I am trying to Grant Admin Consent of a API in an Azure AD application through Graph API. I created the App, created its Client Secret, then created a Service Principal to which I want to add AppRoleAssignment.
The API call to do so requires three attributes in the body (Documentation)
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var appRoleAssignment = new AppRoleAssignment
{
PrincipalId = {Input the Service Principal Id},
ResourceId = {? Where to get this value?},
AppRoleId = {Input the App role of the API I added to my Azure AD App}
};
await graphClient.ServicePrincipals["{servicePrincipal-id}"].AppRoleAssignments
.Request()
.AddAsync(appRoleAssignment);
My question is where to get the ResourceId from? Knowing that this is different from one tenant to the other.
Please note that if I grant the admin consent manually, then run this API call
var appRoleAssignments = GraphAppClient.ServicePrincipals[servicePrincipalId].AppRoleAssignments.Request().GetAsync().Result;
Then revoke the consent, get the ResourceId from what the API returned, and then use it in the original call, the admin consent works fine.
The documentation for the appRoleAssignment resource type says the following about the resourceId property:
The unique identifier (id) for the resource service principal for which the assignment is made.
A good approach to find a service principal in a tenant is to search the servicePrincipals collection, filtering on the appId or servicePrincipalName properties.For example, to search for the Microsoft Graph service principal by its identifier URI:
GET https://graph.microsoft.com/v1.0/servicePrincipals
?$filter=servicePrincipalNames/any(n:n eq 'https://graph.microsoft.com')
Or to find it by its appId:
GET https://graph.microsoft.com/v1.0/servicePrincipals
?$filter=appId eq '00000003-0000-0000-c000-000000000000'
With the Microsoft Graph SDK for .NET, this would look something like this:
var r = await graphServiceClient.ServicePrincipals
.Request()
.Filter("appId eq '00000003-0000-0000-c000-000000000000'")
.GetAsync();
Using Microsoft Graph PowerShell, things look very similar:
$r = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
Using the Azure portal, each app under "Enterprise apps" corresponds to a service principal, and the "Properties" page shows its object ID.
(Once you have the service principal, you can use its appRoles collection to see the list of app roles it publishes, often useful to get the app role's id, which you'll need for the appRoleId property.)
I ended up figuring it out. The resourceId of every set of permission you are trying to add is the objectId of the app in Entreprise Applications. It sounds very confusing, but if you are trying to add Graph API permissions, you need to go to enterprise applications, find GraphAPI, and then find its ObjectId. That is your resourceId.

Microsoft graph API: permission grant for application (app roles) (NOT delegate via Oauth2PermissionGrants)

We are using the Microsoft graph API (.net SDK).
We know that we can use GraphServiceClient.Oauth2PermissionGrants for delegated grant (in Azure AD app it's "Expose an API").
But when it comes to granting admin consent for application type (via app role of other applications), like below:
In the portal, we can just click "Grant admin consent for XXXX".
I could not figure out how to GraphServiceClient.PermissionGrants does not seem to be the one we are after.
Googled around, found the related answer Azure OAuth: Unable to programmatically create app with admin consent for permissions , which leads me to the actual API used https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignedto?view=graph-rest-1.0&tabs=csharp
In a nutshell, use app role assignment via AppRoleAssignedTo:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var appRoleAssignment = new AppRoleAssignment
{
PrincipalId = Guid.Parse("THE-OBJECT-ID-OF-THE-PRINCIPAL-OF-THE-AZURE-AD-APPLICATION-THAT-NEEDS-ACCESS"),
ResourceId = Guid.Parse("THE-OBJECT-ID-OF-THE-PRINCIPAL-OF-THE-AZURE-AD-APPLICATION-THAT-HAS-THE-APP-ROLE-DEFINED"),
AppRoleId = Guid.Parse("THE-ID-OF-THE-APP-ROLE-DEFINED-IN-THE-RESOURCE-ID-ABOVE")
};
await graphClient.ServicePrincipals["THE-OBJECT-ID-OF-THE-PRINCIPAL-OF-THE-AZURE-AD-APPLICATION-THAT-HAS-THE-APP-ROLE-DEFINED"].AppRoleAssignedTo
.Request()
.AddAsync(appRoleAssignment);

Azure One Drive access using Username/password auth (native app)

Business Requirement
OneDrive to have a user level folder created and shared to specific members of team.
Owning user to create folders for project and assign exclusive permissions to certain members (remove access to non-project members)
Technical Environment
One Drive access via Graph API
ADAL Auth
Web Job hosted as NativeJob in Azure App and granted required OneDrive access.
App registered in mine (not the account used to access OneDrive)
Current Effort
Since web-api & web apps cannot use username/password auth, required to access a specific user's drive, resorted to WebJob (not sure if it complies as native app).
WebJob tries to auth using the drive owner's credential but fails with message (AADSTS65001: The user or administrator has not consented to use the application with ID '<appId>' named 'OneDriveFileSystem'. Send an interactive authorization request for this user and resource.)
Code
Auth Request
UserCredential uc = new UserPasswordCredential(userName, password);
AuthenticationResult result = null;
try
{
var authContext = new AuthenticationContext(authority);
result = authContext.AcquireTokenAsync(resource, clientId, uc).Result;
}
catch (Exception ee)
{
return string.Empty;
}
return result.AccessToken;
OneDriveAccess
string accessToken = GetAuthToken();
if (!string.IsNullOrEmpty(accessToken))
{
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
string payload = "{ \"name\": \"" + projectRequest.ProjectName + "\" , \"folder\": { } }";
HttpContent content = new StringContent(payload,
System.Text.Encoding.UTF8,
"application/json");
Uri uri = new Uri(resource + "/v1.0" + RootFolderItemId + RootFolderItemId + "/children");
HttpResponseMessage response = httpClient.PostAsync(uri, content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
}
}
(results in 404, however same url works in Graph Explorer)
Question
Is this design correct or am I missing some critical element?
Do I need to register the app in the account which is used for OneDrive access or can it be allowed to register in any user's account as long as the keys are correct?
If I update the code to use my credential, it asks for multi-factor auth (enabled by admin), but since this is native, this cannot be provided. The drive owner account was created as a service one, so MFA is not applicable to that.
Any other code/configuration required can be provided
Update 1
Using the "me" based endpoint (to default to self's folder) results in a 403 Forbidden, even though I am sending a valid access token. Have granted all permissions for file access (see attached image). The Grant Permission is successful for all demanded permissions.

How to Authenticate MS Teams User Against Azure AD

I am trying to create a bot which would be deployed into MS Teams (and Skype for Business). I see when a user interacts with the bot they are provided with a channelData.tenant.id and the Bot Framework docs say that this is the "The tenant ID for the user." I was wondering if I can use this (or another piece of information coming from the inbound message) to authenticate the user against my Azure AD? Also, would this require me to authenticate the user via an authentication flow like is done with the AuthBot?(https://github.com/MicrosoftDX/AuthBot)
Any help would be great!
You have the tenant.id provided in channelData yes, so you could use it to make some customs requests like with Graph API.
For MS Teams, you can also get more information by calling GetConversationMembersAsync and call AsTeamsChannelAccount method on the members that you got (this method is included in Microsoft.Bot.Connector.Teams NuGet package)
Sample:
// Fetch the members in the current conversation
var connector = new ConnectorClient(new Uri(context.Activity.ServiceUrl));
var members = await connector.Conversations.GetConversationMembersAsync(context.Activity.Conversation.Id);
// Concatenate information about all the members into a string
var sb = new StringBuilder();
foreach (var member in members.Select(m => m.AsTeamsChannelAccount()))
{
sb.AppendLine($"GivenName = '{member.Name}', Email = '{member.Email}', User Principal Name '{member.UserPrincipalName}', AAD ObjectId '{member.ObjectId}', TeamsMemberId = '{member.Id}'");
}
// Post the member info back into the conversation
await context.PostAsync($"People in this conversation: {sb.ToString()}");
With this call you will have additional interesting values: Email and ObjectId (which is the user's Azure AD object ID).
As a conclusion, you still have to log your user if you need to do some authenticated logic, but in MS Teams case you have more information and ways to do it.

Adding users with roles into app registration

I can see you can create app registrations with graph API but is it possible to add users and roles to an app registration?
If you want to assign a user to that application, in one of the specified app roles, you'll need to set the appRoleAssignment on the user . If using Azure AD Graph api , you could use below rest api :
https://graph.windows.net/{tenant-id}/users/{username}/appRoleAssignments?api-version={api-version}
Content-Type:application/json
Authorization: Bearer {token}
{
"id": "RoleID",
"principalId": "UserObjectID",
"principalType": "User",
"resourceId": "servicePrincipalID"
}
id: This is the Id for the Role you are assigning. These Ids can be found in the Application's Manifest. Or you could use below api to get the specific role defined for your application(appRoles claim):
https://graph.windows.net/{tenant}/applications/{ObjectIDOfApplication}?api-version=1.6
principalId :This is the Obeject Id of the User you are assigning the role to.
principalType :If you are assigning this role to a User then this is set to the string User .
resourceId : Service Principal ID of the application . To get service principal id , you could use below api (objectId claim) :
https://graph.windows.net/{tenant}/servicePrincipals?api-version=1.6&$filter=appId eq 'appid'
Application role assignments are available in the Microsoft Graph Beta endpoint: see Update approleassignment
To give you an idea of what could do to add app role assignments to a user, I suggest you look at the Configure.ps1 PowerShell script of the active-directory-dotnet-webapp-roleclaims sample on GitHub, which creates test users of a given role and updates the application registration. This is in PowerShell, but you should be able to adapt it to using MSGraph

Resources