本文介绍了使用MSAL.NET针对Azure Magment API SDK进行身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用其 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

  1. Audience 是帐户 TenantId .如果不确定其工作原理,可以在Microsoft官方页面上详细了解它.
  2. scopes 参数看起来似乎支持多个范围,但实际上不支持.通过多个 scope 会导致发生错误
  1. The Audience is the Account TenantId. If you're unsure of how this works you can learn more about it on the Official Microsoft Page.
  2. The scopes parameter which appears to look like it supports multiple scopes, it indeed does not. Passing more than one scope 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进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 20:32