private string GetUserPrincipalName(int nameFormat)
        {
            if (DesktopOsHelper.IsWindows())
            {
                uint userNameSize = 0;
                WindowsNativeMethods.GetUserNameEx(nameFormat, null, ref userNameSize);
                if (userNameSize == 0)
                {
                    throw new MsalClientException(
                              MsalError.GetUserNameFailed,
                              MsalErrorMessage.GetUserNameFailed,
                              new Win32Exception(Marshal.GetLastWin32Error()));
                }

                var sb = new StringBuilder((int)userNameSize);
                if (!WindowsNativeMethods.GetUserNameEx(nameFormat, sb, ref userNameSize))
                {
                    throw new MsalClientException(
                              MsalError.GetUserNameFailed,
                              MsalErrorMessage.GetUserNameFailed,
                              new Win32Exception(Marshal.GetLastWin32Error()));
                }

                return(sb.ToString());
            }

            throw new PlatformNotSupportedException(
                      "MSAL cannot determine the username (UPN) of the currently logged in user." +
                      "For Integrated Windows Authentication and Username/Password flows, please use .WithUsername() before calling ExecuteAsync(). " +
                      "For more details see https://aka.ms/msal-net-iwa");
        }
        public void IsBrokerAvailable_net5()
        {
            var appBuilder = PublicClientApplicationBuilder
                             .Create(TestConstants.ClientId);

            Assert.AreEqual(DesktopOsHelper.IsWin10OrServerEquivalent(), appBuilder.IsBrokerAvailable());
        }
        public void WamOnWin10()
        {
            if (!DesktopOsHelper.IsWin10OrServerEquivalent())
            {
                Assert.Inconclusive("Needs to run on win10 or equivalent");
            }
            var pcaBuilder = PublicClientApplicationBuilder
                             .Create("d3adb33f-c0de-ed0c-c0de-deadb33fc0d3")
                             .WithAuthority(TestConstants.AuthorityTenant);

            pcaBuilder = pcaBuilder.WithBrokerPreview();
            Assert.IsTrue(pcaBuilder.IsBrokerAvailable());
        }
Пример #4
0
        public bool IsBrokerInstalledAndInvokable()
        {
#if NET_CORE
            if (!DesktopOsHelper.IsWindows())
            {
                return(false);
            }
#endif
            // WAM is present on Win 10 only
            return(ApiInformation.IsMethodPresent(
                       "Windows.Security.Authentication.Web.Core.WebAuthenticationCoreManager",
                       "GetTokenSilentlyAsync"));
        }
Пример #5
0
 public override IBroker CreateBroker(ApplicationConfiguration appConfig, CoreUIParent uiParent)
 {
     if (DesktopOsHelper.IsWin10OrServerEquivalent())
     {
         return(appConfig.BrokerCreatorFunc != null?
                appConfig.BrokerCreatorFunc(uiParent, appConfig, Logger) :
                    new Features.WamBroker.WamBroker(uiParent, appConfig, Logger));
     }
     else
     {
         Logger.Info("Not a Win10 machine. WAM is not available");
         return(new NullBroker());
     }
 }
        public override IBroker CreateBroker(ApplicationConfiguration appConfig, CoreUIParent uiParent)
        {
            if (DesktopOsHelper.IsWin10OrServerEquivalent())
            {
                Logger.Info("WAM supported OS. ");

                return(appConfig.BrokerCreatorFunc != null?
                       appConfig.BrokerCreatorFunc(uiParent, appConfig, Logger) :
                           new Features.WamBroker.WamBroker(uiParent, appConfig, Logger));
            }
            else
            {
                Logger.Info("WAM is not available. WAM is supported only on Windows 10+ or Windows Server 2019+");
                return(new NullBroker(Logger));
            }
        }
        /// <summary>
        /// Reads a Kerberos Service Ticket associated with given service principal name from
        /// current user's Ticket Cache.
        /// </summary>
        /// <param name="servicePrincipalName">Service principal name to find associated Kerberos Ticket.</param>
        /// <param name="logonId">The Logon Id of the user owning the ticket cache.
        /// The default of 0 represents the currently logged on user.</param>
        /// <returns>Byte stream of searched Kerberos Ticket information if exists. Null, otherwise.</returns>
        /// <remarks>
        /// Can throws <see cref="Win32Exception"/> if error occurs while searching ticket information from Ticket Cache.
        /// </remarks>
        public static byte[] GetKerberosTicketFromWindowsTicketCache(string servicePrincipalName, long logonId)
        {
#if !SUPPORTS_WIN32
            throw new PlatformNotSupportedException("Ticket Cache interface is not supported for this .NET platform. It is supported on .NET Classic, .NET Core and NetStandadrd");
#else
            if (!DesktopOsHelper.IsWindows())
            {
                throw new PlatformNotSupportedException("Ticket Cache interface is not supported on this OS. It is supported on Windows only.");
            }

            using (var reader = new Platforms.Features.DesktopOs.Kerberos.TicketCacheReader(servicePrincipalName, logonId))
            {
                return(reader.RequestToken());
            }
#endif
        }
        public SspiSecurityContext(
            Credential credential,
            string package,
            long logonId = 0,
            InitContextFlag clientFlags = _defaultRequiredFlags)
        {
            if (!DesktopOsHelper.IsWindows())
            {
                throw new PlatformNotSupportedException("Ticket Cache interface is not supported for this OS platform.");
            }

            _credential  = credential;
            _clientFlags = clientFlags;
            Package      = package;
            _logonId     = logonId;
        }
        public void IsBrokerAvailable_OldDotNet()
        {
            var builder1 = PublicClientApplicationBuilder
                           .Create(TestConstants.ClientId);


            // broker is not available out of the box
            Assert.AreEqual(false, builder1.IsBrokerAvailable());

            var builder2 = PublicClientApplicationBuilder
                           .Create(TestConstants.ClientId)
                           .WithDesktopFeatures();


            // broker is not available out of the box
            Assert.AreEqual(DesktopOsHelper.IsWin10OrServerEquivalent(), builder2.IsBrokerAvailable());
        }
