/// <summary>
        /// Obtain an access token using MSAL running inside the current process.
        /// </summary>
        private async Task <JsonWebToken> GetAccessTokenInProcAsync(string authority, string clientId, Uri redirectUri, string[] scopes, string userName)
        {
            IPublicClientApplication app = await CreatePublicClientApplicationAsync(authority, clientId, redirectUri);

            AuthenticationResult result = null;

            // Try silent authentication first if we know about an existing user
            if (!string.IsNullOrWhiteSpace(userName))
            {
                result = await GetAccessTokenSilentlyAsync(app, scopes, userName);
            }

            //
            // If we failed to acquire an AT silently (either because we don't have an existing user, or the user's RT has expired)
            // we need to prompt the user for credentials.
            //
            // Depending on the current platform and session type we try to show the most appropriate authentication interface:
            //
            // On .NET Framework MSAL supports the WinForms based 'embedded' webview UI. For Windows + .NET Framework this is the
            // best and natural experience.
            //
            // On other runtimes (e.g., .NET Core) MSAL only supports the system webview flow (launch the user's browser),
            // and the device-code flows.
            //
            //     Note: .NET Core 3 allows using WinForms when run on Windows but MSAL does not yet support this.
            //
            // The system webview flow requires that the redirect URI is a loopback address, and that we are in an interactive session.
            //
            // The device code flow has no limitations other than a way to communicate to the user the code required to authenticate.
            //
            if (result is null)
            {
#if NETFRAMEWORK
                // If we're in an interactive session and on .NET Framework, let MSAL show the WinForms-based embeded UI
                if (PlatformUtils.IsInteractiveSession())
                {
                    result = await app.AcquireTokenInteractive(scopes)
                             .WithPrompt(Prompt.SelectAccount)
                             .WithUseEmbeddedWebView(true)
                             .ExecuteAsync();
                }
#elif NETSTANDARD
                // MSAL requires the application redirect URI is a loopback address to use the System WebView
                if (PlatformUtils.IsInteractiveSession() && app.IsSystemWebViewAvailable && redirectUri.IsLoopback)
                {
                    result = await app.AcquireTokenInteractive(scopes)
                             .WithPrompt(Prompt.SelectAccount)
                             .WithSystemWebViewOptions(GetSystemWebViewOptions())
                             .ExecuteAsync();
                }
#endif
                // If we do not have a way to show a GUI, use device code flow over the TTY
                else
                {
                    EnsureTerminalPromptsEnabled();

                    result = await app.AcquireTokenWithDeviceCode(scopes, ShowDeviceCodeInTty).ExecuteAsync();
                }
            }

            return(new JsonWebToken(result.AccessToken));
        }