使用MSAL.NET针对Azure Magment API SDK进行身份验证

时间:2019-06-27 17:27:38

标签: .net msal azure-management-api

尝试使用其SDK针对Azure Management API进行身份验证。我可以使用户通过MSAL.NET SDK进行身份验证。但是,当我尝试将Bearer令牌传递给ClientCrendentials时,我可以和AuthorizationFailed消息一起使用。

我已在Active Directory实例中启用user_impersination并委派权限,并通过应用程序门户注册了我的应用程序。

租户设置为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方法中返回的承载令牌来授权用户。

1 个答案:

答案 0 :(得分:0)

我设法解决了这个问题,有两点值得指出

  1. Audience是帐户TenantId。如果不确定其工作原理,可以在Microsoft官方页面上详细了解它。
  2. 看起来scopes的参数似乎支持多个范围,但实际上不支持。传递多个scope会导致发生错误

有用的资源

  • single to multi tenant applications
  • application audiences
  • choosing an authentication provider
  • Best practices for ConfigureAwait

    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);
        }
    }