Пример #10
0
 internal static void AddSupportForWam(PublicClientApplicationBuilder builder)
 {
     if (DesktopOsHelper.IsWin10OrServerEquivalent())
     {
         builder.Config.BrokerCreatorFunc =
             (uiParent, appConfig, logger) => new Platforms.Features.WamBroker.WamBroker(uiParent, appConfig, logger);
     }
     else
     {
         builder.Config.BrokerCreatorFunc =
             (uiParent, appConfig, logger) =>
         {
             logger.Info("Not a Win10 machine. WAM is not available");
             return(new NullBroker());
         };
     }
 }
Пример #11
0
        /// <summary>
        /// Brokers enable Single-Sign-On, device identification,
        /// and application identification verification. To enable one of these features,
        /// you need to set the WithBroker() parameters to true. See https://aka.ms/msal-net-brokers
        /// for more information on platform specific settings required to enable the broker.
        ///
        /// On iOS and Android, Authenticator and Company Portal serve as brokers.
        /// On Windows, WAM (Windows Account Manager) serves as broker. See https://aka.ms/msal-net-wam
        /// </summary>
        /// <param name="enableBroker">Determines whether or not to use broker with the default set to true.</param>
        /// <returns>A <see cref="PublicClientApplicationBuilder"/> from which to set more
        /// parameters, and to create a public client application instance</returns>
        /// <remarks>If your app uses .NET classic or .NET Core 3.x, and you wish to use the Windows broker,
        /// please install the nuget package Microsoft.Identity.Client.Desktop and call .WithDesktopFeatures()</remarks>
        public PublicClientApplicationBuilder WithBroker(bool enableBroker = true)
        {
#pragma warning disable CS0162 // Unreachable code detected

#if NET45
            throw new PlatformNotSupportedException(
                      "The Windows broker is not available on .NET Framework 4.5, please use at least .NET Framework 4.6.2");
#endif

#if NET461
            if (Config.BrokerCreatorFunc == null)
            {
                throw new PlatformNotSupportedException(
                          "The Windows broker is not directly available on MSAL for .NET Framework" +
                          " To use it, please install the nuget package named Microsoft.Identity.Client.Desktop " +
                          "and call the extension method .WithWindowsBroker() first.");
            }
#endif

#if NET_CORE
            if (Config.BrokerCreatorFunc == null && DesktopOsHelper.IsWindows())
            {
                throw new PlatformNotSupportedException(
                          "If you have a Windows application which targets net5 or net5-windows, please change the target to net5-windows10.0.17763.0. \nYour app can still run on earlier versions of Windows such as Win7 if you add <SupportedOSPlatformVersion>7</SupportedOSPlatformVersion> in the csproj.\n The broker (WAM) is available only on Win10 and this library will fallback to a browser on older systems. " +

                          "\n\r\n\rIf you have a NET5 cross-platform (Windows, Mac, Linux) application, please dual target net5 and net5-windows10.0.17763.0. Your installer should deploy the net5 version on Mac and Linux and the net5-window10.0.17763.0 on Windows." +
                          "\n\r\n\rIf you have a .NET Core 3.1 application, please install the nuget package named Microsoft.Identity.Client.Desktop and call the extension method .WithWindowsBroker() first. " +
                          "\n\rFor details see https://aka.ms/msal-net-wam and https://github.com/dotnet/designs/blob/main/accepted/2020/platform-checks/platform-checks.md ");
            }
#endif

#if NET461 || WINDOWS_APP || NET5_WIN
            if (!Config.ExperimentalFeaturesEnabled)
            {
                throw new MsalClientException(
                          MsalError.ExperimentalFeature,
                          MsalErrorMessage.ExperimentalFeature(nameof(WithBroker)));
            }
#endif

            Config.IsBrokerEnabled = enableBroker;
            return(this);

#pragma warning restore CS0162 // Unreachable code detected
        }
        public bool IsBrokerInstalledAndInvokable(AuthorityType authorityType)
        {
            if (!DesktopOsHelper.IsWin10OrServerEquivalent())
            {
                _logger.Warning("[WAM Broker] Not a supported operating system. WAM broker is not available. ");
                return(false);
            }

            // WAM does not work on pure ADFS environments
            if (authorityType == AuthorityType.Adfs)
            {
                _logger.Warning("[WAM Broker] WAM does not work in pure ADFS environments. Falling back to browser for an ADFS authority. ");
                return(false);
            }

            _logger.Verbose("[WAM Broker] IsBrokerInstalledAndInvokable true");
            return(true);
        }
