public void GetKrbCred() { KerberosSupplementalTicket ticket = KerberosSupplementalTicketManager.FromIdToken(_testIdTokenWithKerberosTicketClaim); byte[] krbCred = KerberosSupplementalTicketManager.GetKrbCred(ticket); Assert.IsNotNull(krbCred); }
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."); }
private async Task KerberosRunHappyPathTestAsync(LabResponse labResponse) { // Test with Id token var factory = new HttpSnifferClientFactory(); var idTokenPublicClient = PublicClientApplicationBuilder .Create(labResponse.App.AppId) .WithTestLogging() .WithHttpClientFactory(factory) .WithAuthority(labResponse.Lab.Authority, "organizations") .WithClientId(TestConstants.KerberosTestApplicationId) .WithKerberosTicketClaim(TestConstants.KerberosServicePrincipalName, KerberosTicketContainer.IdToken) .Build(); AuthenticationResult authResult = await GetAuthenticationResultWithAssertAsync( labResponse, factory, idTokenPublicClient, "", Guid.NewGuid()).ConfigureAwait(false); KerberosSupplementalTicket ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( authResult, KerberosTicketContainer.IdToken, labResponse.User.Upn); Assert.IsNotNull(ticket); TestCommon.ValidateKerberosWindowsTicketCacheOperation(ticket); // Test with Access Token factory = new HttpSnifferClientFactory(); var accessTokenPublicClient = PublicClientApplicationBuilder .Create(labResponse.App.AppId) .WithTestLogging() .WithHttpClientFactory(factory) .WithAuthority(labResponse.Lab.Authority, "organizations") .WithClientId(TestConstants.KerberosTestApplicationId) .WithKerberosTicketClaim(TestConstants.KerberosServicePrincipalName, KerberosTicketContainer.AccessToken) .Build(); authResult = await GetAuthenticationResultWithAssertAsync( labResponse, factory, accessTokenPublicClient, "", Guid.NewGuid()).ConfigureAwait(false); ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( authResult, KerberosTicketContainer.AccessToken, labResponse.User.Upn); Assert.IsNotNull(ticket); TestCommon.ValidateKerberosWindowsTicketCacheOperation(ticket); }
/// <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); }
private async Task KerberosAcquireTokenWithDeviceCodeFlowAsync(LabResponse labResponse, string userType, KerberosTicketContainer ticketContainer) { Trace.WriteLine($"Calling KerberosAcquireTokenWithDeviceCodeFlowAsync with {0}", userType); var builder = PublicClientApplicationBuilder.Create(labResponse.App.AppId) .WithTestLogging() .WithTenantId(labResponse.Lab.TenantId) .WithClientId(TestConstants.KerberosTestApplicationId) .WithKerberosTicketClaim(TestConstants.KerberosServicePrincipalName, ticketContainer); switch (labResponse.User.AzureEnvironment) { case AzureEnvironment.azureusgovernment: builder.WithAuthority(labResponse.Lab.Authority + labResponse.Lab.TenantId); break; default: break; } var pca = builder.Build(); var userCacheAccess = pca.UserTokenCache.RecordAccess(); var result = await pca.AcquireTokenWithDeviceCode(s_scopes, deviceCodeResult => { SeleniumExtensions.PerformDeviceCodeLogin(deviceCodeResult, labResponse.User, TestContext, false); return(Task.FromResult(0)); }).ExecuteAsync(CancellationToken.None).ConfigureAwait(false); Trace.WriteLine("Running asserts"); userCacheAccess.AssertAccessCounts(0, 1); Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); Assert.IsNotNull(result); Assert.IsTrue(!string.IsNullOrEmpty(result.AccessToken)); KerberosSupplementalTicket ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( result, ticketContainer, labResponse.User.Upn); Assert.IsNotNull(ticket); TestCommon.ValidateKerberosWindowsTicketCacheOperation(ticket); }
/// <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); }
private async Task <AuthenticationResult> KerberosRunTestForUserAsync( LabResponse labResponse, KerberosTicketContainer ticketContainer) { HttpSnifferClientFactory factory = null; IPublicClientApplication pca = PublicClientApplicationBuilder .Create(labResponse.App.AppId) .WithRedirectUri(SeleniumWebUI.FindFreeLocalhostRedirectUri()) .WithAuthority(labResponse.Lab.Authority + "common") .WithTestLogging(out factory) .WithTenantId(labResponse.Lab.TenantId) .WithClientId(TestConstants.KerberosTestApplicationId) .WithKerberosTicketClaim(TestConstants.KerberosServicePrincipalName, ticketContainer) .Build(); var userCacheAccess = pca.UserTokenCache.RecordAccess(); Trace.WriteLine("Part 1 - Acquire a token interactively, no login hint"); AuthenticationResult result = await pca .AcquireTokenInteractive(s_scopes) .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.SelectAccount, false, false)) .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); Assert.IsTrue(result.AuthenticationResultMetadata.DurationTotalInMs > 0); Assert.IsTrue(result.AuthenticationResultMetadata.DurationInHttpInMs > 0); KerberosSupplementalTicket ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( result, ticketContainer, labResponse.User.Upn); Assert.IsNotNull(ticket); userCacheAccess.AssertAccessCounts(0, 1); IAccount account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(1, 1); // the assert calls GetAccounts Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); Trace.WriteLine("Part 2 - Clear the cache"); await pca.RemoveAsync(account).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(1, 2); Assert.IsFalse((await pca.GetAccountsAsync().ConfigureAwait(false)).Any()); userCacheAccess.AssertAccessCounts(2, 2); Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); if (factory?.RequestsAndResponses != null) { factory.RequestsAndResponses.Clear(); } Trace.WriteLine("Part 3 - Acquire a token interactively again, with login hint"); result = await pca .AcquireTokenInteractive(s_scopes) .WithCustomWebUi(CreateSeleniumCustomWebUI(labResponse.User, Prompt.ForceLogin, true, false)) .WithPrompt(Prompt.ForceLogin) .WithLoginHint(labResponse.User.Upn) .ExecuteAsync(new CancellationTokenSource(_interactiveAuthTimeout).Token) .ConfigureAwait(false); userCacheAccess.AssertAccessCounts(2, 3); AssertCcsRoutingInformationIsSent(factory, labResponse); ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( result, ticketContainer, labResponse.User.Upn); Assert.IsNotNull(ticket); account = await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); userCacheAccess.AssertAccessCounts(3, 3); Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); if (factory?.RequestsAndResponses != null) { factory.RequestsAndResponses.Clear(); } Trace.WriteLine("Part 4 - Acquire a token silently"); result = await pca .AcquireTokenSilent(s_scopes, account) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( result, ticketContainer, labResponse.User.Upn); Assert.IsNotNull(ticket); Trace.WriteLine("Part 5 - Acquire a token silently with force refresh"); result = await pca .AcquireTokenSilent(s_scopes, account) .WithForceRefresh(true) .ExecuteAsync(CancellationToken.None) .ConfigureAwait(false); await MsalAssert.AssertSingleAccountAsync(labResponse, pca, result).ConfigureAwait(false); Assert.IsFalse(userCacheAccess.LastAfterAccessNotificationArgs.IsApplicationCache); AssertCcsRoutingInformationIsSent(factory, labResponse); ticket = TestCommon.GetValidatedKerberosTicketFromAuthenticationResult( result, ticketContainer, labResponse.User.Upn); Assert.IsNotNull(ticket); TestCommon.ValidateKerberosWindowsTicketCacheOperation(ticket); return(result); }
/// <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."); }