问题描述
尝试使用其 SDK 来针对Azure Management API进行身份验证.我可以使用MSAL.NET SDK 对用户进行身份验证.但是,当我尝试将Bearer令牌传递给ClientCrendentials时,我可以和AuthorizationFailed消息一起使用.
Trying to Authenticate against Azure Management API using their SDK. I can get the user authenticated with the MSAL.NET SDK. But when I try to pass the Bearer token for ClientCrendentials I can and AuthorizationFailed Message.
我已在Active Directory实例中启用 user_impersination
并委派权限,并通过应用程序门户注册了我的应用程序.
I've enabled user_impersination
and delegate permissions in my Active Directory instance and register my application through the application portal.
租户设置为 common
class Program
{
static readonly string TenantID = ConfigurationManager.AppSettings.Get("tenant_id");
static readonly string ClientID = ConfigurationManager.AppSettings.Get("client_id");
static readonly string Scopes = ConfigurationManager.AppSettings.Get("scopes");
static AuthenticationResult Authentication { get; set; }
static AzureEnvironment AzureEnvironment => AzureEnvironment.AzureGlobalCloud;
static void Main(string[] args)
{
// useful links
// Micorosft.Identity.Client https://github.com/AzureAD/microsoft-authentication-library-for-dotnet
DoLoginAsync().Wait();
CallAzure().Wait();
//CallMsGraphAPI().Wait();
Console.Read();
}
static async Task DoLoginAsync()
{
try
{
IPublicClientApplication client = PublicClientApplicationBuilder.Create(ClientID)
.WithAuthority(AzureCloudInstance.AzurePublic, TenantID)
.Build();
Authentication = await client.AcquireTokenInteractive(Scopes.Split(','))
.ExecuteAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static async Task CallAzure()
{
try
{
var client = RestClient.Configure()
.WithEnvironment(AzureEnvironment)
.WithCredentials(GetCredentials())
.WithLogLevel(HttpLoggingDelegatingHandler.Level.BodyAndHeaders)
.Build();
var subscriptionClient = new SubscriptionClient(client);
var subscriptions = await subscriptionClient.Subscriptions.ListAsync();
Console.WriteLine(subscriptions); // fails
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
static AzureCredentials GetCredentials()
{
var provider = new StringTokenProvider(Authentication.AccessToken, "Bearer");
var tokenCredentials = new TokenCredentials(provider, TenantID, Authentication.Account.Username);
return new AzureCredentials(tokenCredentials, tokenCredentials, TenantID, AzureEnvironment);
}
}
我认为可以使用我在 GetCredentials
方法中返回的承载令牌来授权用户.
I would think the user could be authorized using the Bearer Token given back in the GetCredentials
method I have.
推荐答案
我设法解决了这个问题,但有两点值得指出
I managed to work through the issue and had two things worth pointing out
-
Audience
是帐户TenantId
.如果不确定其工作原理,可以在Microsoft官方页面上详细了解它. -
scopes
参数看起来似乎支持多个范围,但实际上不支持.通过多个scope
会导致发生错误
- The
Audience
is the AccountTenantId
. If you're unsure of how this works you can learn more about it on the Official Microsoft Page. - The
scopes
parameter which appears to look like it supports multiple scopes, it indeed does not. Passing more than onescope
causes an error to occur
有用的资源
class Program
{
static AuthenticationResult AuthenticationResult { get; set; }
static readonly string ClientId = ConfigurationManager.AppSettings.Get("ClientId") ?? throw new ApplicationException("No ClientID configured in <appsettings /> App.Config");
static readonly IEnumerable<string> Scopes = new[] { "https://management.azure.com/user_impersonation" };
static IPublicClientApplication App { get; set; }
static void Main(string[] args)
{
App = PublicClientApplicationBuilder.Create(ClientId)
.WithLogging((level, message, containsPii) =>
{
Console.WriteLine("Error when using Public Client");
Console.WriteLine($"{level}: {message}");
}, LogLevel.Verbose, true, true)
.WithAuthority(AzureCloudInstance.AzurePublic, AadAuthorityAudience.AzureAdMultipleOrgs, true)
.Build();
DoLoginAsync().Wait();
CallAzureMangementRestApiAsync().Wait();
}
static async Task DoLoginAsync()
{
try
{
var accounts = await App.GetAccountsAsync().ConfigureAwait(false);
try
{
AuthenticationResult = await App.AcquireTokenSilent(Scopes, accounts.FirstOrDefault())
.ExecuteAsync()
.ConfigureAwait(false);
}
catch (MsalUiRequiredException)
{
AuthenticationResult = await App.AcquireTokenInteractive(Scopes)
.ExecuteAsync()
.ConfigureAwait(false);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static async Task CallAzureMangementRestApiAsync()
{
try
{
try
{
var accounts = await App.GetAccountsAsync().ConfigureAwait(false);
AuthenticationResult = await App.AcquireTokenSilent(Scopes, accounts.FirstOrDefault())
.WithAuthority(AzureCloudInstance.AzurePublic, AuthenticationResult.TenantId)
.ExecuteAsync()
.ConfigureAwait(false);
}
catch (MsalUiRequiredException)
{
// UI needs to have the user call in
AuthenticationResult = await App.AcquireTokenInteractive(Scopes)
.WithAuthority(AzureCloudInstance.AzurePublic, AuthenticationResult.TenantId)
.ExecuteAsync()
.ConfigureAwait(false);
}
var client = RestClient.Configure()
.WithEnvironment(AzureEnvironment.FromName(AuthenticationResult?.Account?.Environment) ?? AzureEnvironment.AzureGlobalCloud)
.WithCredentials(GetAzureCredentials())
.WithLogLevel(HttpLoggingDelegatingHandler.Level.BodyAndHeaders)
.Build();
using (var subscriptionClient = new SubscriptionClient(client))
{
var subscriptions = await subscriptionClient.Subscriptions
.ListAsync()
.ConfigureAwait(false);
foreach (var s in subscriptions)
{
Console.WriteLine($"Id={s.Id};subscriptionId={s.SubscriptionId};displayName={s.DisplayName}");
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static AzureCredentials GetAzureCredentials()
{
var provider = new StringTokenProvider(AuthenticationResult.AccessToken, "Bearer");
var token = new TokenCredentials(provider, AuthenticationResult.TenantId, AuthenticationResult.IdToken != null ? AuthenticationResult.UniqueId : AuthenticationResult.IdToken);
return new AzureCredentials(token, token, AuthenticationResult.TenantId, AzureEnvironment.AzureGlobalCloud);
}
}
这篇关于使用MSAL.NET针对Azure Magment API SDK进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!