Пример #13
0
        /// <summary>
        /// Brokers enable Single-Sign-On, device identification,
        /// and application identification verification. To enable one of these features,
        /// you need to set the WithBroker() parameters to true. See https://aka.ms/msal-net-brokers
        /// for more information on platform specific settings required to enable the broker.
        ///
        /// On iOS and Android, Authenticator and Company Portal serve as brokers.
        /// On Windows, WAM (Windows Account Manager) serves as broker. See https://aka.ms/msal-net-wam
        /// </summary>
        /// <param name="enableBroker">Determines whether or not to use broker with the default set to true.</param>
        /// <returns>A <see cref="PublicClientApplicationBuilder"/> from which to set more
        /// parameters, and to create a public client application instance</returns>
        /// <remarks>If your app uses .NET classic or .NET Core 3.x, and you wish to use the Windows broker,
        /// please install the nuget package Microsoft.Identity.Client.Desktop and call .WithDesktopFeatures()</remarks>
        public PublicClientApplicationBuilder WithBroker(bool enableBroker = true)
        {
#pragma warning disable CS0162 // Unreachable code detected

#if NET45
            throw new PlatformNotSupportedException(
                      "The Windows broker is not available on .NET Framework 4.5, please use at least .NET Framework 4.6.2");
#endif

#if NET461
            if (Config.BrokerCreatorFunc == null)
            {
                throw new PlatformNotSupportedException(
                          "The Windows broker is not directly available on MSAL for .NET Framework" +
                          " To use it, please install the nuget package named Microsoft.Identity.Client.Desktop " +
                          "and call the extension method .WithDesktopFeatures() first.");
            }
#endif

#if NET_CORE
            if (Config.BrokerCreatorFunc == null && DesktopOsHelper.IsWindows())
            {
                throw new PlatformNotSupportedException(
                          "If you have a Windows application which targets net5 or net5-windows, please change the target to net5-windows10.0.17763.0, which provides support from Win7 to Win10. For details see https://github.com/dotnet/designs/blob/main/accepted/2020/platform-checks/platform-checks.md" +
                          "If you have a cross-platform (Windows, Mac, Linux) application which targets net5, please dual target net5 and net5-windows10.0.17763.0. Your installer should deploy the net5 version on Mac and Linux and the net5-window10.0.17763.0 on Win7-Win10. For details see https://github.com/dotnet/designs/blob/main/accepted/2020/platform-checks/platform-checks.md" +
                          "If you have a .NET Core 3.1 application, please install the nuget package named Microsoft.Identity.Client.Desktop and call the extension method .WithDesktopFeatures() first.");
            }
#endif

#if NET461 || WINDOWS_APP || NET5_WIN
            if (!Config.ExperimentalFeaturesEnabled)
            {
                throw new MsalClientException(
                          MsalError.ExperimentalFeature,
                          MsalErrorMessage.ExperimentalFeature(nameof(WithBroker)));
            }
#endif

            Config.IsBrokerEnabled = enableBroker;
            return(this);

#pragma warning restore CS0162 // Unreachable code detected
        }
 private static void AddRuntimeSupportForWam(PublicClientApplicationBuilder builder)
 {
     if (DesktopOsHelper.IsWin10OrServerEquivalent())
     {
         builder.Config.BrokerCreatorFunc =
             (uiParent, appConfig, logger) =>
         {
             logger.Info("WAM supported OS.");
             return(new RuntimeBroker(uiParent, appConfig, logger));
         };
     }
     else
     {
         builder.Config.BrokerCreatorFunc =
             (uiParent, appConfig, logger) =>
         {
             logger.Info("Not a Win10 machine. WAM is not available");
             return(new NullBroker(logger));
         };
     }
 }
        /// <summary>
        /// Save current Kerberos Ticket to current user's Ticket Cache. Windows only.
        /// </summary>
        /// <param name="ticket">Kerberos ticket object to save.</param>
        /// <param name="logonId">The Logon Id of the user owning the ticket cache.
        /// The default of 0 represents the currently logged on user.</param>
        /// <remarks>Can throw <see cref="ArgumentException"/> when given ticket parameter is not a valid Kerberos Supplemental Ticket.
        /// Can throw <see cref="Win32Exception"/> if error occurs while saving ticket information into Ticket Cache.
        /// </remarks>
        public static void SaveToWindowsTicketCache(KerberosSupplementalTicket ticket, long logonId)
        {
#if !SUPPORTS_WIN32
            throw new PlatformNotSupportedException("Ticket Cache interface is not supported for this .NET platform. It is supported on .NET Classic, .NET Core and NetStandadrd");
#else
            if (!DesktopOsHelper.IsWindows())
            {
                throw new PlatformNotSupportedException("Ticket Cache interface is not supported on this OS. It is supported on Windows only.");
            }

            if (ticket == null || string.IsNullOrEmpty(ticket.KerberosMessageBuffer))
            {
                throw new ArgumentException("Kerberos Ticket information is not valid");
            }

            using (var cache = Platforms.Features.DesktopOs.Kerberos.TicketCacheWriter.Connect())
            {
                byte[] krbCred = Convert.FromBase64String(ticket.KerberosMessageBuffer);
                cache.ImportCredential(krbCred, logonId);
            }
#endif
        }
