Search code examples
azurepowerbiazure-active-directorypowerbi-embeddedmulti-factor-authentication

Azure Security Defaults and Power BI Embedded


Whenever I try to login to Outlook, Power BI or Azure, I keep getting a pop-up telling me that Security Defaults will be enabled for the entire organization in x days (it is in 2 days now). There is no option to disable it.

I know it can be disabled in the MS Entra in Azure. But it is already disabled. When it gets automatically enabled, will I able to turn it off back again? (I'm tenant admin) We are using master account to generate access tokens to be used for calling Power BI Embedded APIs/SDK. Will security defaults cause problems with it if it is enabled?

Code:

                IPublicClientApplication clientApp = PublicClientApplicationBuilder
                                                                    .Create(ConfigValidatorService.ApplicationId)
                                                                    .WithAuthority(m_authorityUrl)
                                                                    .Build();
                var userAccounts = await clientApp.GetAccountsAsync();

                SecureString secureStringPassword = new SecureString();
                    foreach (var key in ConfigValidatorService.Password)
                    {
                        secureStringPassword.AppendChar(key);
                    }
                    AuthenticationResult authenticationResult = await clientApp.AcquireTokenByUsernamePassword(m_scope, ConfigValidatorService.Username, secureStringPassword).ExecuteAsync();
                    

Edit:

I will change the code to use service principal instead.

IConfidentialClientApplication clientApp = ConfidentialClientApplicationBuilder
                                                                                .Create(ConfigValidatorService.ApplicationId)
                                                                                .WithClientSecret(ConfigValidatorService.ApplicationSecret)
                                                                                .WithAuthority(tenantSpecificURL)
                                                                                .Build();

var authenticationResult = await clientApp.AcquireTokenForClient(m_scope).ExecuteAsync();

Solution

  • Note that: Customers are periodically notified about the automatic activation of security defaults if they:

    • Do not have any Conditional Access policies in place.
    • Do not have any premium licenses.
    • Are not actively using legacy authentication clients.

    Security defaults enforce all the users in the organization to register for multifactor authentication and if you do not want MFA then you need to disable it in Microsoft Entra Portal:

    enter image description here

    If the security default is enabled, AcquireTokenByUsernamePassword will throw error while generating the access token as this flow doesn't support MFA enabled accounts.

    If the security defaults is enabled (MFA enabled) then you will get an error like below while using AcquireTokenByUsernamePassword :

    public class AuthService
    {
        private static string m_authorityUrl = "https://login.microsoftonline.com/TenantID";
        private static string[] m_scope = new string[] { "https://analysis.windows.net/powerbi/api/.default" };
    
        public async Task AuthenticateUserAsync()
        {
            IPublicClientApplication clientApp = PublicClientApplicationBuilder
                                                    .Create(ConfigValidatorService.ApplicationId)
                                                    .WithAuthority(m_authorityUrl)
                                                    .Build();
    
            var userAccounts = await clientApp.GetAccountsAsync();
    
            SecureString secureStringPassword = new SecureString();
            foreach (var key in ConfigValidatorService.Password)
            {
                secureStringPassword.AppendChar(key);
            }
    
            AuthenticationResult authenticationResult = await clientApp.AcquireTokenByUsernamePassword(m_scope, ConfigValidatorService.Username, secureStringPassword).ExecuteAsync();
    
            Console.WriteLine($"Access Token: {authenticationResult.AccessToken}");
        }
    }
    
    public static class ConfigValidatorService
    {
        public static string ApplicationId = "ClientID";
        public static string Username = "[email protected]";
        public static string Password = "Password";
    }
    public class Program
    {
        public static async Task Main(string[] args)
        {
            AuthService authService = new AuthService();
            await authService.AuthenticateUserAsync();
        }
    }
    

    enter image description here

    Hence either you need to disable the security defaults or switch to any other authentication flow to generate access token.

    If Security defaults is enabled, make use of below code which makes use of AcquireTokenInteractive flow:

    public class AuthService
    {
        private static string m_authorityUrl = "https://login.microsoftonline.com/TenantID";
        private static string[] m_scope = new string[] { "https://analysis.windows.net/powerbi/api/.default" };
    
        public async Task AuthenticateUserAsync()
        {
            IPublicClientApplication clientApp = PublicClientApplicationBuilder
                                                    .Create(ConfigValidatorService.ApplicationId)
                                                    .WithAuthority(m_authorityUrl)
                                                    .WithDefaultRedirectUri()
                                                    .Build();
    
            AuthenticationResult authenticationResult = null;
    
            try
            {
                authenticationResult = await clientApp.AcquireTokenInteractive(m_scope).ExecuteAsync();
            }
            catch (MsalException ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
                return;
            }
    
           Console.WriteLine($"Access Token: {authenticationResult.AccessToken}");
        }
    }
    
    public static class ConfigValidatorService
    {
        public static string ApplicationId = "ClientID";
    }
    
    public class Program
    {
        public static async Task Main(string[] args)
        {
            AuthService authService = new AuthService();
            await authService.AuthenticateUserAsync();
        }
    }
    

    enter image description here

    Reference:

    Providing a default level of security in Microsoft Entra ID - Microsoft Entra | Microsoft