Inheritance: ClientBase
        public async Task<AdApplication> AssureAzureAdAppAndPrincipal(GraphClient cl, Guid tenantId)
        {
            AdApplication app = null;
            ServicePrincipal principal = null;
            app = await cl.GetApplicationAsync();
            if (app != null)
                principal = await cl.GetServicePrincipalAsync(app.AppId);

            if (app == null || principal == null)
            { 
                var r = System.Windows.MessageBox.Show("An application has to be created in your Azure AD. Do you want to continue?", "Please confirm...", System.Windows.MessageBoxButton.OKCancel);
                if (r == System.Windows.MessageBoxResult.OK)
                {
                    if (app == null)
                        app = await cl.CreateApplicationAsync();
                    if (principal == null)
                    {
                        principal = await cl.CreateServicePrincipalAsync(app.AppId);
                        await Task.Factory.StartNew(() => System.Threading.Thread.Sleep(30)); //sleep for 30 secconds so principal is available
                    }
                    
                }
                else
                    return null;
            }
            return app;
        }
        private async Task RemoveServiceCredential(GraphClient cl, ManagementPack configMp)
        {
            var secRefOverride = (ManagementPackSecureReferenceOverride)_emg.Overrides.GetOverrides(new ManagementPackOverrideCriteria($"Name = '{Parameters.SECURE_REFERENCE_OVERRIDE_NAME}'")).FirstOrDefault();
            if (secRefOverride != null)
            {
                secRefOverride.Status = ManagementPackElementStatus.PendingDelete;
                secRefOverride.GetManagementPack().AcceptChanges();
            }
            var secData = (BasicCredentialSecureData)_emg.Security.GetSecureData(new SecureDataCriteria($"Name = '{Parameters.SECURE_REFERENCE_NAME}'")).FirstOrDefault();
            if (secData != null)
                _emg.Security.DeleteSecureData(secData);

            var app = await cl.GetApplicationAsync();
            if (app != null && app.PasswordCredentials != null)
            {
                var passCred = app.PasswordCredentials.FirstOrDefault(x => x.CustomKeyIdentifier == Convert.ToBase64String(_emg.Id.ToByteArray()));
                if (passCred != null)
                { 
                    app.PasswordCredentials.Remove(passCred);
                    await cl.UpdateApplicationAsync(app);
                }
            }
        }
        private async Task RenewServiceCredential(GraphClient cl, ManagementPack configMp, AdApplication app, TimeSpan credValidity)
        {
            if (app == null)
                throw new ArgumentNullException(nameof(app));

            if (app.PasswordCredentials != null)
            {
                var passCred = app.PasswordCredentials.FirstOrDefault(x => x.CustomKeyIdentifier == Convert.ToBase64String(_emg.Id.ToByteArray()));
                if (passCred != null)
                    app.PasswordCredentials.Remove(passCred);
                await cl.UpdateApplicationAsync(app);
            }

            var pass = RandomString();
            var securePass = new System.Security.SecureString();
            foreach (char c in pass)
                securePass.AppendChar(c);

            var endDate = DateTime.UtcNow + credValidity;

            app.PasswordCredentials.Add(new PasswordCredential()
            {
                EndDate = endDate,
                StartDate = DateTime.UtcNow,
                KeyId = Guid.NewGuid(),
                Value = pass,
                CustomKeyIdentifier = Convert.ToBase64String(_emg.Id.ToByteArray())
            });
            await cl.UpdateApplicationAsync(app);

            bool isNew = false;
            var secData = (BasicCredentialSecureData)_emg.Security.GetSecureData(new SecureDataCriteria($"Name = '{Parameters.SECURE_REFERENCE_NAME}'")).FirstOrDefault();

            if (secData == null)
            {
                secData = new BasicCredentialSecureData();
                isNew = true;                
            }

            secData.UserName = app.AppId.ToString();
            secData.Data = securePass;
            secData.Name = Parameters.SECURE_REFERENCE_NAME;

            if (isNew)
                _emg.Security.InsertSecureData(secData);
            secData.Update();

            var secRefOverride = (ManagementPackSecureReferenceOverride)_emg.Overrides.GetOverrides(new ManagementPackOverrideCriteria($"Name = '{Parameters.SECURE_REFERENCE_OVERRIDE_NAME}'")).FirstOrDefault();
            if (secRefOverride == null)
                secRefOverride = new ManagementPackSecureReferenceOverride(configMp, Parameters.SECURE_REFERENCE_OVERRIDE_NAME);

            secRefOverride.DisplayName = Parameters.SECURE_REFERENCE_OVERRIDE_NAME;
            secRefOverride.Context = EntityClass;
            secRefOverride.SecureReference = ConnectorSecureReference;
            secRefOverride.Value = BitConverter.ToString(secData.SecureStorageId, 0, secData.SecureStorageId.Length).Replace("-", "");

            secRefOverride.GetManagementPack().AcceptChanges();

            Settings.CredentialExpirationDate = endDate;
        }
        public async Task RenewServiceCredential(TimeSpan credValidity)
        {
            try
            {
                ProgressStatus = "Renewing workflow credentials...";
                var mp = AssureConfigManagementPack();
                var client = new GraphClient(Settings.TenantId);
                client.AuthorizationCodeRequired += client_AuthorizationCodeRequired;

                var app = await AssureAzureAdAppAndPrincipal(client, Settings.TenantId);
                if (app == null) return;
                await RenewServiceCredential(client, mp, app, credValidity);
                CommitSettings();
            }
            catch (Exception e)
            {
                ShowError(e);
            }
        }
        public async Task Disconnect()
        {
            try
            {
                var res = MessageBox.Show("Are you sure you want to disconnect?", "Please confirm", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
                if (res != MessageBoxResult.OK) return;

                var r = MessageBox.Show("Do you also want to delete application in Azure AD? If you have other management groups connected to the same tenant this will break the connection", "Delete application", MessageBoxButton.YesNo, MessageBoxImage.Question);

                ProgressStatus = "Removing configuration...";
                var mp = AssureConfigManagementPack();
                var client = new GraphClient(Settings.TenantId);
                client.AuthorizationCodeRequired += client_AuthorizationCodeRequired;

                await RemoveServiceCredential(client, mp);

                if (r == MessageBoxResult.Yes)
                    await client.DeleteServicePrincipalAndApplicationAsync();

                //DisableWorkflows();
                ClearSettings();
                RefreshSettings();
            }
            catch (Exception e)
            {
                ShowError(e);
            }
        }
        public async Task<bool> Connect(AutomationAccountInfo accountInfo, TimeSpan credValidity)
        {
            try
            {
                ProgressStatus = "Configuring...";
                var mp = AssureConfigManagementPack();
                var client = new GraphClient(accountInfo.TenantId);
                client.AuthorizationCodeRequired += client_AuthorizationCodeRequired;

                ProgressStatus = "Configuring service principal...";
                var app = await AssureAzureAdAppAndPrincipal(client, accountInfo.TenantId);

                if (app == null) return false;
                await RenewServiceCredential(client, mp, app, credValidity);

                ProgressStatus = "Setting service principal permissions...";
                var principal = await client.GetServicePrincipalAsync(app.AppId);
                await _configClient.SetServicePrincipalPermission(accountInfo, principal.ObjectId);

                ProgressStatus = "Saving changes...";
                Settings.TenantId = accountInfo.TenantId;
                Settings.SubscriptionId = accountInfo.SubscriptionId;
                Settings.ResourceGroupName = accountInfo.ResourceGroupName;
                Settings.AutomationAccountName = accountInfo.AutomationAccountName;
                if (string.IsNullOrEmpty(Settings.DefaultRunOn))
                    Settings.DefaultRunOn = "Azure";
                //EnableWorkflows();
                CommitSettings();
                return true;
            }
            catch (Exception e)
            {
                ShowError(e);
                return false;
            }
        }