Azure Active Directory - how to assign application role to group programmatically - c#

I am looking to create a role based authorization mvc application using Azure AD:
Create a .NET MVC web app in Azure App Service with Azure Active Directory authentication
Azure Role-based Access Control
From the Azure Portal, I am able :
To create user and groups.
To assign user to group.
To create applications roles.
To create application roles (by modifying the manifest)
To assign an application role to a user.
I've just had a free Azure Active Directory edition and I've readed that we can use the Microsoft Azure Active Directory to perform these actions :
To assign multiple application roles to users.
To assign multiple application roles to groups.
Microsoft provides good samples to query the AAD and I've started with it but I can't figured out how to assign an application to a group.
Here is my pseudo code to get the group:
ActiveDirectoryClient client = AuthenticationHelper.GetActiveDirectoryClient();
var app = (await client.Applications.GetByObjectId("applicationObjectId").ExecuteAsync());
var servicePrincipal = await client.ServicePrincipals.GetByObjectId("servicePrincipalObjectId").ExecuteAsync();
var appRole = app.AppRoles.First(r => r.DisplayName == "my role");
var mygroup = (await client.Groups.ExecuteAsync()).CurrentPage.FirstOrDefault();
What I would like to do is something like that :
mygroup .AppRoleAssignments.Add(new AppRoleAssignment()
{
ResourceId = Guid.Parse(servicePrincipal.ObjectId),
Id = appRole.Id,
PrincipalType = "Group",
PrincipalId = Guid.Parse(mygroup .ObjectId),
});
await group.UpdateAsync();
But the type of the AppRoleAssignments is IPagedCollection<IAppRoleAssignment> and there is no Add method.
Does anyone knows what I need to chage in my code ?

In fact it was simple... I had to cast the IGroup as a Group :
ActiveDirectoryClient client = AuthenticationHelper.GetActiveDirectoryClient();
var app = (await client.Applications.GetByObjectId("applicationObjectId").ExecuteAsync());
var servicePrincipal = await client.ServicePrincipals.GetByObjectId("servicePrincipalObjectId").ExecuteAsync();
var appRole = app.AppRoles.First(r => r.DisplayName == "my role");
var mygroup = (Group)(await client.Groups.ExecuteAsync()).CurrentPage.FirstOrDefault();
And it works fine ^^ :
mygroup .AppRoleAssignments.Add(new AppRoleAssignment()
{
ResourceId = Guid.Parse(servicePrincipal.ObjectId),
Id = appRole.Id,
PrincipalType = "Group",
PrincipalId = Guid.Parse(mygroup .ObjectId),
});
await group.UpdateAsync();

Related

Authenticate at subscription level using Azure SDK

