Add Site Collection Admin using SharePoint CSOM and .Net 6 - c#

I'm struggeling to understand how to use SharePoint CSOM to add a user as Site Collection Admin.
So far this code works for a Global Admin to add a user as Site Colleciton Admin, eventhough the Global Admin is not included as Site Admin.
I've tried to run the code as normal user which is only Site Collection Admin, to add another user as Site Colleciton Admin. But then I get some errors:
If I use the SharePoint Admin URL to get the Access Token, then the code crash on row #48 as 401 "Unauthorized"
If I use the Site Collection URL to get the Access Token, I get error when trying to get the acces token saying that Site is doesn't exist on the environment.
If I use the root site URL ("https://domain-admin.sharepoint.com/) to get the Access Token, then the code crash on row #51 as 401 "Unauthorized".
I'm using the PnP.PowerShell code as reference: https://github.com/pnp/powershell/blob/dev/src/Commands/Admin/SetTenantSite.cs#L547-L574
And my process is pretty much the same as here: MSAL AD token not valid with SharePoint Online CSOM
But I don't have clear if it's a issue of access token or the CSOM commands I use.
Does anyone has any idea how to move forward?
btw, I guess if I use the Global Admin account I only need to use tenant.SetSiteAdmin(siteCollection, userEmail, true);. I read somewhere that even for global admin I need EnsureUser(userEmail);, but so far the code seems working without it.
using Microsoft.Identity.Client;
using Microsoft.SharePoint.Client;
namespace ScriptTester
{
internal class Program
{
static async Task Main(string[] args)
{
await AddUserAdmin();
}
public static async Task AddUserAdmin()
{
string siteAdmin = "https://domain-admin.sharepoint.com/";
string siteRoot = "https://domain.sharepoint.com/";
string siteCollection = "https://domain.sharepoint.com/sites/SiteName/";
string userEmail = "_email";
string accessToken = await GetAccessToken(siteRoot);
using (var context = new Microsoft.SharePoint.Client.ClientContext(siteRoot))
{
context.ExecutingWebRequest += (sender, e) =>
{
e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
};
var tenant = new Microsoft.Online.SharePoint.TenantAdministration.Tenant(context);
try
{
addLog("Try using tenant context");
tenant.SetSiteAdmin(siteCollection, userEmail, true);
tenant.Context.ExecuteQueryRetry();
}
catch (Exception ex)
{
addLog("Failed using Tenant context");
addLog(ex.Message);
using (var site = tenant.Context.Clone(siteCollection))
{
var user = site.Web.EnsureUser(userEmail);
user.Update();
user.IsSiteAdmin= true;
site.Load(user);
site.ExecuteQueryRetry();
tenant.SetSiteAdmin(siteCollection, userEmail, true);
tenant.Context.ExecuteQueryRetry();
}
}
}
}
public static async Task<string> GetAccessToken(string siteUrl)
{
string tenantId = "xxxx-xxxx-xxxx-xxxx-xxx";
string clientId = "xxxx-xxxx-xxxx-xxxx-xxx";
Uri authority = new Uri($"https://login.microsoftonline.com/{tenantId}");
string redirectUri = "http://localhost";
string defaultPermissions = siteUrl + "/.default";
string[] scopes = new string[] { defaultPermissions };
var app = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(authority)
.WithRedirectUri(redirectUri)
.Build();
AuthenticationResult result;
result = await app.AcquireTokenInteractive(scopes)
.WithUseEmbeddedWebView(false)
.ExecuteAsync();
return result.AccessToken;
}
}
}

I will recommend you to use PnP Core component to access site collection and add admin. Please refer to the following code
string siteUrl = "https://xxx.sharepoint.com/";
string userName = "xxxx#xxx.onmicrosoft.com";
string password = "*******";
AuthenticationManager authManager = new AuthenticationManager();
try
{
using (var clientContext = authManager.GetSharePointOnlineAuthenticatedContextTenant(siteUrl, userName, password))
{
List<UserEntity> admins = new List<UserEntity>();
UserEntity admin = new UserEntity();
admin.LoginName = "nirmal";
admins.Add(admin);
clientContext.Site.RootWeb.AddAdministrators(admins, true);
Console.WriteLine("User added as Site Collection Admin");
Console.ReadKey();
}
}
catch (Exception ex)
{
Console.WriteLine("Error Message: " + ex.Message);
Console.ReadKey();
}

Related

Cannot get past Azure Authentication for basic c# application

I am just starting in with Azure and my first attempt is using the Graph client API for a simple data display. In simple terms, I want to get the Teams status of an employee and display it on a form in some graphical way.
I am trying to be as basic as can be so when I tried to download the sample I did not want the UWP project, just basic winform (console would work at the moment). I did borrow from the project and got something to compile but I get the error:
MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
This is the full code and I am obviously missing something...what? This is an App that should be able to access the Graph API for a get user read and a getPresence call to show current status with the nee to have a use log in. I can see that Graph Explorer has a token and looking at postman set up there is some way to do this without a interaction, but none of the documentation is clear. I'll continue to pok at this and maybe see if I can get postman to work which might help, but behind the scene's access is not clear to me.
public partial class Form1 : Form
{
//Set the scope for API call to user.read
private string[] scopes = new string[] { "user.read" };
private const string ClientId = "my client id";
private const string Tenant = "my tenant id";
private const string Authority = "https://login.microsoftonline.com/" + Tenant;
// The MSAL Public client app
private static IPublicClientApplication PublicClientApp;
private static string MSGraphURL = "https://graph.microsoft.com/v1.0/";
private static AuthenticationResult authResult;
public Form1()
{
InitializeComponent();
PublicClientApp = PublicClientApplicationBuilder.Create(ClientId).WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient").Build();
callMe();
}
private async void callMe()
{
// Sign-in user using MSAL and obtain an access token for MS Graph
GraphServiceClient graphClient = await SignInAndInitializeGraphServiceClient(scopes);
// Call the /me endpoint of Graph
User graphUser = await graphClient.Me.Request().GetAsync();
Console.WriteLine(graphUser.Id);
var graphu2 = await graphClient.Users["my email address"].Request().GetAsync();
}
private async Task<GraphServiceClient> SignInAndInitializeGraphServiceClient(string[] scopes)
{
GraphServiceClient graphClient = new GraphServiceClient(MSGraphURL,
new DelegateAuthenticationProvider(async (requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", await getToken(scopes));
}));
return await Task.FromResult(graphClient);
}
public async Task<string> getToken(string[] scopes)
{
PublicClientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority(Authority)
.WithLogging((level, message, containsPii) =>
{
Console.WriteLine($"MSAL: {level} {message} ");
}, LogLevel.Warning, enablePiiLogging: false, enableDefaultPlatformLogging: true)
.Build();
IEnumerable<IAccount> accounts = await PublicClientApp.GetAccountsAsync().ConfigureAwait(false);
IAccount firstAccount = accounts.FirstOrDefault();
try
{
authResult = await PublicClientApp.AcquireTokenSilent(scopes, firstAccount)
.ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
// A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token
Console.WriteLine($"MsalUiRequiredException: {ex.Message}");
authResult = await PublicClientApp.AcquireTokenInteractive(scopes)
.ExecuteAsync()
.ConfigureAwait(true);
}
return authResult.AccessToken;
}
Apologies but I'm going to ignore your code and break it back to something that's a lot more simple.
using Azure.Identity;
using Microsoft.Graph;
namespace StackoverflowAnswer
{
internal class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
static async Task MainAsync()
{
var tenantId = "YOUR_TENANT_ID";
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
try
{
string[] scopes = { "https://graph.microsoft.com/.default" };
ClientSecretCredential clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
GraphServiceClient graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var users = await graphClient.Users.Request().GetAsync();
foreach (var user in users)
Console.WriteLine(user.UserPrincipalName);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
A lot of the above code was taken from the following documentation as once you've authenticated, the rest of the SDK is much the same. It can be tricky in points though depending on the specific nature of what you want to do ...
https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/tokencredentials.md
This also helps ...
https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS#client-credentials-provider
Also make sure that you've assigned the desired API permissions to the app in the Azure Portal ...
... and also make sure you've set a client secret for your app. If you have a client ID then you've clearly already gotten that far ...
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
Update
Now, in relation to working with the Presence API, this is a little more tricky.
Although it appears to, the Presence API doesn't support application permissions. There is an application permission for it but put simply, it doesn't work. This user voice link provides insight on that.
https://techcommunity.microsoft.com/t5/microsoft-365-developer-platform/graph-api-presence-should-support-application-permissions/idi-p/2276109
So what you need to do is apply the delegated permissions to your registered application.
Because of that, you need to use a UsernamePasswordCredential rather than a ClientSecretCredential in your code and replace it when instantiating the GraphServiceClient.
UsernamePasswordCredential usernamePasswordCredential = new UsernamePasswordCredential("<USERNAME>", "<PASSWORD>", tenantId, clientId);
Further to that, you'll need to make sure that the user in question has granted access to use that permission. If it was a user facing app, then they'd log in and be presented with the question to approve the permissions that you have set but because it's not, you need to go to the Enterprise Applications section in Azure AD, find your app, go to Permissions and press the Grant admin consent button for your tenant.
Someone may have a better approach than the above but it's the only way I could find to do it. It will mean if someone knows the client ID and how to authenticate, they can then execute the same API's as you.
Anyway, that will then allow you to get the presence of all users in your organisation.

Obtaining access to Graph API without user interaction

I'm new to graph API. I'm creating an app that can access user email using Graph API. I've been using the device token method which is used here.
The above code is working with my application. But I want to automate this process. I found some help from Microsoft documents here, from the sample codes here, and from this SO post.
But I can't get my code to obtain the token automatically. I thought it was an API permissions issue so I set them up like below.
I was able to get the AcquireTokenInteractive but AcquireTokenSilent is not working.
UPDATE: I've managed to get an exception the message is this "No account or login hint was passed to the AcquireTokenSilent call.". Also found that variable FirstAccount seems to be empty.
Below is my code for obtaining the token.
using Azure.Core;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Identity.Client;
using System.Net.Http.Headers;
namespace DEA
{
public class GraphHelper
{
private static GraphServiceClient? graphClient;
private static AuthenticationResult token;
private static IPublicClientApplication? application;
public static async void InitializeAuto(string ClientID, string InstanceID, string TenantID, string GraphUrl, string[] scopes)
{
string auth = string.Concat(InstanceID, TenantID);
application = PublicClientApplicationBuilder.Create(ClientID)
.WithAuthority(auth)
.WithDefaultRedirectUri()
.Build();
try
{
var accounts = await application.GetAccountsAsync();
graphClient = new GraphServiceClient(GraphUrl,
new DelegateAuthenticationProvider(async (requestMessage) =>
{
token = await application.AcquireTokenInteractive(scopes, accounts.FirstOrDefault()).ExecuteAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token.AccessToken);
}
));
}
catch (Exception ex)
{
Console.WriteLine("Exception thrown: {0}", ex.Message);
}
}
}
The above function is called from my "Program.cs".
using DEA;
using Microsoft.Extensions.Configuration;
var appConfig = LoadAppSettings();
if (appConfig == null)
{
Console.WriteLine("Set the graph API pemissions. Using dotnet user-secrets set .... They don't exsits in this computer.");
return;
}
var appId = appConfig["appId"];
var TenantId = appConfig["TenantId"];
var Instance = appConfig["Instance"];
var GraphApiUrl = appConfig["GraphApiUrl"];
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
GraphHelper.InitializeAuto(appId, Instance, TenantId, GraphApiUrl, scopes);
static IConfigurationRoot? LoadAppSettings()
{
var appConfig = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
// Check for required settings
if (string.IsNullOrEmpty(appConfig["appId"]) ||
string.IsNullOrEmpty(appConfig["scopes"]))
{
return null;
}
return appConfig;
}
I don't know what I'm doing wrong. I used a try ... catch but still nothing. The only error I get is an exception thrown by the graph client call when I press option 2 of my app.
Can someone please help me to solve this, please?
After reading #Marc and #Jeremy Lakeman I rewrote the code using IConfidentialClientApplication. And used this as a guide from Microsoft guides.
And came up with the below code and it works now.
public static async void InitializeAuto(string ClientID, string InstanceID, string TenantID, string GraphUrl, string ClientSecret, string[] scopes)
{
string auth = string.Concat(InstanceID, TenantID);
application = ConfidentialClientApplicationBuilder.Create(ClientID)
.WithClientSecret(ClientSecret)
.WithAuthority(new Uri(auth))
.Build();
Console.WriteLine("Auth: {0}", auth);
Console.WriteLine("Client Secrets: {0}", ClientSecret);
try
{
graphClient = new GraphServiceClient(GraphUrl,
new DelegateAuthenticationProvider(async (requestMessage) =>
{
AuthToken = await application.AcquireTokenForClient(scopes).ExecuteAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", AuthToken.AccessToken);
}
));
/*result = await application.AcquireTokenForClient(scopes)
.ExecuteAsync();
Console.WriteLine("Token: {0}", result.AccessToken);*/
}
catch (MsalUiRequiredException ex)
{
// The application doesn't have sufficient permissions.
// - Did you declare enough app permissions during app creation?
// - Did the tenant admin grant permissions to the application?
Console.WriteLine("Exception: {0}", ex.Message);
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
// Invalid scope. The scope has to be in the form "https://resourceurl/.default"
// Mitigation: Change the scope to be as expected.
Console.WriteLine("Scope provided is not supported");
}
}
Could you please do a fresh start and try again with AcquireTokenSilent(), lets see if you got any error .
{
var accounts = await application.GetAccountsAsync();
result = await application.AcquireTokenSilent(scopes,
accounts.FirstOrDefault())
.ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
result = await application.AcquireTokenInteractive(scopes)
.WithClaims(ex.Claims)
.ExecuteAsync();
}
doc - https://github.com/Azure-Samples/ms-identity-dotnet-desktop-tutorial/tree/master/1-Calling-MSGraph/1-1-AzureAD

Invalid domain name Azure Active directory issue and Migration to Microsoft Graph C# application

I am trying to run below code to get the user details as response from Azure Active Directory :
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace AADConsole2
{
class Program
{
private const string aadInstance = "https://login.microsoftonline.com/{0}";
private const string resource= "https://graph.windows.net";
private const string GraphServiceObjectId = "XXX";
private const string TenantId = "XXXXX";
private const string tenant = "company.onmicrosoft.com";
private const string ClientId = "XXXX";
private static string appKey= "XXXXXXXXXXXXXXXX";
static string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, aadInstance, tenant);
private static HttpClient httpclient = new HttpClient();
private static AuthenticationContext context = null;
private static ClientCredential credential = null;
static void Main(string[] args)
{
context = new AuthenticationContext(authority);
credential = new ClientCredential(ClientId, appKey);
Task<string> token = GetToken();
token.Wait();
Console.WriteLine(token.Result);
Task<string> users = GetUsers(token.Result);
users.Wait();
Console.WriteLine(users.Result);
Console.ReadLine();
}
private static async Task<string> GetUsers(string result) {
//throw new NotImplementedException();
string users = null;
string queryString = "test";
var uri = "https://graph.windows.net/{your_tenant_name}.onmicrosoft.com/users?api-version=1.6";
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result);
var getResult = await httpclient.GetAsync(uri);
if(getResult.Content != null)
{
users = await getResult.Content.ReadAsStringAsync();
}
return users;
}
private static async Task<string> GetToken()
{
AuthenticationResult result = null;
string token = null;
result = await context.AcquireTokenAsync(resource, credential);
token = result.AccessToken;
return token;
}
}
}
I am getting below error:
uMCJ9.FdttazjoKYZWP_SmC5B7Nd3kOF-jRs62WLKYovDA8qMvybLTw8yIUoihp7I00ctJGJHDoEbhbIi0XHp9Ujdq0bNPlG-L5SoE9IFSoxX3ZQOZwSf90b_nDapbHJ8KCHZUnCBOwVnYiTXtpIQfrDVqqENarrIGa_uUbiriomYiB8gVkKWe6PB-I4lsYPEmMNnnpdvIf1eV_CsTmvUA54Ch1Zdip9mxrzRqrUqsx6vUTo0riCmiCxRg7mH2DuMaEPTZuQAMwhrQM_EwNsgx1yX1VsCKkL1Gu7CV_dqW5xxYlE7NEQmorT8W6aySbiBzsUWisJNnaR8RqZzeAUlSVMKBiw
{"odata.error":{"code":"Request_BadRequest","message":{"lang":"en","value":"Invalid domain name in the request url."},"requestId":"01ab745b-8a3f-48cc-9542-0c6abcae8950","date":"2020-02-17T22:41:28"}}
r
Also ,help me in getting tenant name ( it's a name or alphanumeric id ?) ,currently i am just using below tenant name.
private const string tenant = "company.onmicrosoft.com";
I only want to use Microsoft Graph API in this code. Thanks.
i also want to know the whether this code is using Microsoft Graph or
Azure AD.
This code is using Azure AD Graph API. It works fine if the request uri is correct.You should use your tenant name, not company.onmicrosoft.com, and you must specify the api-version. So the request uri should be
var uri = "https://graph.windows.net/{your_tenant_name}.onmicrosoft.com/users?api-version=1.6";
If the tenant name is wrong, you will encounter Invalid domain name error.
I am not sure whether to use https://graph.microsoft.com or
https://graph.windows.net.
You can use either one. But the official document strongly recommend that you use Microsoft Graph instead of Azure AD Graph API to access Azure Active Directory (Azure AD) resources.
If you want to use Microsoft Graph API, just change the value of resource and request api url. The resource will be https://graph.microsoft.com. The request api url will be var uri = "https://graph.microsoft.com/v1.0/users";.
Note: Remember to grant your application the correct permissions in Azure portal and grant admin consent.

Failing to get Team details from a c# console app while it works from Graph Explorer

I need to collect Microsoft Teams data from a C# console application using Microsoft Graph.
I am using ADAL and cloned the authentication methods from the https://github.com/microsoftgraph/console-csharp-connect-sample sample.
The only difference is that I am using an HttpClient client and not a GraphServiceClient that does not implement Teams objects.
The list of required permissions have been determined with a Fiddler trace of a request made with Graph Explorer (no need for User.Read.All or User.Write.All) :
User.Read, Mail.Send, Files.ReadWrite, User.ReadWrite, User.ReadBasic.All, Sites.ReadWrite.All, Contacts.ReadWrite, People.Read, Notes.ReadWrite.All, Tasks.ReadWrite, Mail.ReadWrite, Files.ReadWrite.All, Calendars.ReadWrite
Everything works fine with my console app as long as I am not requesting any Teams resource:
I can get the list of groups "that are Teams" with the following
request: https://graph.microsoft.com/beta/groups?$filter=resourceProvisioningOptions/any(v:v eq 'Team')&$select=id,displayname,groupTypes,resourceBehaviorOptions,resourceProvisioningOptions
I can successfully get the group details with: https://graph.microsoft.com/beta/groups/{groupId}
But when I try to get the team view of that group (which I am member of) it fails with HTTP
403-Unautorized:
https://graph.microsoft.com/beta/groups/{groupId}/team
Very
frustrating to see that this last step is working well from the
Graph Explorer
My problem is very similiar with Access Denied when querying Teams in Microsoft Graph but in my case I am member of the teams I am trying to access and the request works with Graph Explorer.
Code details:
class AuthenticationHelper
{
// The Client ID is used by the application to uniquely identify itself to the v2.0 authentication endpoint.
static string clientId = Constants.ClientId;
// The list of required permissions have been determined with a Fiddler trace of a request made with Graph Explorer
// e.g. below are the permissions Grap Explorer requires to run the sample requests
public static string[] Scopes = {
"User.Read"
, "Mail.Send"
, "Files.ReadWrite"
, "User.ReadWrite"
, "User.ReadBasic.All"
, "Sites.ReadWrite.All"
, "Contacts.ReadWrite"
, "People.Read"
, "Notes.ReadWrite.All"
, "Tasks.ReadWrite"
, "Mail.ReadWrite"
, "Files.ReadWrite.All"
, "Calendars.ReadWrite"
};
public static PublicClientApplication IdentityClientApp = new PublicClientApplication(clientId);
public static string UserToken = null;
public static DateTimeOffset Expiration;
//-----------------------------------------------------------------------------------------------------------------
public static async Task<HttpClient> GetAuthenticatedHttpClient()
{
HttpClient client = null;
try
{
client= new HttpClient(new HttpClientHandler { UseCookies = true });
var token = await GetTokenForUserAsync();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// This header has been added to identify our sample in the Microsoft Graph service. If extracting this code for your project please remove.
client.DefaultRequestHeaders.Add("SampleID", "TestCSharp-AzureToken");
return client;
}
catch (Exception ex)
{
Debug.WriteLine("Could not create a graph client: " + ex.Message);
}
return client;
}
//-----------------------------------------------------------------------------------------------------------------
public static async Task<string> GetTokenForUserAsync()
{
AuthenticationResult authResult;
try
{
IEnumerable<IAccount> accounts = await IdentityClientApp.GetAccountsAsync();
IAccount firstAccount = accounts.FirstOrDefault();
authResult = await IdentityClientApp.AcquireTokenSilentAsync(Scopes, firstAccount);
UserToken = authResult.AccessToken;
}
catch (Exception)
{
if (UserToken == null || Expiration <= DateTimeOffset.UtcNow.AddMinutes(5))
{
authResult = await IdentityClientApp.AcquireTokenAsync(Scopes );
UserToken = authResult.AccessToken;
Expiration = authResult.ExpiresOn;
}
}
return UserToken;
}
}
//----------------------------------------------------
// Console entry point
class Program
{
//public static GraphServiceClient client;
public static HttpClient _client;
static async Task<string> GetHttpResponse(string url)
{
string responseBody = null;
_client = await AuthenticationHelper.GetAuthenticatedHttpClient();
HttpResponseMessage response = await _client.GetAsync(url);
response.EnsureSuccessStatusCode();
using (HttpContent content = response.Content)
{
responseBody = await response.Content.ReadAsStringAsync();
logger.Trace(responseBody);
}
return responseBody;
}
static void Main(string[] args)
{
// call 1 is working: list groups that "are Microsoft Teams"
string s;
string url = "https://graph.microsoft.com/beta/groups?$filter=resourceProvisioningOptions/any(v:v eq 'Team')&$select=id,displayname,groupTypes,resourceBehaviorOptions,resourceProvisioningOptions";
s = await GetHttpResponse(url);
Console.WriteLine(s);
// call 2 is working: Display details of one of these groups
Console.Write($"Enter the id of the group/teams to search for: ");
string groupId = Console.ReadLine().Trim().ToLower();
url = $"https://graph.microsoft.com/beta/groups/{groupId}";
s = await GetHttpResponse(url);
Console.WriteLine(s);
// call 3 is failing: Display the team view of this groups
url = url + "/team";
s = await GetHttpResponse(url);
Console.WriteLine(s);
}
}
You're missing a scope. You need to have Group.Read.All in order to read a Group or Team.

Unable to authorize Azure LogAnalytics Workspace

I am trying to connect to my workspace in the Azure Portal. I am getting the error as
Operation returned an invalid status code 'Unauthorized'.
The creds object has fetched the Authentication Token and I have added resource permissions to my app as mentioned in this link
using System;
using Microsoft.Azure.OperationalInsights;
using Microsoft.Rest.Azure.Authentication;
namespace LogAnalytics
{
class Program
{
static void Main(string[] args)
{
var workspaceId = "**myworkspaceId**";
var clientId = "**myClientId**";
var clientSecret = "**myClientSecret**";
//<your AAD domain>
var domain = "**myDomain**";
var authEndpoint = "https://login.microsoftonline.com";
var tokenAudience = "https://api.loganalytics.io/";
var adSettings = new ActiveDirectoryServiceSettings
{
AuthenticationEndpoint = new Uri(authEndpoint),
TokenAudience = new Uri(tokenAudience),
ValidateAuthority = true
};
var creds = ApplicationTokenProvider.LoginSilentAsync(domain,clientId, clientSecret,
strong textadSettings).GetAwaiter().GetResult();
var client = new OperationalInsightsDataClient(creds);
client.WorkspaceId = workspaceId;
//Error happens below
var results = client.Query("union * | take 5");
Console.WriteLine(results);
Console.ReadLine();
}
}
}
Operation returned an invalid status code 'Unauthorized'.
According to the error message and the code you provided, you need to add permission in your registered application in Azure AD.
Note: If you want to add permission to application you need to be admin, and then you could use the ClientId and ClientSecret to get Authentication Token and read log analytics.
However, if you are not admin, you could delegate permission to user and access to Azure AD with username and password.
To get authentication token with user, you could can use the function UserTokenProvider.LoginSilentAsync(nativeClientAppClientid, domainName, userName, password).GetAwaiter().GetResult() to get our credentials.

Categories

Resources