Пример #16
0
        public bool IsBrokerInstalledAndInvokable(AuthorityType authorityType)
        {
#if NET_CORE
            if (!DesktopOsHelper.IsWindows())
            {
                _logger.Info("[WAM Broker] Not a Windows operating system. WAM broker is not available. ");
                return(false);
            }
#endif
            // WAM does not work on pure ADFS environments
            if (authorityType == AuthorityType.Adfs)
            {
                _logger.Info("[WAM Broker] WAM does not work in pure ADFS environments. Falling back to browser for an ADFS authority. ");
                return(false);
            }

            _logger.Info("[WAM Broker] Authority is AAD. Using WAM Broker. ");

            // WAM is present on Win 10 only
            return(ApiInformation.IsMethodPresent(
                       "Windows.Security.Authentication.Web.Core.WebAuthenticationCoreManager",
                       "GetTokenSilentlyAsync"));
        }
Пример #17
0
        /// <summary>
        /// Validates Windows Ticket Cache interface for the given <see cref="KerberosSupplementalTicket"/> Kerberos Ticket.
        /// </summary>
        /// <param name="ticket">A <see cref="KerberosSupplementalTicket"/> object to be checked.</param>
        public static void ValidateKerberosWindowsTicketCacheOperation(KerberosSupplementalTicket ticket)
        {
            if (DesktopOsHelper.IsWindows())
            {
                // First, save the given Kerberos Ticket (with KRB-CRED format) into the Windows Ticket Cache.
                // Windows Ticket Cache decrypts the given Kerberos Ticket with KRB-CRED format, re-encrypt with it's
                // credential and save it as AP-REQ format.
                KerberosSupplementalTicketManager.SaveToWindowsTicketCache(ticket);

                // Read-back saved Ticket data.
                byte[] ticketBytes
                    = KerberosSupplementalTicketManager.GetKerberosTicketFromWindowsTicketCache(ticket.ServicePrincipalName);
                Assert.IsNotNull(ticketBytes);

                // To validate public field of AP-REQ format Kerberos Ticket, convert binary ticket data as a printable string format.
                StringBuilder sb = new StringBuilder();
                foreach (byte ch in ticketBytes)
                {
                    if (ch >= 32 && ch < 127)
                    {
                        sb.Append((char)ch);
                    }
                    else
                    {
                        sb.Append('*');
                    }
                }
                string ticketAsString = sb.ToString();

                // Check the Azure AD Kerberos Realm string exists.
                Assert.IsTrue(ticketAsString.IndexOf(TestConstants.AzureADKerberosRealmName) >= 0);

                // Check the ticket has matched Kerberos Service Principal Name.
                Assert.IsTrue(ticketAsString.IndexOf(TestConstants.KerberosServicePrincipalNameEscaped, StringComparison.OrdinalIgnoreCase) >= 0);
            }
        }