I'm trying to get a list of App Services from a subscription so that I can filter staging sites and delete them using the Azure SDK. I'm running into the issue of not authenticating properly or not being able to see any resources on the subscription.
I have the "Owner" role on the subscription so I should have total access to the subscription and its resources however when trying to follow Microsoft's docs on authenticating (https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication) I can't seem to find a way to authenticate at the subscription level.
Here's the code I have:
var azurecreds = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(
"???", //client ID
"???", //client secret
"have this", //tenant ID
AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.Authenticate(azurecreds)
.WithSubscription("have this"); //subscription ID
//attempts with hard-coded values but not working
var appServicePlans = azure.AppServices.AppServicePlans.List();
var appServicePlans2 = azure.WebApps.List();
var appServicePlans2 = azure.AppServices.AppServicePlans.ListByResourceGroup("Staging");
As you are following this document : Authenticate with token credentials
So , as per the above document , you must have created a service principal using this command :
az ad sp create-for-rbac --sdk-auth
After you have create this service principal , you will get the below details :
From the above picture you have to copy the ClientID, Client Secret, TenantID and SubscriptionId. After you have taken a note of these mentioned details , you can put the same in the code .
var azurecreds = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(
"ClientID copied from the above step", //client ID
"Client Secret Copied from the above step", //client secret
"have this", //tenant ID
AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.Authenticate(azurecreds)
.WithSubscription("have this"); //subscription ID
//attempts with hard-coded values but not working
var appServicePlans = azure.AppServices.AppServicePlans.List();
var appServicePlans2 = azure.WebApps.List();
var appServicePlans2 = azure.AppServices.AppServicePlans.ListByResourceGroup("Staging");

How to create a API scope using Azure AD Graph API

I'm trying to use the Azure AD Graph API to create an API Scope for an Azure AD B2C application. This is the operation performed using the "Expose an API" blade in the portal.
I've tried adding the scope directly to the application like so:
var current = await graphClient.Applications[appId].Request().GetAsync();
var currentList = current.Api.Oauth2PermissionScopes ?? new List<PermissionScope>();
var newScope = new PermissionScope
{
AdminConsentDescription = scopeDescription,
AdminConsentDisplayName = scopeDescription,
IsEnabled = true,
Type = "Admin",
Value = scopeName
};
var updated = new Application {
Api = new ApiApplication {
Oauth2PermissionScopes = currentList.Append(newScope).ToList()
}
};
await graphClient.Applications[appId].Request().UpdateAsync(updated);
However, when I do that, I get an exception:
Microsoft.Graph.ServiceException
Code: ValueRequired
Message: Property api.oauth2PermissionScopes.id value is required but is empty or missing.
Does this mean that I need to create the scope separately then add it to the application? Looking over the Graph API docs, it isn't obvious how to do that and I haven't found any articles that discuss it, either.
How do you use Graph API to create API scopes?
if you want to use the Microsoft Graph API to create an API Scope for an Azure AD B2C application, we need to define PermissionScope object. The object should provide id(it is GUID).
For example
Register Application
Grant API permissions
Under Manage, select API permissions.
Under Configured permissions, select Add a permission.
Select the Microsoft APIs tab, then select Microsoft Graph.
Select Application permissions.
Select the checkbox of the permission Application.ReadWrite.All to grant to your application.
Select Add permissions. As directed, wait a few minutes before proceeding to the next step.
Select Grant admin consent for (your tenant name).
Create a client secret
code
static async Task Main(string[] args)
{
string clientId = "0159ec7d-f99f-***";
string clientSecret = "G_fM3QKa***essTRX23t1_o";
string tenantDomain = "{your tenat name}.onmicrosoft.com";
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantDomain)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var id = "fa89ac50-d5fd-47cb-9f3f-833f413a2ed4";
var app =await graphClient.Applications[id].Request().GetAsync();
var updated = new Application();
if (app.IdentifierUris.ToList().Count == 0) {
updated.IdentifierUris = new string[] { $"https://{tenantDomain}/{app.AppId}" };
}
var appscope = app.Api.Oauth2PermissionScopes.ToList();
var newScope = new PermissionScope
{
Id = Guid.NewGuid(),
AdminConsentDescription = "Allow the application to have read-only access to all Employee data",
AdminConsentDisplayName = "Read-only access to Employee records",
IsEnabled = true,
Type = "Admin",
Value = "Employees.Read.All"
};
appscope.Add(newScope);
updated.Api = new ApiApplication { Oauth2PermissionScopes =appscope };
await graphClient.Applications[id].Request().UpdateAsync(updated);
}
For more details, please refer to here.

AADSTS500011 - PowerBi C# .NET (resource x not found in tenant y)

I am trying to integrate the power bi embedded with C#, I always have this same error that comes out, I put it to you just below, as well as the versions of the packages and the code (basic) which is supposed to do the work .
Thank you for all your answers
Microsoft.PowerBI.Api (v2.0.12)
Microsoft.PowerBI.JavaScript (v2.5.1)
Microsoft.IdentityModel.Clients.ActiveDirectory (v3.13.9)
Microsoft PowerBI JavaScript (v2.5.1)
Microsoft IdentityModel Clients.ActiveDirectory (v3.13.9)
Note that the two head variables are temporary.
The error always come out at this line : var authenticationResult = await authenticationContext.AcquireTokenAsync(this.resourceUrl, this.applicationId, credential);
There is the error message : "exceptionMessage": "AADSTS500011: The resource principal named https://analysis.windows.net/powerbi/api/ was not found in the tenant named x. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
public async Task<EmbedConfigResource> EmbedReport([FromUri]string username, [FromUri]string roles)
{
roles = "None";
username = this.pbiUsername;
var result = new EmbedConfigResource { Username = username, Roles = roles };
var credential = new UserPasswordCredential(this.pbiUsername, this.pbiPassword);
var authenticationContext = new AuthenticationContext(this.authorityUrl);
var authenticationResult = await authenticationContext.AcquireTokenAsync(this.resourceUrl, this.applicationId, credential);
var tokenCredentials = new TokenCredentials(authenticationResult.AccessToken, "Bearer");
using (var client = new PowerBIClient(new Uri(this.apiUrl), tokenCredentials))
{
var reports = await client.Reports.GetReportsInGroupAsync(this.workspaceId);
Report report = reports.Value.FirstOrDefault(r => r.Id == this.reportId);
var datasets = await client.Datasets.GetDatasetByIdInGroupAsync(this.workspaceId, report.DatasetId);
result.IsEffectiveIdentityRequired = datasets.IsEffectiveIdentityRequired;
result.IsEffectiveIdentityRolesRequired = datasets.IsEffectiveIdentityRolesRequired;
GenerateTokenRequest generateTokenRequestParameters;
var rls = new EffectiveIdentity(this.pbiUsername, new List<string> { report.DatasetId });
if (!string.IsNullOrWhiteSpace(roles))
{
var rolesList = new List<string>();
rolesList.AddRange(roles.Split(','));
rls.Roles = rolesList;
}
generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view", identities: new List<EffectiveIdentity> { rls });
var tokenResponse = await client.Reports.GenerateTokenInGroupAsync(this.workspaceId, report.Id, generateTokenRequestParameters);
result.EmbedToken = tokenResponse;
result.EmbedUrl = report.EmbedUrl;
result.Id = report.Id;
return result;
}
}
You must log into Azure portal, go to Azure Active Directory -> App registrations, select your app, click View API permissions, and then grant admin consent by clicking the button at the bottom:
If you don't have access to the portal, or the button is disabled, you must ask your admin to do it for you.

Azure AD Graph API - Assign user to applications using C#

I found that Applications can be assigned to users in this answer but can't seem to figure out how to do this using C#. Below is the JSON and the C# I'm trying.
Azure Active Directory: assign user to an application from the gallery via Graph API
Assign principal (user or group) to application:
•resourceId is the objectId of the servicePrincipal that get created in the tenant for the application
•id is the default role id of App.
•principalId is the objectId of the principal (user or group) that is being assigned to the app.
HTTP POST https://graph.windows.net/7fe877e6-a150-4992-bbfe-f517e304dfa0/users/de4b092e-1dd4-4d40-b74d-a2d7096c9495/appRoleAssignments?api-version=1.5
Authorization : Bearer eyJ0eXAiOi--snip--JKVBfk_Q
Content-Type : application/json
Content-Length : 176
{
"id": "fc60bc23-43df-4a60-baaa-f0b8694e0259",
"principalId": "de4b092e-1dd4-4d40-b74d-a2d7096c9495",
"resourceId": "93c60e8e-74f9-4add-9ae2-dd9bc0d6edcd"
}
AppRoleAssignment appAssignment = new AppRoleAssignment();
appAssignment.Id = appRole.Id;
appAssignment.PrincipalId = new Guid(retrievedUser.ObjectId);
appAssignment.ResourceId = new Guid("aa9b2f6b-6528-4552-a202-2039ce86d95c");
appAssignment.UpdateAsync();
A little late to the party BUT! Since the documentation is completly missing I had to do a lot of googling and trail & error.
The solution is to update the user like this:
var appRoleAssignment = new AppRoleAssignment()
{
ResourceId = Guid.Parse(principal.ObjectId),
PrincipalId = Guid.Parse(user.ObjectId),
Id = Guid.Parse(roleId)
};
user.AppRoleAssignments.Add(appRoleAssignment);
await user.UpdateAsync();

Retrieving all Users using Google Apps Provisioning API?

I am trying to retrieve all users in domain but it's never work. I never got any error in my code.
I am adding as reference Google.GData.Apps.dll in my project. I am using Google Apps Provisioning API. I am referring these link https://developers.google.com/google-apps/provisioning/
Code :-
string domain = #"<domain name>";
string subs = #"<Authorization code>";
AppsService appService = new AppsService(domain, subs);
// appService.CreateUser("john.jain","James","anderson","james#1234");
// appService.DeleteUser("Amitesh");
appService.RetrieveAllUsers();
The following works for me - RetrieveAllUsers() returns a UserFeed object containing all users. Note that I am using a different constructor for the apps service (using username/password credentials and not OAuth).
this.appsService = new AppsService(credential.Domain, credential.Username, credential.Password);
UserFeed userFeed = this.appsService.RetrieveAllUsers();
// Selecting all users except domain super administrators.
var usernamesInDomain =
(from UserEntry user in userFeed.Entries
where user.Login.Admin != true
select user.Login.UserName).ToList();
What does the returned UserFeed object contain in your case?
This is my solution :-
Google.GData.Apps.UserFeed s = appService.RetrieveAllUsers();
foreach (UserEntry s1 in s.Entries)
{
string username = s1.Login.UserName.ToString();
}

Categories

Resources