Get Owner(s) in .NET Azure Active Directory groups - azure

I have an email account which is a Security Group where there are few members in it. I am trying to figure out the email address of the owner of the group but I haven't been able to figure it out.
Below is the source code
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, async () => await Task.FromResult(accessToken));
var group = (Group)await activeDirectoryClient.Groups.Where(u => u.Mail == "email#domaincom").ExecuteSingleAsync();.
var groupFetcher = activeDirectoryClient.Groups.GetByObjectId(group.ObjectId);
var membersResult = groupFetcher.Members.ExecuteAsync().Result;
var ownerResult = groupFetcher.Owners.ExecuteAsync().Result;
After I execute this code, I can see the members of the Group but why ownerResult variable is always empty? How can I retrieve the owner of the group?

I am testing using the code below(Microsoft.Azure.ActiveDirectory.GraphClient with version 2.1.1)and it works well for me. Please ensure that the group have the owners assigned.
var group = (Group) client.Groups.Where(u => u.Mail == "email#domain.onmicrosoft.com").ExecuteSingleAsync().Result;
var groupFetcher = client.Groups.GetByObjectId(group.ObjectId);
//var membersResult = groupFetcher.Members.ExecuteAsync().Result;
var ownerResult = groupFetcher.Owners.ExecuteAsync().Result;
foreach (var owner in ownerResult.CurrentPage)
Console.WriteLine(((Microsoft.Azure.ActiveDirectory.GraphClient.User)owner).DisplayName);
You can check it from Azure portal like figure below:
If the owner exists, I also suggest that you capture the request using Fiddler to check whether the response is expected.

Related

ASP.NET Identity using Azure Active Directory... when/how are AspNetUsers db records created

I have a simple MVC .Core 6 web application that will be used on the corporate extranet (via an azure app service).
I've setup Microsoft Identity for login/authentication. This works really well. User requests a page and they're sent off to the corporate azure active directory login page (include 2fa) and returned to the application authenticated with user claims.
BUT... my Identity database tables remain empty (AspNetUsers et al). I was half expecting a record to be created representing the user that just signed in.
I scaffolded the ExternalLogin.cshtml page expecting it to be displayed after a user logs in (and there I could manually create the user if userManager.GetUserAsync(User) == null). But the page is never shown
I think I want AspNetUsers table entries because my simple app does a bit of audit trail stuff (CreatedByUserId, LastUpdatedByUserId) and I would like these to be foreign keys to the AspNetUsers table.
Thoughts? Are my expectations out of whack?
I was way off base on this.
Microsoft.Identity.Web and Microsoft.Identity.Web.UI don't need/create AspNetUsers table (et al).
If you want to build your own users table when a user logs in to the application you can do the following:
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, opts =>
{
opts.Events = new OpenIdConnectEvents()
{
OnTicketReceived = async (context) =>
{
//
// Pull out the user details
//
var objectidentifier = context.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
var nameidentifier = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var name = context.Principal.FindFirstValue("name");
var email = context.Principal.FindFirstValue("preferred_username");
//
// Demo code to create a record in a users db table
//
using var scope = context.HttpContext.RequestServices.CreateScope();
var ctx = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
var isUserExists = await ctx.MyApplicationUser.AnyAsync(u => u.ObjectIdentifier == objectidentifier);
if (!isUserExists)
{
var applicationUser = new MyApplicationUser()
{
ObjectIdentifier = objectidentifier,
NameIdentifier = nameidentifier,
Email = email,
Name = name,
};
ctx.MyApplicationUser.Add(applicationUser);
await ctx.SaveChangesAsync();
};
}
};
});
Note that some care is needed to pull out the correct claims.
Note this should probably update an existing user if their details changed (names do change).
This is slightly modified from what I found at: https://dotnetthoughts.net/azure-active-directory-b2c-in-aspnet-core-mvc-part1/

C# How to get list of users in all roles in RBAC defined in a subscription using Microsoft.Azure.Management.Graph.RBAC.Fluent

