Not able to get all users from Azure Active Directory - c#

I am using solution mentioned here to get all users from Active Directory however I suspect the code is pulling disabled users from our old Active Directory. The new one is Azure Active Directory. Please let me know what change is required to get below details of only active users from Azure Active Directory:
First Name
Last Name
Email
Enterprise ID

Getting all users in Azure AD can use Microsoft Graph API. Here's the API for listing users. But it doesn't support personal Microsoft account, it only supports work or school accounts. By the way, I'm not sure what is Enterprise ID, could you pls take a look at this section to check if this API contained it?
I assume you have an asp.net core WEB API which is used to getting user list. So you should use code like below.
using Microsoft.Graph;
using Azure.Identity;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "aad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var users = await graphClient.Users.Request().GetAsync();
Then an Azure AD application is required for the variables in code above. Pls follow this document to register the Azure AD app. Since my assumption is based on a web API, no need to add redirect URL here. Now we can get tenantId , clientId in Overview blade, and created the client secret. We also need to modify API permissions blade and add required API permissions. What we need is Application permission User.Read.All,User.ReadWrite.All,Directory.Read.All, Directory.ReadWrite.All.

Related

Microsoft Graph Api - upload file and invalidRequest

I have a problem uploading files to sharepoint using the graph api.
With the token downloaded from https://developer.microsoft.com/en-us/graph/graph-explorer everything works fine. I get a response with a status of 200.
However, when I want to upload a file with a token received from AD I get an invalid request.
In the scope of my token there is: "Files.ReadWrite Files.ReadWrite.All Group.Read.All Group.ReadWrite.All GroupMember.Read.All GroupMember.ReadWrite.All openid profile Sites.Read.All Sites.ReadWrite.All User.Read email".
Reading the file list works without any problems
Below is the code on how I generate the token to Graph Api
Firstly, pls don't show your code in your picture because we can't copy code from picture directly so that we can't test your code and reproduce your issue.
In your screenshot, I can see you used https://graph.microsoft.com/.default as the scope, and since you used a console application, so you should use client credential flow to generate the author provider so that you can generate a correct access token. And this can also explain why you used the token obtained from graph explorer can work. When we use graph explorer, it will ask us to sign in first so that it can generate an access token which containing delegate api permission. And in your code you used var authProvider = new DelegateAuthenticationProvider.
You also shared the api permissions, but when you used client credential flow, you have to set the application api permission but not the delegate api permission. For this upload file api, the permission should be Files.ReadWrite.All, Sites.ReadWrite.All. Pls don't forget the give the api permission.
By the way, since you've used the graph SDK, you can use my code snippet to call graph api.
using Microsoft.Graph;
using Azure.Identity;
var scopes = new[] { "https://graph.microsoft.com/.default" };
string tenantId = "TenantId";
string clientId = "ClientId";
string clientSecret = "ClientSecret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var uploadFile = await graphClient.Drives[drives].Root.xxxx;

Authenticate Office 365 IMAP Account using Unattended C# Console

