diff --git a/LibsAndSamples.sln b/LibsAndSamples.sln index ee3f05d15d..d9a246792d 100644 --- a/LibsAndSamples.sln +++ b/LibsAndSamples.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.3.32708.82 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11217.181 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9B0B5396-4D95-4C15-82ED-DC22B5A3123F}" ProjectSection(SolutionItems) = preProject @@ -117,8 +117,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Client.D EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsTestApp", "tests\devapps\WinFormsTestApp\WinFormsTestApp.csproj", "{F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KerberosConsole", "tests\devapps\KerberosConsole\KerberosConsole.csproj", "{94F35780-220A-4C08-83B9-41168F7017CD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net5TestApp", "tests\devapps\Net5TestApp\Net5TestApp.csproj", "{998D38B3-344C-4F19-833E-6181B0834AF6}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebApi", "WebApi", "{CC07F293-91B9-45A3-AA3A-77885BBCB624}" @@ -1050,47 +1048,6 @@ Global {F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}.Release|x64.Build.0 = Release|x64 {F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}.Release|x86.ActiveCfg = Release|x86 {F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}.Release|x86.Build.0 = Release|x86 - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|Any CPU.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|Any CPU.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM64.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM64.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhone.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhone.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhoneSimulator.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhoneSimulator.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x64.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x64.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x86.ActiveCfg = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x86.Build.0 = Debug + MobileApps|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM64.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhone.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x64.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x64.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x86.ActiveCfg = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x86.Build.0 = Debug|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM.Build.0 = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM64.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM64.Build.0 = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhone.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhone.Build.0 = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|x64.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|x64.Build.0 = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|x86.ActiveCfg = Release|Any CPU - {94F35780-220A-4C08-83B9-41168F7017CD}.Release|x86.Build.0 = Release|Any CPU {998D38B3-344C-4F19-833E-6181B0834AF6}.Debug + MobileApps|Any CPU.ActiveCfg = Debug + MobileApps|Any CPU {998D38B3-344C-4F19-833E-6181B0834AF6}.Debug + MobileApps|Any CPU.Build.0 = Debug + MobileApps|Any CPU {998D38B3-344C-4F19-833E-6181B0834AF6}.Debug + MobileApps|ARM.ActiveCfg = Debug + MobileApps|Any CPU @@ -2062,7 +2019,6 @@ Global {A7679FF0-19E8-41E3-9F7C-F54235124CC4} = {1A37FD75-94E9-4D6F-953A-0DABBD7B49E9} {B8689FF1-20F9-4669-CF55-9B2E8B5F8DD5} = {1A37FD75-94E9-4D6F-953A-0DABBD7B49E9} {F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB} - {94F35780-220A-4C08-83B9-41168F7017CD} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB} {998D38B3-344C-4F19-833E-6181B0834AF6} = {384BA371-F17F-4A70-9423-D54F71BB3FCB} {CC07F293-91B9-45A3-AA3A-77885BBCB624} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB} {DD23D8FF-86BA-4E9F-8AF1-0EBE0D86986A} = {CC07F293-91B9-45A3-AA3A-77885BBCB624} diff --git a/tests/devapps/KerberosConsole/AADKerberosLogger.cs b/tests/devapps/KerberosConsole/AADKerberosLogger.cs deleted file mode 100644 index 199073c0f1..0000000000 --- a/tests/devapps/KerberosConsole/AADKerberosLogger.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; - -namespace KerberosConsole -{ - /// - /// Helper to provide internal tracking log for debugging. - /// Shows the message to the console and save to internal log file under 'Documents' folder. - /// - public static class AADKerberosLogger - { - private static int _bytesPerLine = 16; - private static int _lastFileIndex = 0; - - /// - /// Name of log file. - /// - private static string _logFileName = ""; - - /// - /// Filename to save log data. - /// - internal static string LogFileName - { - get - { - if (string.IsNullOrEmpty(_logFileName)) - { - do - { - _lastFileIndex++; - - _logFileName = String.Format( - CultureInfo.InvariantCulture, - @"{0}\AzureAD-MSAL-{1}-{2}.log", - Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), - DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), - _lastFileIndex); - } while (File.Exists(_logFileName)); - } - return _logFileName; - } - } - - public static bool SkipLoggingToConsole - { - get; - set; - } = false; - - /// - /// Save the given formatted log text to log file. - /// - /// The message formatter. - /// The message format variables. - public static void Format(string format, params object[] args) - { - var entry = string.Format(CultureInfo.InvariantCulture, format, args); - Save(entry); - } - - /// - /// Save the given log text to log file. - /// - /// Log message to be saved. - public static void Save(string logText) - { - if (!SkipLoggingToConsole) - { - Console.WriteLine("[AADKerberos] " + logText); - } - - File.AppendAllText(LogFileName, logText + Environment.NewLine); - } - - /// - /// Output given enumber of empty lines. - /// - /// Number of empty lines to display. - public static void PrintLines(int numLines = 1) - { - if (numLines > 0) - { - string message = ""; - for (int i = 0; i < numLines; i++) - { - message += Environment.NewLine; - } - - if (!SkipLoggingToConsole) - { - Console.Write(message); - } - - File.AppendAllText(LogFileName, message); - } - } - - /// - /// Save the given log text to log file with timestamp. - /// - /// Log message to be saved. - public static void SaveWithTimestamp(string logText) - { - string logMessage = DateTime.Now.ToString("s", CultureInfo.InvariantCulture) + ": " + logText; - - if (!SkipLoggingToConsole) - { - Console.WriteLine("[AADKerberos] " + logMessage); - } - - File.AppendAllText( - LogFileName, - Environment.NewLine + logMessage + Environment.NewLine); - } - - /// - /// Convert given string table as Loggable text. - /// - /// String table to be converted. - /// Loggable test string. - public static string ToString(IDictionary dict) - { - StringBuilder sb = new StringBuilder(); - foreach (string key in dict.Keys) - { - sb.Append("\n " + key) - .Append(": ") - .Append(dict[key]); - } - - return sb.ToString(); - } - - /// - /// Convert given string list as Loggable text. - /// - /// String list to be converted. - /// Loggable test string. - public static string ToString(IEnumerable list) - { - StringBuilder sb = new StringBuilder(); - foreach (string str in list) - { - if (sb.Length > 0) - { - sb.Append(", "); - } - - sb.Append(str); - } - - return sb.ToString(); - } - - /// - /// Shows given binary data with HEX display format as following format: - /// 1C 4B 45 52 42 45 52 4F 53 2E 4D 49 43 52 4F 53 *KERBEROS.MICROS - /// - /// Array of binary data to be displayed. - public static void PrintBinaryData(byte[] dataToPrint) - { - char[] line = new char[256]; - int charIndexBegin = _bytesPerLine * 3; - int endOfLine = charIndexBegin + _bytesPerLine; - - for (int i = 0; i < dataToPrint.Length; i += _bytesPerLine) - { - int index = 0, charindex = charIndexBegin; - Array.Fill(line, ' '); - - for (int j = 0; (i + j) < dataToPrint.Length && j < _bytesPerLine; j++) - { - string hex = dataToPrint[i + j].ToString("X2", CultureInfo.InvariantCulture); - line[index] = hex[0]; - line[index + 1] = hex[1]; - - if (dataToPrint[i + j] >= 32 && dataToPrint[i + j] < 127) - { - line[charindex] = (char)dataToPrint[i + j]; - } - else - { - line[charindex] = '*'; - } - - charindex++; - index += 3; - } - - line[endOfLine] = (char) 0; - Save(new string(line, 0, _bytesPerLine * 4)); - } - } - } -} diff --git a/tests/devapps/KerberosConsole/KerberosConsole.csproj b/tests/devapps/KerberosConsole/KerberosConsole.csproj deleted file mode 100644 index 56ff0e961a..0000000000 --- a/tests/devapps/KerberosConsole/KerberosConsole.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net8 - Debug;Release;Debug + MobileApps - - - - - - - - - - - - - diff --git a/tests/devapps/KerberosConsole/Program.cs b/tests/devapps/KerberosConsole/Program.cs deleted file mode 100644 index 139b9177fa..0000000000 --- a/tests/devapps/KerberosConsole/Program.cs +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.Identity.Client; -using Microsoft.Identity.Client.Kerberos; - -using System; -using System.ComponentModel; -using System.Globalization; -using System.Security; -using System.Threading.Tasks; - -namespace KerberosConsole -{ - /// - /// It is a sample console program to show the primary usage of the Azure AD Kerberos Feature. - /// Usages: - /// KerberosConsole -h - /// show usage format. - /// KerberosConsole -cached - /// find cached Kerberos Ticket with default name defined in the sample application. - /// KerberosConsole -cached -spn {spn name} - /// find cached Kerberos ticket matched with given {spn name}. - /// KerberosConsole - /// acquire an authentication token, retrieves the Kerberos Ticket, and cache it into the - /// current user's Windows Ticket Cache. You can check cached ticket information with "klist" - /// utility command or "KerberosConsole -cached" command. - /// KerberosConsole -devicecodeflow - /// acquire an authentication token using the device code flow. - /// KerberosConsole -upn john@contoso.com -password passwordxxx - /// acquire an authentication token using Username/Password flow. - /// You have to provide both the upn and password. - /// Note: - /// This application uses the Kerberos.NET package to show detailed information of a cached - /// Kerberos Ticket. You can get detailed information for the Kerberos.NET package here: - /// https://www.nuget.org/packages/Kerberos.NET/ - /// - class Program - { - private string _tenantId = "428881af-9ab1-40b3-8158-3611358fff68"; - private string _clientId = "5221b482-2651-4cb3-9ad8-c09a78e4de9e"; - private string _kerberosServicePrincipalName = "HTTP/prod.aadkreberos.msal.com"; - private KerberosTicketContainer _ticketContainer = KerberosTicketContainer.IdToken; - private string _redirectUri = "http://localhost:8940/"; - private bool _isReadFromCache = false; - private long _logonId = 0; - - private string _Username = "localAdmin@aadktest.onmicrosoft.com"; - private string _UserPassword = string.Empty; - - private bool _isDeviceCodeFlow = false; - - private string[] _publicAppScopes = - { - "user.read", - "Application.Read.All" - }; - - public static void Main(string[] args) - { - Program program = new Program(); - if (args.Length > 0 && !program.ParseCommandLineArguments(args)) - { - return; - } - - if (program._isReadFromCache) - { - program.ShowCachedTicket(); - return; - } - - program.AcquireKerberosTicket(); - } - - /// - /// Parse the command line arguments and set internal parameters with supplied value. - /// - /// List of commandline arguments. - /// True if argument parsing completed. False, if there's an error detected. - public bool ParseCommandLineArguments(string[] args) - { - for (int i = 0; i < args.Length; i++) - { - if (args[i].Equals("-tenantId", StringComparison.OrdinalIgnoreCase) && (i + 1) < args.Length) - { - _tenantId = args[++i]; - } - else if (args[i].Equals("-clientId", StringComparison.OrdinalIgnoreCase) && (i + 1) < args.Length) - { - _clientId = args[++i]; - } - else if (args[i].Equals("-spn", StringComparison.OrdinalIgnoreCase) && (i + 1) < args.Length) - { - _kerberosServicePrincipalName = args[++i]; - } - else if (args[i].Equals("-container", StringComparison.OrdinalIgnoreCase) && (i + 1) < args.Length) - { - ++i; - if (args[i].Equals("id", StringComparison.OrdinalIgnoreCase)) - _ticketContainer = KerberosTicketContainer.IdToken; - else if (args[i].Equals("access", StringComparison.OrdinalIgnoreCase)) - _ticketContainer = KerberosTicketContainer.AccessToken; - else - { - Console.WriteLine("Unknown ticket container type '" + args[i] + "'"); - ShowUsages(); - return false; - } - } - else if (args[i].Equals("-redirectUri", StringComparison.OrdinalIgnoreCase) && (i + 1) < args.Length) - { - _redirectUri = args[++i]; - } - else if (args[i].Equals("-scopes", StringComparison.OrdinalIgnoreCase) && (i + 1) < args.Length) - { - _publicAppScopes = args[++i].Split(' '); - } - else if (args[i].Equals("-cached", StringComparison.OrdinalIgnoreCase)) - { - _isReadFromCache = true; - } - else if (args[i].Equals("-luid", StringComparison.OrdinalIgnoreCase)) - { - ++i; - try - { - _logonId = long.Parse(args[i], NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo); - } - catch (Exception ex) - { - Console.WriteLine("-luid should be a long number or HEX format string!"); - Console.WriteLine(ex); - return false; - } - } - else if (args[i].Equals("-upn", StringComparison.OrdinalIgnoreCase)) - { - i++; - _Username = args[i]; - } - else if (args[i].Equals("-password", StringComparison.OrdinalIgnoreCase)) - { - i++; - _UserPassword = args[i]; - } - else if (args[i].Equals("-devicecodeflow", StringComparison.OrdinalIgnoreCase)) - { - _isDeviceCodeFlow = true; - } - else - { - ShowUsages(); - return false; - } - } - - return true; - } - - /// - /// Acquire an authentication token. - /// If a valid token received, then show the received token information with included Kerberos Ticket. - /// If IdToken is used for token container, cached the received Kerberos Ticket into current user's - /// Windows Ticket Cache. - /// - public void AcquireKerberosTicket() - { - Console.WriteLine("Acquiring authentication token ..."); - AuthenticationResult result; - if (_isDeviceCodeFlow) - { - result = AcquireTokenWithDeviceCodeFlow(); - } - else if (string.IsNullOrEmpty(_Username) || string.IsNullOrEmpty(_UserPassword)) - { - result = AcquireTokenFromPublicClientWithInteractive(); - } - else - { - result = AcquireTokenFromPublicClientWithUserPassword(); - } - - if (result == null) - { - Console.WriteLine("Failed to get Access Token"); - return; - } - - ProcessKerberosTicket(result); - ShowCachedTicket(); - } - - /// - /// Checks there's a Kerberos Ticket in current user's Windows Ticket Cache matched with the service principal name. - /// If there's a valid ticket, then show the Ticket Information on the console. - /// - /// - public bool ShowCachedTicket() - { - try - { - byte[] ticket - = KerberosSupplementalTicketManager.GetKerberosTicketFromWindowsTicketCache(_kerberosServicePrincipalName, _logonId); - if (ticket != null && ticket.Length > 32) - { - var encode = Convert.ToBase64String(ticket); - - AADKerberosLogger.PrintLines(2); - AADKerberosLogger.Save($"---Find cached Ticket: {ticket.Length} bytes"); - AADKerberosLogger.PrintBinaryData(ticket); - - TicketDecoder decoder = new TicketDecoder(); - decoder.ShowApReqTicket(encode); - return true; - } - - Console.WriteLine($"There's no ticket associated with '{_kerberosServicePrincipalName}'"); - } - catch (Win32Exception ex) - { - Console.WriteLine($"ERROR while finding Kerberos Ticket for '{_kerberosServicePrincipalName}': {ex.Message}"); - } - return false; - } - - /// - /// Shows the program usages. - /// - private static void ShowUsages() - { - Console.WriteLine("KerberosConsole {option}"); - Console.WriteLine(" -tenantId {id} : set tenent Id to use."); - Console.WriteLine(" -clientId {id} : set client Id (Application Id) to use."); - Console.WriteLine(" -spn {spn} : set the service principal name to use."); - Console.WriteLine(" -container {id, access} : set the ticket container to use."); - Console.WriteLine(" -redirectUri {uri} : set redirectUri for OAuth2 authentication."); - Console.WriteLine(" -scopes {scopes} : list of scope separated by space."); - Console.WriteLine(" -cached : check cached ticket first."); - Console.WriteLine(" -luid {loginId} : sets login id of current user with HEX format."); - Console.WriteLine(" -upn {username}: Username with UPN format, e.g john@contoso.com, for Username/Password based authentication flow."); - Console.WriteLine(" -password {password}: Password for the given username."); - Console.WriteLine(" -devicecodeflow: Use Device Code flow to get authentication token."); - Console.WriteLine(" -h : show help for command options"); - } - - /// - /// Checks there's a valid Kerberos Ticket information within the received authentication token. - /// If there's a valid one, show the ticket information and cache it into current user's - /// Windows Ticket Cache so that it can be shared with other Kerberos-aware applications. - /// - /// The from token request. - private void ProcessKerberosTicket(AuthenticationResult result) - { - KerberosSupplementalTicket ticket; - if (_ticketContainer == KerberosTicketContainer.IdToken) - { - // 1. Get the Kerberos Ticket contained in the Id Token. - ticket = KerberosSupplementalTicketManager.FromIdToken(result.IdToken); - if (ticket == null) - { - AADKerberosLogger.Save("ERROR: There's no Kerberos Ticket information within the IdToken."); - return; - } - - AADKerberosLogger.PrintLines(2); - - try - { - // 2. Save the Kerberos Ticket into current user's Windows Ticket Cache. - KerberosSupplementalTicketManager.SaveToWindowsTicketCache(ticket, _logonId); - AADKerberosLogger.Save("---Kerberos Ticket cached into user's Ticket Cache\n"); - } - catch (Win32Exception ex) - { - AADKerberosLogger.Save("---Kerberos Ticket caching failed: " + ex.Message); - } - - AADKerberosLogger.PrintLines(2); - AADKerberosLogger.Save("KerberosSupplementalTicket {"); - AADKerberosLogger.Save(" Client Key: " + ticket.ClientKey); - AADKerberosLogger.Save(" Key Type: " + ticket.KeyType); - AADKerberosLogger.Save(" Errorr Message: " + ticket.ErrorMessage); - AADKerberosLogger.Save(" Realm: " + ticket.Realm); - AADKerberosLogger.Save(" Service Principal Name: " + ticket.ServicePrincipalName); - AADKerberosLogger.Save(" Client Name: " + ticket.ClientName); - AADKerberosLogger.Save(" KerberosMessageBuffer: " + ticket.KerberosMessageBuffer); - AADKerberosLogger.Save("}\n"); - - // shows detailed ticket information. - TicketDecoder decoder = new TicketDecoder(); - decoder.ShowKrbCredTicket(ticket.KerberosMessageBuffer); - } - else - { - AADKerberosLogger.PrintLines(2); - AADKerberosLogger.Save("Kerberos Ticket handling is not supported for access token."); - } - } - - /// - /// Acquire an authentication token interactively with public client configuration. - /// - /// The object. - private AuthenticationResult AcquireTokenFromPublicClientWithInteractive() - { - // 1. Setup public client application to get Kerberos Ticket. - var app = PublicClientApplicationBuilder.Create(_clientId) - .WithTenantId(_tenantId) - .WithRedirectUri(_redirectUri) - .WithKerberosTicketClaim(_kerberosServicePrincipalName, _ticketContainer) - .WithLogging(LogDelegate, LogLevel.Verbose, true, true) - .Build(); - - try - { - AADKerberosLogger.Save("Calling AcquireTokenInteractive() with:"); - AADKerberosLogger.Save(" Tenant Id: " + _tenantId); - AADKerberosLogger.Save(" Client Id: " + _clientId); - AADKerberosLogger.Save(" Redirect Uri: " + _redirectUri); - AADKerberosLogger.Save(" spn: " + _kerberosServicePrincipalName); - AADKerberosLogger.Save(" Ticket container: " + _ticketContainer); - - // 2. Acquire the authentication token. - // Kerberos Ticket will be contained in Id Token or Access Token - // according to specified ticket container parameter. - AuthenticationResult result = app.AcquireTokenInteractive(_publicAppScopes) - .ExecuteAsync() - .GetAwaiter() - .GetResult(); - - ShowAuthenticationResult(result); - return result; - } - catch (Exception ex) - { - AADKerberosLogger.Save("Exception: " + ex); - return null; - } - } - - /// - /// Acquire an authentication token with public client configuration using username/password non-interactively. - /// - /// NOTE: You have to enable public client flows for your application in the Azure Portal: - /// Login to the Azure Portal - /// Goto "App Registrations" - /// Select your application - /// Select "Authentication" under the Manage section. - /// Select "Yes" for the "Allow public client flows" under the Advanced Settings. - /// Click "Save" to save the changes. - /// - /// The object. - private AuthenticationResult AcquireTokenFromPublicClientWithUserPassword() - { - // 1. Setup public client application to get Kerberos Ticket. - var app = PublicClientApplicationBuilder.Create(_clientId) - .WithTenantId(_tenantId) - .WithRedirectUri(_redirectUri) - .WithKerberosTicketClaim(_kerberosServicePrincipalName, _ticketContainer) - .WithLogging(LogDelegate, LogLevel.Verbose, true, true) - .Build(); - - try - { - AADKerberosLogger.Save("Calling AcquireTokenByUsernamePassword() with:"); - AADKerberosLogger.Save(" Tenant Id: " + _tenantId); - AADKerberosLogger.Save(" Client Id: " + _clientId); - AADKerberosLogger.Save(" Redirect Uri: " + _redirectUri); - AADKerberosLogger.Save(" spn: " + _kerberosServicePrincipalName); - AADKerberosLogger.Save(" Ticket container: " + _ticketContainer); - AADKerberosLogger.Save(" Username: " + _Username); - - // 2. Acquire the authentication token. - // Kerberos Ticket will be contained in Id Token or Access Token - // according to specified ticket container parameter. - #pragma warning disable CS0618 // Type or member is obsolete - AuthenticationResult result = app.AcquireTokenByUsernamePassword(_publicAppScopes, _Username, _UserPassword) - .ExecuteAsync() - .GetAwaiter() - .GetResult(); - #pragma warning restore CS0618 - - ShowAuthenticationResult(result); - return result; - } - catch (Exception ex) - { - AADKerberosLogger.Save("Exception: " + ex); - return null; - } - } - - /// - /// Acquire an authentication token with public client configuration using username/password non-interactively. - /// - /// The object. - private AuthenticationResult AcquireTokenWithDeviceCodeFlow() - { - // 1. Setup public client application to get Kerberos Ticket. - var app = PublicClientApplicationBuilder.Create(_clientId) - .WithTenantId(_tenantId) - .WithRedirectUri(_redirectUri) - .WithKerberosTicketClaim(_kerberosServicePrincipalName, _ticketContainer) - .WithLogging(LogDelegate, LogLevel.Verbose, true, true) - .Build(); - - try - { - AADKerberosLogger.Save("Calling AcquireTokenWithDeviceCodeFlow() with:"); - AADKerberosLogger.Save(" Tenant Id: " + _tenantId); - AADKerberosLogger.Save(" Client Id: " + _clientId); - AADKerberosLogger.Save(" Redirect Uri: " + _redirectUri); - AADKerberosLogger.Save(" spn: " + _kerberosServicePrincipalName); - AADKerberosLogger.Save(" Ticket container: " + _ticketContainer); - - // 2. Acquire the authentication token. - // Kerberos Ticket will be contained in Id Token or Access Token - // according to specified ticket container parameter. - AuthenticationResult result = app - .AcquireTokenWithDeviceCode( - _publicAppScopes, - deviceCodeCallback => - { - ConsoleColor current = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine(deviceCodeCallback.Message); - Console.ForegroundColor = current; - - // stop console output of logging information posted from the MSAL. - AADKerberosLogger.SkipLoggingToConsole = true; - - return Task.FromResult(0); - }) - .ExecuteAsync() - .GetAwaiter() - .GetResult(); - - AADKerberosLogger.SkipLoggingToConsole = false; - ShowAuthenticationResult(result); - return result; - } - catch (Exception ex) - { - AADKerberosLogger.Save("Exception: " + ex); - return null; - } - } - - private void ShowAuthenticationResult(AuthenticationResult result) - { - ConsoleColor current = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Yellow; - - ShowAccount(result.Account); - AADKerberosLogger.Save("Token Information:"); - AADKerberosLogger.Save(" Correlation Id: " + result.CorrelationId); - AADKerberosLogger.Save(" Unique Id:" + result.UniqueId); - AADKerberosLogger.Save(" Expres On: " + result.ExpiresOn); - AADKerberosLogger.Save(" Access Token:\n" + result.AccessToken); - AADKerberosLogger.Save(" Id Token:\n" + result.IdToken); - - Console.ForegroundColor = current; - } - - /// - /// Shows the account information included in the authentication result. - /// - /// The information to display. - private void ShowAccount(IAccount account) - { - if (account != null) - { - AADKerberosLogger.Save("Account Info:"); - AADKerberosLogger.Save(" Username: " + account.Username); - AADKerberosLogger.Save(" Environment: " + account.Environment); - AADKerberosLogger.Save(" HomeAccount Tenant Id: " + account.HomeAccountId.TenantId); - AADKerberosLogger.Save(" HomeAccount Object Id: " + account.HomeAccountId.ObjectId); - AADKerberosLogger.Save(" Home Account Identifier: " + account.HomeAccountId.Identifier); - } - } - - /// - /// Callback to receive logging message for internal operation of the MSAL. - /// Show the received message to the console and save to the logging file. - /// - /// Log level of the log message to process - /// Pre-formatted log message - /// Indicates if the log message contains Organizational Identifiable Information (OII) - /// or Personally Identifiable Information (PII) nor not. - private static void LogDelegate(LogLevel level, string message, bool containsPii) - { - AADKerberosLogger.Save(message); - } - } -} diff --git a/tests/devapps/KerberosConsole/TicketDecoder.cs b/tests/devapps/KerberosConsole/TicketDecoder.cs deleted file mode 100644 index 8157987a4d..0000000000 --- a/tests/devapps/KerberosConsole/TicketDecoder.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Kerberos.NET; -using Kerberos.NET.Entities; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -using System; - -namespace KerberosConsole -{ - /// - /// Utility class to handle the Kerberos Ticket. - /// The Kerberos.NET package is used to show detailed internal structure of a Kerberos Ticket. - /// You can get detailed information for the Kerberos.NET package here: - /// https://www.nuget.org/packages/Kerberos.NET/ - /// - public class TicketDecoder - { - /// - /// Shows the Kerberos Ticket included in an authentication token with KrbCred format - /// which is used to transfer Kerberos credentials between applications. - /// Reference: - /// The Unencrypted Form of Kerberos 5 KRB-CRED Message - /// https://tools.ietf.org/html/rfc6448 - /// - /// - internal void ShowKrbCredTicket(string message) - { - var krbAsRepBytes = Convert.FromBase64String(message); - var krbCred = KrbCred.DecodeApplication(krbAsRepBytes); - Assert.IsNotNull(krbCred); - - var credPart = krbCred.Validate(); - Assert.IsNotNull(credPart); - - AADKerberosLogger.PrintLines(2); - AADKerberosLogger.Save("KRB-CRED Supplemental Ticket -----------------------------"); - AADKerberosLogger.Save(" ProtocolVersionNumber: " + krbCred.ProtocolVersionNumber); - AADKerberosLogger.Save(" Message Type: " + krbCred.MessageType); - AADKerberosLogger.Save(" # of Tickets: " + krbCred.Tickets.Length); - - for (int i = 0; i < krbCred.Tickets.Length; i++) - { - var ticket = krbCred.Tickets[i]; - var ticketInfo = credPart.TicketInfo[i]; - - var key = new byte[ticketInfo.Key.KeyValue.Length]; - ticketInfo.Key.KeyValue.CopyTo(key); - - AADKerberosLogger.Save(" Number: " + ticket.TicketNumber); - AADKerberosLogger.Save(" Realm: " + ticket.Realm); - AADKerberosLogger.Save(" SName: " + ticket.SName.FullyQualifiedName); - ShowEncryptedDataPart("EncryptedPart", ticket.EncryptedPart); - - AADKerberosLogger.Save(" Ticket.Flags: " + ticketInfo.Flags); - AADKerberosLogger.Save(" Ticket.Realm: " + ticketInfo.Realm); - AADKerberosLogger.Save(" Ticket.PName: " + ticketInfo.PName.FullyQualifiedName); - AADKerberosLogger.Save(" Ticket.SRealm: " + ticketInfo.SRealm); - AADKerberosLogger.Save(" Ticket.SName: " + ticketInfo.SName.FullyQualifiedName); - AADKerberosLogger.Save(" Ticket.AuthTime: " + ticketInfo.AuthTime); - AADKerberosLogger.Save(" Ticket.StartTime: " + ticketInfo.StartTime); - AADKerberosLogger.Save(" Ticket.EndTime: " + ticketInfo.EndTime); - AADKerberosLogger.Save(" Ticket.RenewTill: " + ticketInfo.RenewTill); - ShowEncrytionKey("Ticket.Key", ticketInfo.Key); - - if (ticketInfo.AuthorizationData == null) - { - AADKerberosLogger.Save(" Ticket.AuthorizationData:"); - } - else - { - for (int j = 0; j < ticketInfo.AuthorizationData.Length; j++) - { - ShowAuthorizationData("Ticket.AuthorizationData", ticketInfo.AuthorizationData[j]); - } - } - AADKerberosLogger.Save(""); - } - } - - /// - /// Shows the internal information of a cached Kerberos Ticket in current user's Windows Ticket Cache - /// with KRB_AP_REQ format. - /// Reference: - /// The Kerberos Network Authentication Service (V5) - /// https://tools.ietf.org/html/rfc4120#section-3.2.1 - /// - /// - internal void ShowApReqTicket(string messaage) - { - var tokenBytes = System.Convert.FromBase64String(messaage); - var contextToken = MessageParser.Parse(tokenBytes); - Assert.IsNotNull(contextToken); - Assert.IsNotNull(contextToken.KrbApReq); - - var req = contextToken.KrbApReq; - Assert.IsNotNull(req.Ticket); - - AADKerberosLogger.PrintLines(2); - AADKerberosLogger.Save("AP-REQ Cached Ticket----------------------------------------"); - AADKerberosLogger.Save(" Protocol Version Number: " + req.ProtocolVersionNumber); - AADKerberosLogger.Save(" MessageType: " + req.MessageType); - AADKerberosLogger.Save(" ApOptions: " + req.ApOptions); - - AADKerberosLogger.Save(" Ticket.TicketNumber: " + req.Ticket.TicketNumber); - AADKerberosLogger.Save(" Ticket.Realm: " + req.Ticket.Realm); - AADKerberosLogger.Save(" Ticket.SName: " + req.Ticket.SName.FullyQualifiedName); - ShowEncryptedDataPart("Ticket.EncryptedPart", req.Ticket.EncryptedPart); - ShowEncryptedDataPart("Ticket.Authenticator", req.Authenticator); - } - - private void ShowEncryptedDataPart(string title, KrbEncryptedData data) - { - if (data == null) - { - AADKerberosLogger.Save($" {title}:"); - } - else - { - AADKerberosLogger.Save($" {title}.EType: " + data.EType); - AADKerberosLogger.Save($" {title}.KeyVersionNumber: " + data.KeyVersionNumber); - AADKerberosLogger.Save($" {title}.Cipher.Length: " + data.Cipher.Length); - AADKerberosLogger.Save($" {title}.Cipher.Value:"); - AADKerberosLogger.PrintBinaryData(data.Cipher.ToArray()); - } - } - - private void ShowAuthorizationData(string title, KrbAuthorizationData auth) - { - if (auth != null) - { - AADKerberosLogger.Save($" {title}.Type: {auth.Type}"); - AADKerberosLogger.Save($" {title}.Data.Length: {auth.Data.Length}"); - AADKerberosLogger.Save($" {title}.Data.Value:"); - AADKerberosLogger.PrintBinaryData(auth.Data.ToArray()); - } - } - - private void ShowEncrytionKey(string title, KrbEncryptionKey key) - { - if (key == null) - { - AADKerberosLogger.Save($" {title}:"); - } - else - { - AADKerberosLogger.Save($" {title}.Usage: {key.Usage}"); - AADKerberosLogger.Save($" {title}.EType: {key.EType}"); - AADKerberosLogger.Save($" {title}.KeyValue.Length: {key.KeyValue.Length}"); - AADKerberosLogger.Save($" {title}.KeyValue.Value:"); - AADKerberosLogger.PrintBinaryData(key.KeyValue.ToArray()); - } - } - } -}