How to get a list of users in all roles in RBAC defined in a subscription.
var authorityUri = $"https://login.microsoftonline.com/{tenantId}";
var scopes = new System.Collections.Generic.List<string> { "https://graph.microsoft.com/.default" };
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(appId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
var authenticated1 = Microsoft.Azure.Management.Fluent.Azure.Configure().Authenticate(credentials);
IRoleDefinition Rdef = authenticated1.RoleDefinitions.GetByScopeAndRoleName("/", "Owner");
Good so far. The inner Rdef give me the role name, ID, and Name and now I am trying to list all users in that subscription scope for that role.
var roleassignement1 = authenticated1.RoleAssignments.ListByScopeAsync("/");// GetById("*****")// .GetByScopeAsync("subscriptions/322dac8a-416c-4de6-977c-e6b21344651c", "Owner");
What is the scope here, I added the subscription/subid as scope. What I am trying to do is list all RBAC on the subscription.
What am I doing wrong? Any pointer is appreciated.
Regards.
Just change the code from:
var roleassignement1 = authenticated1.RoleAssignments.ListByScopeAsync("/");
to
var roleassignement1 = await authenticated1.RoleAssignments.ListByScopeAsync("subscriptions/322dac8a-416c-4de6-977c-e6b21344651c");
, and then it can work.

Azure authentification for multiple audience using WithExtraScopesToConsent and AcquireTokenSilent

I am building an app that let user manipulate Azure resource and Azure storage therefore I need to access multiple audiences, however, it's not possible to have one toke with multiple audience in azure. So I am using this tutorial
https://learn.microsoft.com/bs-latn-ba/azure/active-directory/develop/msal-net-user-gets-consent-for-multiple-resources
and my code look like :
IPublicClientApplication client = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
.WithDefaultRedirectUri()
// .WithRedirectUri($"msal{clientId}://auth")
.Build();
var accounts = client.GetAccountsAsync().Result;
string[] scopes = { "https://management.azure.com/user_impersonation" };
string[] scopestorage = { "https://storage.azure.com/user_impersonation" };
var result = client.AcquireTokenInteractive(scopes)
.WithAccount(accounts.FirstOrDefault())
.WithExtraScopesToConsent(scopestorage)
.ExecuteAsync().Result;
var result2= client.AcquireTokenSilent(scopestorage, accounts.FirstOrDefault()).ExecuteAsync();
but I am getting an exception while executing the AcquireTokenInteractive method
Microsoft.Identity.Client.MsalUiRequiredException: 'No account or login hint was passed to the AcquireTokenSilent call.'
Also when I look in the locals my variable "accounts" i can see Count=0 and nothing in there.
Any pointer for a solutions would be greatly appreciated.
Regards
Vincent
Your need to make some changes to your code. Here is the working sample for your reference:
string[] scopes = { "https://management.azure.com/user_impersonation" };
string[] scopestorage = { "https://storage.azure.com/user_impersonation" };
IPublicClientApplication client = PublicClientApplicationBuilder
.Create("cbc32712-ac27-4532-802d-303998a6e712")
.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
.Build();
var result = client.AcquireTokenInteractive(scopes)
.ExecuteAsync().Result;
var accounts = client.GetAccountsAsync().Result;
var result2 = client.AcquireTokenSilent(scopestorage, accounts.FirstOrDefault()).ExecuteAsync().Result;
Note:
1.As you will get access token for storage resource by using AcquireTokenSilent method, make sure you have granted user/admin consent for your application to access this resource.
2.You can not use WithExtraScopesToConsent method for different resource endpoints.

How to get groups that user belong to?

Using Graph Service, I have tried to get list of groups that user belong to. Here is my sample code:
var userMemberOf = null;
var userMemberGroups = null;
const GraphService = require('graph-service');
const ClientCredentials = require('client-credentials');
const tenant = 'my-company.com';
const clientId = '0b13aa29-ca6b-42e8-a083-89e5bccdf141';
const clientSecret = 'lsl2isRe99Flsj32elwe89234ljhasd8239jsad2sl=';
const credentials = new ClientCredentials(tenant, clientId, clientSecret);
const service = new GraphService(credentials);
service.get('/users/tnguyen482#my-company.com/memberOf').then(response => {
userMemberOf = response.data;
});
var settings = {
"securityEnabledOnly": true
}
service.post('/users/tnguyen482#my-company.com/getMemberGroups', settings).then(response => {
userMemberGroups = response.data;
});
The data return from both get & post method was an empty list. I have tried another user id but the result is the same. Am I correct when using method memberOf and getMemberGroups to get list of groups that user belong to? Does my sample code correct?
When the user is in no group graph will return an empty result.
Otherwise, when an error occured (e.g. accessDenied or user not found) an corresponding http-status with an errormessage will be returned (more information in the documentation).
The operations you are using seem to be correct.
If you want to rule out that your operations/code is incorrect, you should try executing the operations in the Graph Explorer.
Its a great tool for debugging and you can even login for access to your own data.

Get AccountName / UPN in a UWP App when logged on in Azure

I am creating a UWP app which shows certain data, depending on the logged on user.
The user is logged on in Windows Azure and the computer account is also joined to Azure.
I have enabled the "Account Information" feature in the app manifest.
I am trying to find out the user data, using the User Class, like mentioned in several examples online:
private async void GetAllUserData()
{
var users = await User.FindAllAsync();
foreach (var user in users)
{
var authenticationStatus = user.AuthenticationStatus;
var nonRoamableId = user.NonRoamableId;
var provider = await user.GetPropertyAsync(KnownUserProperties.ProviderName);
var accountName = await user.GetPropertyAsync(KnownUserProperties.AccountName);
var displayName = await user.GetPropertyAsync(KnownUserProperties.DisplayName);
var domainName = await user.GetPropertyAsync(KnownUserProperties.DomainName);
var principalName = await user.GetPropertyAsync(KnownUserProperties.PrincipalName);
var firstName = await user.GetPropertyAsync(KnownUserProperties.FirstName);
var guestHost = await user.GetPropertyAsync(KnownUserProperties.GuestHost);
var lastName = await user.GetPropertyAsync(KnownUserProperties.LastName);
var sessionInitiationProtocolUri = await user.GetPropertyAsync(KnownUserProperties.SessionInitiationProtocolUri);
var userType = user.Type;
}
}
The only properties I can get from the user object are:
DisplayName
AuthenticationStatus
NonRoamableId
UserType
All other properties remain empty. From my understanding, when I am logged in to Windows Azure, at least the principal name should have a value.
What am I doing wrong - or in other words - what do I have to do, to get account information?
After enabling "Enterprise Authentication" feature in my app manifest, the UPN is filled in the principalName variable.
I know, this does not the real authentication job for the application, but for my purpose it is sufficient to have the UPN, authenticated in Windows.
For more information about adding Azure authentication to an app I have found the following links:
https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-windows-store-dotnet-get-started-users
https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-native-uwp-v2/

Resources