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());
- }
- }
- }
-}