I am developing a .NET Core Console Application (C#) that needs to authenticate to an Office 365 IMAP account. The purpose is to retrieve mail and process CSV file attachments unattended.
The app has been registered on Azure as a Mobile/Desktop app with the RedirectUri set as http://localhost.
The following code causes a new tab to open in Chrome web browser and asks for the Outlook account to use for login. I need to stop the browser from opening and handle authentication completely from code.
Current Code:
using var client = new ImapClient(new ProtocolLogger("imap.log"));
var options = new PublicClientApplicationOptions
{
ClientId = _options.ClientId,
TenantId = _options.TenantId,
RedirectUri = "http://localhost"
};
var publicClientApplication = PublicClientApplicationBuilder
.CreateWithApplicationOptions(options)
.Build();
var scopes = new[]
{
"email",
"offline_access",
"https://outlook.office.com/IMAP.AccessAsUser.All" // Only needed for IMAP
//"https://outlook.office.com/POP.AccessAsUser.All", // Only needed for POP
//"https://outlook.office.com/SMTP.AccessAsUser.All", // Only needed for SMTP
};
var cancellationToken = new CancellationToken();
var authToken = await publicClientApplication
.AcquireTokenInteractive(scopes)
.ExecuteAsync(cancellationToken);
await publicClientApplication
.AcquireTokenSilent(scopes, authToken.Account)
.ExecuteAsync(cancellationToken);
SaslMechanism oauth2;
if (client.AuthenticationMechanisms.Contains("OAUTHBEARER"))
{
oauth2 = new SaslMechanismOAuthBearer(authToken.Account.Username, authToken.AccessToken);
}
else
{
oauth2 = new SaslMechanismOAuth2(authToken.Account.Username, authToken.AccessToken);
}
await client.AuthenticateAsync(oauth2);
await client.DisconnectAsync (true);
This line triggers a browser window to open https://login.microsoftonline.com/:
var authToken = await publicClientApplication
.AcquireTokenInteractive(scopes)
.ExecuteAsync(cancellationToken);
This console application will be run unattended. How do I obtain the token and authenticate without a web browser opening up?
This is an answear to your latest comment, as it's my final recommendation. So, first of all, you should decide if you want to acess the data on behalf of user, or as an app granted permissions by admin.
First step is to register your app.
Second step is getting the acess token. This is going to differ based on the method you chose. Tutorial for each: acting on behalf of the user or acting without the user, but granted permission from admin.
Once you have the acess token, you can call the Microsoft Graph API. The important thing is, you always have to call Microsoft Graph API. There is no other official way (as far as I know) of comunicating with Microsoft's services. You can try the requests with the Microsoft Graph Explorer, however it's VERY limited with it's defaul urls/parameters, so I suggest taking a look at the docs.
From what you've described, you first want to obtain UserID. The way of doing this is going to vary based on what type of auth you chose.
If you chose to act on behalf of user, you should be able to get that (ID) using this endpoint: https://graph.microsoft.com/v1.0/me/
If you chose to act as an app with admin consent, you should be able to search for user using the https://graph.microsoft.com/v1.0/me/people/?$search= with search query parameters. Here are the docs for this endpoint
Now, the only thing left, is to supply that ID to one of the Outlook api methods. You can find docs for them here. Specifically, it seems like you want to list all messages and then read a specific message.
Also, keep an eye on what methods you use with which type of auth. On behalf of user, you usually want url's that contain /me, on behalf of app with given admin privelages, you usually want some endpoint that enables you to pass user id.
Hope I helped!
PS: There is no code in this response, because there is a lot of stuff that just cannot be coded without your decisions, actions on Azure and so on. I suggest you read a little bit about auth and graph api using microsoft docs I linked earlier.
This code worked for me using MSAL after registering the app in azure and getting a client secret.
var options = new ConfidentialClientApplicationOptions
{
ClientId = "<ClientID or Application ID>",
TenantId = "<Azure TenantId>",
RedirectUri = "http://localhost"
};
string clientSecret = "<Client Secret Goes here>";
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.CreateWithApplicationOptions(options)
.WithClientSecret(clientSecret)
.Build();
var scopes = new string[] {
"https://outlook.office365.com/.default"
};
var authToken = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync();

Authenticating to Azure Devops Git repo

We are working on a system to automatically commit generated projects into Git repositories located in Azure Devops. We want to use libgit2sharp for this. We want the user to authenticate using their Microsoft account, grab the Access Token(jwt) from the authentication request and use that as means of authentication. But we cannot seem to get this working.
In another post I read 2 other authentication methods: 1. Alternative accounts. 2. Personal Access Tokens, PAT. Both made in the profile sections of your devops account.
I can get Alternative accounts to work perfectly but this is not our preferred route as it will require extra actions from the user. The PAT does not seem to work for me and throws me an error that there were "too many redirects or authentication replays". I figured this is because of the two factor authentication that is enabled on the Microsoft account.
Is it even supported to use an Access Token(jwt) in LibGit2Sharp with 2FA enabled?
using (var repo = new Repository({repo location}))
{
foreach (var file in file)
{
repo.Index.Add(file.Path);
repo.Index.Write();
}
var author = new Signature("{name}", "{name}", DateTime.Now);
var committer = author;
repo.Commit("Here's a commit i made!", author, committer);
var options = new PushOptions();
options.CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials() { Username = "{username}", Password = "{password}" };
repo.Network.Push(repo.Branches["master"], options);
}
Personal Access Tokens (PAT) do bypass MFA so that is probably not the error you're getting. A PAT is your best option, at the moment of the push you need the remote-url of your local Git repo to be as follows:
https://pat:{PAT_HERE}#dev.azure.com/...
e.g.
https://pat:gaakbfootuial7ksj4uv55o52335tyhhaasbqdvbg5xgyy33t754#dev.azure.com/auroraloop/devenv/_git/devenv
Tips:
The PAT will take the permissions of the Azure DevOps user that generated it so the user must have contribute permissions to the repo.
You cannot automate PAT creation, you must have it upfront stored somewhere, if you don't want to hardcode this (you shouldn't) consider using an Azure Key Vault to store and retrieve the value I'm sure they have c# libraries.
The options.CredentialsProvider part of your code is probably doing exactly what I mentioned about the remote-url try setting it as follows:
options.CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials() { Username = "pat", Password = "{PAT_HERE}" };
Hardcode the PAT for testing and if successful take a look at the Azure Key Vault approach.

