is it possible to retrieve token to azure aks server (same which is in .kube/config), using Azure Credentials, programatically c#/.net 6.
I know that in powershell to retrieve it i can run "az aks get-credentials" (yaml).
Yes, it is possible to retrieve a token from an Azure server using Azure credentials programmatically in C#.
Below is the code snippet, which I have followed and it worked for me.
IConfidentialClientApplication client = ConfidentialClientApplicationBuilder
.Create("<Client-Id>")
.WithClientSecret("<Client-Secret>")
.WithAuthority("https://login.microsoftonline.com/Tenant-ID")
.Build();
List<string> scopes = new List<string>
{
"https://graph.microsoft.com/.default"
};
AuthenticationResult result = await client
.AcquireTokenForClient(scopes)
.ExecuteAsync();
GraphServiceClient graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
requestMessage.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
}));
var res = await client.AcquireTokenForClient(scopes).ExecuteAsync();
string token = result.AccessToken;
Retrieving the token
Related
I have created an ASP.NET Framework application using Microsoft Identify Platform from the standard template and used ConfidentialClient to acquire an access token. I now want to use this access token to call the Azure DevOps REST API.
My scenario is:
Open the application and immediately get asked to log in
Acquire an access token from ConfidentialClient
Execute an API call to Azure DevOps (e.g. GET https://dev.azure.com/{organization}/_apis/projects)
I believe I have completed steps 1 and 2 (code below), but when I execute the API is doesn't return the results, merely a HTML page asking me to login
The access token is recovered from the following code:
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
var authCode = context.Code;
var tenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var authority = aadInstance + tenantId;
//string[] scopes = new string[] { "https://graph.microsoft.com/User.Read" };
string[] scopes = new string[] { "https://app.vssps.visualstudio.com/user_impersonation" };
//string[] scopes = new string[] { "https://graph.microsoft.com/User.Read", "https://app.vssps.visualstudio.com/user_impersonation" };
// Get the access token from the ConfidentialClientApplication)
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.WithAuthority(authority)
.Build();
var authResult = await app.AcquireTokenByAuthorizationCode(scopes, authCode).ExecuteAsync();
string accessToken = authResult.AccessToken;
Debug.WriteLine($"Access Token: {accessToken}");
//await GetProfileData(accessToken);
await GetProjectList(accessToken);
}
If I run this I get the access token but using this as the bearer token in my API call doesn't work. The method for calling the API is as follows:
private async Task GetProjectList(string accessToken)
{
// Get the Project List from the Azure DevOps API
var httpClient = new HttpClient();
var httpRequest = new HttpRequestMessage(HttpMethod.Get,
"https://dev.azure.com/gp-ementris/_apis/projects");
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
"Bearer", accessToken);
var response = await httpClient.SendAsync(httpRequest);
if (response.IsSuccessStatusCode)
{
Debug.WriteLine(await response.Content.ReadAsStringAsync());
}
}
Can someone help explain how I can get the API to work with the token?
Thanks
I'm getting the error
Unable to retrieve user's mysite URL
when I do any query to OneDrive. My complete code below and I'm just running it on Windows
using System;
using System.Collections.Generic;
using System.Net.Http.Headers;
using Microsoft.Graph;
using Microsoft.Identity.Client;
namespace MSGraphTests
{
class Program
{
static async System.Threading.Tasks.Task Main(string[] args)
{
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication confidentialClient = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}/v2.0"))
.Build();
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await confidentialClient
.AcquireTokenForClient(scopes)
.ExecuteAsync();
var token = authResult.AccessToken;
Console.WriteLine(token);
// Build the Microsoft Graph client. As the authentication provider, set an async lambda
// which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
// and inserts this access token in the Authorization header of each API request.
GraphServiceClient graphClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", token);
})
);
var children = await graphClient.Me.Drive.Root.Children
.Request()
.GetAsync();
}
}
}
Everything works fine in Graph Explorer and I have the Files.ReadWrite.All and User.Read.All permissions set both for Delegate and Application in Azure. I do get the token in the line Console.WriteLine(token).
I'm sure this is just an issue with my code and not permissions as I'm able to send queries using the O365 python library. How can I get this working?
I am trying to create online meeting using below code and passing all the details of app registration.
Still its returning 404 error.
static string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(LaiAppClientID).WithClientSecret(Secret).WithRedirectUri(redirectURI).Build();
AuthorizationCodeProvider authProvider = new AuthorizationCodeProvider(app, scopesssss);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
graphClient = new GraphServiceClient("https://graph.microsoft.com/beta",
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
var token = await app.AcquireTokenForClient(scopesssss).WithAuthority(String.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", tenantID), true).ExecuteAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token.AccessToken);
}));
var onlineMeeting = new OnlineMeeting
{
StartDateTime = DateTimeOffset.Parse("2021-07-12T21:30:34.2444915+00:00"),
EndDateTime = DateTimeOffset.Parse("2021-07-12T22:00:34.2464912+00:00"),
Subject = "My First MS Teams Meeting",
AudioConferencing= audioConferencing
};
var task = Task.Run(async () =>
{
return await graphClient.Me.OnlineMeetings.Request().AddAsync(onlineMeeting);
});
var d = task.Result;
As your code shows, you use the auth code flow to get access token, then create onlineMeeting by MS Graph API. Please see my code, it works well.
string clientId = "<your-client-id>";
string clientSecret = "<your-client-secret>";
string redirectUri = "<your-redirect-url>";
string authority = "https://login.microsoftonline.com/<tenant>";
string authorizationCode = "<the authorization code>";
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.WithAuthority(authority)
.Build();
AuthorizationCodeProvider auth = new AuthorizationCodeProvider(app, scopes);
GraphServiceClient graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => {
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await app.AcquireTokenByAuthorizationCode(scopes, authorizationCode).ExecuteAsync();
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
})
);
var onlineMeeting = new OnlineMeeting
{
StartDateTime = DateTimeOffset.Parse("2021-07-12T21:30:34.2444915+00:00"),
EndDateTime = DateTimeOffset.Parse("2021-07-12T22:00:34.2464912+00:00"),
Subject = "My First MS Teams Meeting"
};
await graphServiceClient.Me.OnlineMeetings.Request().AddAsync(onlineMeeting);
Note:
authorizationCode: The auth code flow need to get this code first, then you could obtain the access token for API. See this step, you could request the url by browser and sign in with user, then it will response the code.
permission: To let it work, you need to add the permission(your application -> API permissions -> MS Graph -> Delegated permissions -> OnlineMeetings.ReadWrite) to create onlineMeeting, see here.
Reference:
Microsoft Graph API about creating onlineMeeting by C#: link
The sample about using AuthorizationCodeProvider and more details about the code.
UPDATE:
Message: Create online meeting with application permission is only
supported in beta.
The API(/v1.0) just supports delegated permission(OnlineMeetings.ReadWrite), not application permission. You could see this in the previous note.
Both the /beta also only supports delegated permission, see:
Can someone tell me if it will still be possible to use following authentication method with MS Graph after October 13, 2020?
public static async Task<string> GetUserAccessTokenAsync()
{
String APIToken = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX";
String LoginMail = "xxx#xxx.be";
String LoginWachtwoord = "xxxxxxxxxxx";
UserPasswordCredential userPasswordCredential = new UserPasswordCredential(LoginMail, LoginWachtwoord);
AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/diekeure.be");
//Console App for Microsoft Graph
AuthenticationResult token = await authContext.AcquireTokenAsync("https://graph.microsoft.com/", APIToken, userPasswordCredential);
return token.AccessToken;
} /* GetUserAccessTokenAsync */
public static GraphServiceClient GetAuthenticatedClient()
{
GraphServiceClient graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) => {
string accessToken = await GetUserAccessTokenAsync();
// Append the access token to the request.
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
}));
return graphClient;
} /* GetAuthenticatedClient */
-> await graphClient....
Nuget package: Microsoft.IdentityModel.Clients.ActiveDirectory v3.19.8
I'm not really sure of this won't work either
Your sample isn't using Basic Authentication, it is using the OAuth Password grant. While not a very secure authentication mechanism (since you have to store a password), it is quite different than Basic Auth.
The email you referenced is also specific to legacy services like Exchange Web Services (EWS). Microsoft Graph is not a legacy API, it is the recommended/modern REST API for Microsoft services.
Is it possible to only log in once using MS Graph? Currently whenever I call the graphServiceClient it will ask me to sign in or to choose the signed in user. Is there any way that the process of choosing the signed in user can be avoided? Thanks in advance.
Currently this is how I initialize the graphService.
public static GraphServiceClient GetAuthenticatedClient()
{
GraphServiceClient graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
string appID = ConfigurationManager.AppSettings["ida:AppId"];
PublicClientApplication PublicClientApp = new PublicClientApplication(appID);
string[] _scopes = new string[] { "Calendars.read", "Calendars.readwrite" };
AuthenticationResult authResult = null;
authResult = await PublicClientApp.AcquireTokenAsync(_scopes); //Opens Microsoft Login Screen
// Append the access token to the request.
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
}));
return graphClient;
}
Now whenever I use the standard SDK functionality it will ask me to sign in:
await graphClient.Me.Events[testID].Request().UpdateAsync(x);
And then it will ask me again when I use another function:
await graphClient.Me.Events.Request().AddAsync(newEvent);
Yes it is possible. AcquireTokenAsync does always trigger logon. Instead, you need to implement a token cache and use AcquireTokenSilentAsync. https://learn.microsoft.com/en-us/outlook/rest/dotnet-tutorial has a web app example.