How to create a API scope using Azure AD Graph API - c#

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.

Related

Microsoft Graph - Update mailbox settings with SDK

I'm trying to set automatic replies for Microsoft users using the example here.
The difference from the docs is that I'm trying to do this not for me, but for another user using permissions. Getting error: The OData request is not supported
The issue is mentioned here and here. But both are closed.
The one solution mentioned is here but for this I'm getting the error Access is denied. Check credentials and try again.
Does anyone know of a way to set automatic replies / update mailbox settings in microsoft graph using the c# sdk using the users option - not me?
Using application api permission is right here and we may also refer to the workaround mentioned by OP which worked for him.
===========================================
According to the api document, it support Application permission,
So could you pls try this code:
using Azure.Identity;
using Microsoft.Graph;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var mailboxSettings = new MailboxSettings
{
AutomaticRepliesSetting = new AutomaticRepliesSetting
{
Status = AutomaticRepliesStatus.Scheduled,
ScheduledStartDateTime = new DateTimeTimeZone
{
DateTime = "2022-07-03T18:00:00",
TimeZone = "UTC"
},
ScheduledEndDateTime = new DateTimeTimeZone
{
DateTime = "2022-07-07T18:00:00",
TimeZone = "UTC"
},
ExternalReplyMessage = "I'm on vacation.",
InternalReplyMessage = "I'm on vacation."
}
};
var user = new User();
user.MailboxSettings = mailboxSettings;
await graphClient.Users["user_id"].Request().UpdateAsync(user);
And pls don't forget to add Application api permission MailboxSettings.ReadWrite in Azure AD.

Microsoft Graph for reading my own calendar in C#?

I am not an expert on all things Azure, but I'd like to read my own calendar programmatically. I found some code to access Microsoft Graph and read my calendar, but it seems I have to create an App Registration first, is it possible to SKIP the app registration if I only need to read my OWN calendar? here's my starting point:
var scopes = new[] { "User.Read" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var userName = "myaccount#company.com";
var password = "pwdhere";
var userNamePasswordCredential = new UsernamePasswordCredential(
userName, password, tenantId, clientId, options);
var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);
var events = await graphClient.Me.Calendar.Events
.Request()
.Filter("startsWith(subject,'All')")
.GetAsync();
You need an app registration, otherwise you couldn't even log in. If it's an Azure AD you don't control, such as your employer, you'll need to get an admin to create that for you.

Graph API - adding Schema Extension using .Net Core 3.1

I need to add custom claims to my Azure B2C users, so I figured the way to do this is to add schema extensions to the User for my directory App with Graph API (beta).
I wrote a simple test for that:
SchemaExtension schemaExtension = new SchemaExtension
{
Id = schemaName,
Owner = _appClientId.ToString(),
Description = string.IsNullOrWhiteSpace(schemaDesc) ? string.Empty : schemaDesc.Trim(),
TargetTypes = new List<string>
{
"User"
},
Properties = new List<ExtensionSchemaProperty>
{
new ExtensionSchemaProperty
{
Name = "isGlobalAdmin",
Type = "Boolean"
},
new ExtensionSchemaProperty
{
Name = "isOrganizationAdmin",
Type = "Boolean"
}
}
};
SchemaExtension extension = await GraphClient.SchemaExtensions
.Request()
.AddAsync(schemaExtension);
First, it didn't work because of lack of permissions. So I created a new user in my directory and added Global Admin role to it. Then I set Treat application as a public client to true in the app authentication settings. That fixed permission problem.
But now I have this one:
Microsoft.Graph.ServiceException : Code: Service_InternalServerError
I tried changing params for the SchemaExtension but nothing helps.
How can I make this work?
API I use - Microsoft.Graph.Beta
UPDATE - Graph API init
private async Task<GraphServiceClient> InitGraphClientWithUserAndPassword()
{
try
{
IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
.Create(_appClientId.ToString())
.WithTenantId(_tenantId.ToString())
.Build();
UsernamePasswordProvider authProvider = new UsernamePasswordProvider(publicClientApplication); // scopes
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
SecureString securePass = new NetworkCredential("", _password).SecurePassword;
User me = await graphClient.Me.Request()
.WithUsernamePassword(_userEmail, securePass)
.GetAsync();
return graphClient;
}
catch (Exception ex)
{
const string ERR_MSG = "Could not create GraphAPI client";
_logger.LogError(ex, ERR_MSG);
throw new IlgGraphApiException(ERR_MSG, ex);
}
}
I have tested your code. It works fine for Azure AD but gets error Code: Service_InternalServerError\r\nMessage: Encountered an internal server error.\r\n\r\nInner error\r\n for Azure AD B2C.
I don't think Microsoft Graph API Create schemaExtension is supported for Azure AD B2C currently.
As this article says, Custom attributes in Azure AD B2C use Azure AD Graph API Directory Schema Extensions. Support for newer Microsoft Graph API for querying Azure AD B2C tenant is still under development.

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 Active Directory - how to assign application role to group programmatically

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

Categories

Resources