Getting Registered App Display Name from an App Id

I have an Azure App Id which I have obtained from a token. I would like to get the display name of the application using C# so that I can add it to logs and Application Insights custom properties for a request. It is obviously more human-readable than an Id hence my need.
When I go into the portal I can go to the app registrations and type the AppId in and it shows me the name, so clearly it can be obtained (I can see from the URL https://graph.windows.net/myorganization/applications/?api-version=2.0&$top=40&$filter=appId%20eq%20%27MYAPPID%27), but how do I get this information programmatically in C#?
I could maintain my own lookup table somewhere which converts app ids to names, but this seems pointless when the information is obviously available at runtime.
If you want to get the information about your application in your c# application, you can use Microsoft.Graph.Beta to call the API. For example
Register a new application using the Azure portal
Sign in to the Azure portal using either a work or school account or
a personal Microsoft account.
If your account gives you access to more than one tenant, select your account in the top right corner, and set your portal session to the Azure AD tenant that you want.
In the left-hand navigation pane, select the Azure Active Directory service, and then select App registrations > New registration.
Configure Microsoft Graph permissions you need for your application
Code
/*
install Microsoft.Graph.Beta
install Microsoft.Graph.COre
install Microsoft.Graph.Beta.Auth
*/
string clientId = "your application id";
string appKey = "your client secret";
string tenantId = "your tenant id";
IConfidentialClientApplication confidentialClientApplication =
ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(appKey)
.Build();
ClientCredentialProvider authProvider = new
ClientCredentialProvider(confidentialClientApplication);
var apps = graphClient.Applications.Request().Filter("appId eq \'you application id\'").GetAsync().Result;
foreach(var app in apps){
Console.WriteLine(app.DisplayName);
}
For more details, please refer to the document

Azure AD authentication failing when using ms live accounts other than my AAD acount

I trying to read user data from their Microsoft live account. I have written code as below:
public void GetUserData(){
var authContext = new AuthenticationContext("https://login.microsoftonline.com/common/");
var result = _authenticationContext
.AcquireTokenAsync("https://graph.microsoft.com", "<my client/app ID>", "<redirect URI>", new PlatformParameters(PromptBehavior.RefreshSession))
.Result;
var accessToken = result.AccessToken;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",accessToken);
var userResponse = httpClient.GetStringAsync("https://graph.microsoft.com/beta/me/").Result;
//DO SOMTHING WITH DATA
}
my code is working fine when I used my AAD credentials, but when I used my personal account it is giving the following error.
AADSTS50020: User account 'XXXX#outlook.com' from identity provider
'live.com' does not exist in tenant 'Default Directory' and cannot
access the application 'XXXXXXXXXXXXXXXXX' in that
tenant. The account needs to be added as an external user in the
tenant first. Sign out and sign in again with a different Azure Active
Directory user account.
Here is the screenshot:
It's similar to this question. could someone help me out?
v1 endpoints require that the user is a member in a directory.
You should probably use the v2.0 endpoints for this: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-appmodel-v2-overview
If you expect only consumer MS accounts to login, you can specify the authorize URL as:
https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize
First, for the error massage in your question, you need to add the live account into your directory first and then try to use Azure AD v2 endpoint to authenticate. You can not sign in the app with the external account which was not in that directory.
I assume that you want any Microsoft live account can use your app.
Based on this requirement, I suggest you can use Azure AD B2C to achieve this. Azure AD B2C can enables your application to authenticate with any Microsoft account. You can add Microsoft Account as a social identity providers. So that any live accounts can sign up and sign in your App through Azure AD B2C.
You can see more details about Providing sign-up and sign-in to consumers with Microsoft accounts in this official document.
Hope this helps.

Categories