I am trying to access SharePoint through Microsoft Graph using the v2.0 endpoint (Microsoft App Registration Portal) but I am unable to authenticate.
I am using the following code.
var cca = new ConfidentialClientApplication(client_id, "https://login.microsoftonline.com/testtest.onmicrosoft.com/v2.0/", "http://localhost:61716/", new ClientCredential(password), null, null);
AuthenticationResult authResult = cca.AcquireTokenForClientAsync(new string[] { "https://graph.microsoft.com/.default" }).GetAwaiter().GetResult();
var graph = new GraphServiceClient(new DelegateAuthenticationProvider((message) =>
{
message.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
I am currently getting the error "Message: Either scp or roles claim need to be present in the token."
How do I add the appropriate permissions to the app registration portal and how do I apply them / access SharePoint from my C# application.
Edit: I would like to clarify that I do not want to use the Azure AD, I would like to use the Microsoft App Registration Portal.
The permission need to add in your Application project.
Sites.Read.All, Sites.ReadWrite.All
If you use aspnet MVC, just modify the GraphScopes to in web config(get started).
If you use NetCore, just get started from the Github sample. Then modify the GraphScopes in appsettings
If you use Angular, just get started from here,choose SDK-based or Rest-based for your requirement. Then set the GraphScopes in config.js
Related
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.
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();
I'm developing an API that uses the Microsoft Graph Client SDK to make multiples calls to a Sharepoint site.
To authenticate the users making the calls to the API, I'm using the Integrated Windows Provider method, with this very simple code:
var clientApp = PublicClientApplicationBuilder
.Create(_apiSettings.Value.AzureClientId)
.WithTenantId(_apiSettings.Value.AzureTenantId)
.Build();
var token = clientApp.AcquireTokenByIntegratedWindowsAuth(new string[] { _apiSettings.Value.MicrosoftGraphApiScopeUrl })
.ExecuteAsync().Result;
When calling the method containing this code in local, it works flawlessly. But when I deploy the app to our test server, and by using the NTLM authentication with the same user than in local, I'm having this error:
Microsoft.Identity.Client.MsalUiRequiredException: AADSTS90020: The
SAML 1.1 Assertion is missing ImmutableID of the user.
When printing the content of the HttpContext.User, I see that the same user, connected to the same group, is both used on the "online" and the local version.
I already tried adding this header, but it's not doing anything:
var immId = new Dictionary<string, string>();
immId.Add("Prefer", "IdType=\"ImmutableId\"");
var token = clientApp.AcquireTokenByIntegratedWindowsAuth(new string[] { _apiSettings.Value.MicrosoftGraphApiScopeUrl })
.WithExtraHttpHeaders(immId)
.ExecuteAsync().Result;
What can I do ?
Thanks!
If your application don't have the admin to consent to the application.You will get the MsalUiRequiredException.
Try with the adding the admin consent to application .
Or Try with adding tenant admin selected the Grant/revoke admin consent for {tenant domain} button on the API permissions tab of the registration for the application. For more information, see Add permissions to access your web API.
For more details refer this document
I'm creating an app that needs to authenticate to multiple Office 365 applications in differing tenants using the Graph API. If I follow Microsoft's guidance I can do this, but I have to register the app in each new Azure AD which adds quite a lot of overhead for the user. I'd like to be able to avoid this step and use a username and password only in the authentication provider. This is the link to the Microsoft page which gives example code: https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS#usernamepassword-provider
Thanks
Nathan
Is there way to authenticate to Graph API using Username and Password without Application Registration in Azure AD?
To access the data in Microsoft Graph, your application will need to
acquire an OAuth 2.0 access token. To achieve access token you must need
application Id.No way to bypass it.
Unfortunately, You have to register an App for accessing Microsoft Graph API resources. Because Graph API requires ApplicationId, Application Secret to authenticate request. In that case you have no other options. Its a application architecture.
As you may know, to use Graph API you need to use any of the authentication grant flow provided by Microsoft. If you seen the documentation you would know that each of the application at least need to have application Id which Graph API uses to trace the request is for.
For more details you can have a look official docs
You need your application registration to get the ClientID and TenantID and the permissions to use the Graph API, but you could use without the token with user and password.
With this (max) combination of Libraries (You could not use the 3 first):
Azure.Core 1.24.0
Azure.Identity 1.6.0
Microsoft.Bcl.AsyncInterfaces 6.0.0
Microsoft.Graph 3.35.0
Microsoft.Graph.Auth 1.0.0 Preview 7
Microsoft.Graph.Core 1.25.1
Microsoft.Identity.Client 4.39.0
Microsoft.Identity.Client.Extensions.Msal 2.19.3
Just because Microsoft.Graph.Auth is deprecated (No more updates)
using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;
using System.Security;
In the function you are goint to work you could use:
GraphServiceClient graphClient = await CreateGraphClient();
To set your password (with or without the static):
public static SecureString Password
{
get
{
var password = "xxxxxxxxx";
if (password.StartsWith("Error."))
throw new InvalidProgramException(password);
SecureString secPass = new SecureString();
password.ToCharArray().ToList().ForEach(secPass.AppendChar);
secPass.MakeReadOnly();
return secPass;
}
}
internal static string UserName { get; } = "Usuario";
And you could define (with or without the static) the function as:
internal static async Task<GraphServiceClient> CreateGraphClient()
{
var pass = Password;
IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
.Create(ClientID)
.WithTenantId(TenantID)
.Build();
UsernamePasswordProvider authProvider = new UsernamePasswordProvider(publicClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
try
{
User usr = await graphClient.Me.Request().WithUsernamePassword(UserName, pass).GetAsync();
}
catch {
throw;
}
return graphClient;
}
I have a C# .NET MVC Web App on Azure that I've turned Easy Auth on for Azure AD accounts.
I'm trying to add a user to this web app's "Users and Groups" list associated with the App Registration and assign it a Role defined by the associated manifest.
So far I'm able to get the app's manifest (which contains the app roles' info, such as the id and name) with this call made in my controller:
public JObject GetRoleInfoViaId(string appObjectId)
{
string accessToken = this.Request.Headers["X-MS-TOKEN-AAD-ACCESS-TOKEN"]; // Get Easy Auth Access Token
var url = $"https://graph.microsoft.com/beta/applications/{appObjectId}"; // MS Graph
// Call the URL and return the response
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = httpClient.GetStringAsync(url).Result;
var json = JObject.Parse(response);
return json;
}
}
From here I'm stuck. I have no idea how to go about adding a user to the app and/or app role.
If this is not possible in Microsoft Graph yet, I can switch this to Azure AD Graph. It's the functionality I'm after.
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 . You can achieve that via Azure AD Graph API . Please refer to this reply for explanation and API operations .