/// <summary> /// 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. /// </summary> /// <returns></returns> 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); }
public void GetKrbCred() { KerberosSupplementalTicket ticket = KerberosSupplementalTicketManager.FromIdToken(_testIdTokenWithKerberosTicketClaim); byte[] krbCred = KerberosSupplementalTicketManager.GetKrbCred(ticket); Assert.IsNotNull(krbCred); }
private async Task AddBodyParamsAndHeadersAsync( IDictionary <string, string> additionalBodyParameters, string scopes, CancellationToken cancellationToken) { _oAuth2Client.AddBodyParameter(OAuth2Parameter.ClientId, _requestParams.AppConfig.ClientId); if (_serviceBundle.Config.ClientCredential != null) { await _serviceBundle.Config.ClientCredential.AddConfidentialClientParametersAsync( _oAuth2Client, _requestParams.RequestContext.Logger, _serviceBundle.PlatformProxy.CryptographyManager, _requestParams.AppConfig.ClientId, _requestParams.Authority.GetTokenEndpoint(), _requestParams.SendX5C, cancellationToken).ConfigureAwait(false); } _oAuth2Client.AddBodyParameter(OAuth2Parameter.Scope, scopes); // Add Kerberos Ticket claims if there's valid service principal name in Configuration. // Kerberos Ticket claim is only allowed at token request due to security issue. // It should not be included for authorize request. KerberosSupplementalTicketManager.AddKerberosTicketClaim(_oAuth2Client, _requestParams); foreach (var kvp in additionalBodyParameters) { _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value); } foreach (var kvp in _requestParams.AuthenticationScheme.GetTokenRequestParams()) { _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value); } _oAuth2Client.AddHeader( TelemetryConstants.XClientCurrentTelemetry, _serviceBundle.HttpTelemetryManager.GetCurrentRequestHeader( _requestParams.RequestContext.ApiEvent)); if (!_requestInProgress) { _requestInProgress = true; _oAuth2Client.AddHeader( TelemetryConstants.XClientLastTelemetry, _serviceBundle.HttpTelemetryManager.GetLastRequestHeader()); } //Signaling that the client can perform PKey Auth on supported platforms if (DeviceAuthHelper.CanOSPerformPKeyAuth()) { _oAuth2Client.AddHeader(PKeyAuthConstants.DeviceAuthHeaderName, PKeyAuthConstants.DeviceAuthHeaderValue); } AddExtraHttpHeaders(); }
public void FromIdToken_WithKerberosTicket() { KerberosSupplementalTicket ticket = KerberosSupplementalTicketManager.FromIdToken(_testIdTokenWithKerberosTicketClaim); Assert.IsNotNull(ticket); Assert.IsTrue(string.IsNullOrEmpty(ticket.ErrorMessage)); Assert.IsFalse(string.IsNullOrEmpty(ticket.KerberosMessageBuffer)); Assert.AreEqual(_testServicePrincipalName, ticket.ServicePrincipalName, "Service principal name is not matched."); Assert.AreEqual(_testClientName, ticket.ClientName, "Client name is not matched."); }
/// <summary> /// Get a Kerberos Ticket contained in the given token. /// </summary> /// <param name="token">Token to be validated.</param> /// <param name="userUpn">UPN of the client.</param> /// <returns>A <see cref="KerberosSupplementalTicket"/> if there's valid one.</returns> public static KerberosSupplementalTicket GetValidatedKerberosTicketFromToken(string token, string userUpn) { KerberosSupplementalTicket ticket = KerberosSupplementalTicketManager.FromIdToken(token); Assert.IsNotNull(ticket, "Kerberos Ticket is not found."); Assert.IsTrue(string.IsNullOrEmpty(ticket.ErrorMessage), "Kerberos Ticket creation failed with: " + ticket.ErrorMessage); Assert.IsFalse(string.IsNullOrEmpty(ticket.KerberosMessageBuffer), "Kerberos Ticket data is not found."); Assert.IsTrue(ticket.KerberosMessageBuffer.Length > TestConstants.KerberosMinMessageBufferLength, "Received Kerberos Ticket data is too short."); Assert.AreEqual(KerberosKeyTypes.Aes256CtsHmacSha196, ticket.KeyType, "Kerberos key type is not matched."); Assert.AreEqual(TestConstants.KerberosServicePrincipalName, ticket.ServicePrincipalName, true, CultureInfo.InvariantCulture, "Service principal name is not matched."); Assert.AreEqual(userUpn, ticket.ClientName, true, CultureInfo.InvariantCulture, "Client name is not matched."); return(ticket); }
/// <summary> /// 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. /// </summary> /// <param name="result">The <see cref="AuthenticationResult"/> from token request.</param> 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."); } }
public void GetKerberosTicketClaim_AccessToken() { string kerberosClaim = KerberosSupplementalTicketManager.GetKerberosTicketClaim(_testServicePrincipalName, KerberosTicketContainer.AccessToken); Assert.IsFalse(string.IsNullOrEmpty(kerberosClaim)); JsonObject claim = JsonObject.Parse(kerberosClaim); Assert.IsNotNull(claim); Assert.IsTrue(claim.ContainsKey("access_token")); JsonObject accessToken = claim.GetNamedObject("access_token"); Assert.IsNotNull(accessToken); CheckKerberosClaim(accessToken); }
/// <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); } }
public void FromIdToken_WithoutKerberosTicket() { KerberosSupplementalTicket ticket = KerberosSupplementalTicketManager.FromIdToken(_testIdToken); Assert.IsNull(ticket); }
/// <summary> /// Validates there were no valid Kerberos Ticket contained in the given token. /// </summary> /// <param name="token">Token to be validated.</param> public static void ValidateNoKerberosTicketFromToken(string token) { KerberosSupplementalTicket ticket = KerberosSupplementalTicketManager.FromIdToken(token); Assert.IsNull(ticket, "Kerberos Ticket exists."); }