Пример #18
0
 /// <inheritdoc />
 protected override string InternalGetOperatingSystem()
 {
     return(DesktopOsHelper.GetWindowsVersionString());
 }
        public override Task StartDefaultOsBrowserAsync(string url)
        {
            if (DesktopOsHelper.IsWindows())
            {
                try
                {
                    var psi = new ProcessStartInfo
                    {
                        FileName        = url,
                        UseShellExecute = true
                    };
                    Process.Start(psi);
                }
                catch
                {
                    // hack because of this: https://github.com/dotnet/corefx/issues/10361
                    url = url.Replace("&", "^&");
                    Process.Start(new ProcessStartInfo("cmd", $"/c start msedge {url}")
                    {
                        CreateNoWindow = true
                    });
                }
            }
            else if (DesktopOsHelper.IsLinux())
            {
                try
                {
                    ProcessStartInfo psi = null;
                    foreach (string openTool in new[] { "xdg-open", "gnome-open", "kfmclient" })
                    {
                        if (TryGetExecutablePath(openTool, out string openToolPath))
                        {
                            psi = new ProcessStartInfo(openToolPath, url)
                            {
                                RedirectStandardOutput = true,
                                RedirectStandardError  = true
                            };

                            Process.Start(psi);

                            break;
                        }
                    }

                    if (psi == null)
                    {
                        throw new Exception("Failed to locate a utility to launch the default web browser.");
                    }
                }
                catch (Exception ex)
                {
                    throw new MsalClientException(
                              MsalError.LinuxXdgOpen,
                              MsalErrorMessage.LinuxOpenToolFailed,
                              ex);
                }
            }
            else if (DesktopOsHelper.IsMac())
            {
                Process.Start("/usr/bin/open", url);
            }
            else
            {
                throw new PlatformNotSupportedException(RuntimeInformation.OSDescription);
            }
            return(Task.FromResult(0));
        }
Пример #20
0
 protected override string InternalGetProcessorArchitecture()
 {
     return(DesktopOsHelper.IsWindows() ? WindowsNativeMethods.GetProcessorArchitecture() : null);
 }
Пример #21
0
        public override Task StartDefaultOsBrowserAsync(string url, bool isBrokerConfigured)
        {
            if (DesktopOsHelper.IsWindows())
            {
                try
                {
                    var psi = new ProcessStartInfo
                    {
                        FileName        = url,
                        UseShellExecute = true
                    };
                    Process.Start(psi);
                }
                catch
                {
                    // hack because of this: https://github.com/dotnet/corefx/issues/10361
                    url = url.Replace("&", "^&");
                    Process.Start(new ProcessStartInfo("cmd", $"/c start msedge {url}")
                    {
                        CreateNoWindow = true
                    });
                }
            }
            else if (DesktopOsHelper.IsLinux())
            {
                string sudoUser = Environment.GetEnvironmentVariable("SUDO_USER");
                if (!string.IsNullOrWhiteSpace(sudoUser))
                {
                    throw new MsalClientException(
                              MsalError.LinuxXdgOpen,
                              MsalErrorMessage.LinuxOpenAsSudoNotSupported);
                }

                try
                {
                    bool opened = false;

                    foreach (string openTool in GetOpenToolsLinux(isBrokerConfigured))
                    {
                        if (TryGetExecutablePath(openTool, out string openToolPath))
                        {
                            OpenLinuxBrowser(openToolPath, url);
                            opened = true;
                            break;
                        }
                    }

                    if (!opened)

                    {
                        throw new MsalClientException(
                                  MsalError.LinuxXdgOpen,
                                  MsalErrorMessage.LinuxOpenToolFailed);
                    }
                }
                catch (Exception ex)
                {
                    throw new MsalClientException(
                              MsalError.LinuxXdgOpen,
                              MsalErrorMessage.LinuxOpenToolFailed,
                              ex);
                }
            }
            else if (DesktopOsHelper.IsMac())
            {
                Process.Start("/usr/bin/open", url);
            }
            else
            {
                throw new PlatformNotSupportedException(RuntimeInformation.OSDescription);
            }
            return(Task.FromResult(0));
        }