Skip to content

Commit

Permalink
Enabling Arlington automation tests (#1672)
Browse files Browse the repository at this point in the history
* adding Arlington USGov tests

* Adding ROPC and OBO test for arlington

* Addressing PR comments

* clean up

* Addressing comments

* Fixing tests

* Fixing test

Co-authored-by: trwalke <trwalke@microsoft.com>
  • Loading branch information
trwalke and trwalke committed Apr 2, 2020
1 parent 806d423 commit 068f6cb
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 46 deletions.
2 changes: 2 additions & 0 deletions tests/Microsoft.Identity.Test.Common/TestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,10 @@ public static IDictionary<string, string> ExtraQueryParameters

public const string MsalCCAKeyVaultUri = "https://buildautomation.vault.azure.net/secrets/AzureADIdentityDivisionTestAgentSecret/";
public const string MsalOBOKeyVaultUri = "https://buildautomation.vault.azure.net/secrets/IdentityDivisionDotNetOBOServiceSecret/";
public const string MsalArlingtonOBOKeyVaultUri = "https://msidlabs.vault.azure.net:443/secrets/ARLMSIDLAB1-IDLASBS-App-CC-Secret";
public const string FociApp1 = "https://buildautomation.vault.azure.net/secrets/automation-foci-app1/";
public const string FociApp2 = "https://buildautomation.vault.azure.net/secrets/automation-foci-app2/";
public const string MsalArlingtonCCAKeyVaultUri = "https://msidlabs.vault.azure.net:443/secrets/ARLMSIDLAB1-IDLASBS-App-CC-Secret";

public enum AuthorityType { B2C };
public static string[] s_prodEnvAliases = new string[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,28 @@ namespace Microsoft.Identity.Test.Integration.HeadlessTests
public class ConfidentialClientIntegrationTests
{
private static readonly string[] s_scopes = { "User.Read" };
private static readonly string[] s_oboServiceScope = { "api://23c64cd8-21e4-41dd-9756-ab9e2c23f58c/access_as_user" };
private static readonly string[] s_publicCloudOBOServiceScope = { "api://23c64cd8-21e4-41dd-9756-ab9e2c23f58c/access_as_user" };
private static readonly string[] s_arlingtonOBOServiceScope = { "https://arlmsidlab1.us/IDLABS_APP_Confidential_Client/user_impersonation" };
private static readonly string[] s_keyvaultScope = { "https://vault.azure.net/.default" };
private static readonly string[] s_adfsScopes = { "openid", "profile" };

//TODO: acquire scenario specific client ids from the lab resonse
private const string ConfidentialClientID = "16dab2ba-145d-4b1b-8569-bf4b9aed4dc8";
private const string PublicCloudPublicClientIDOBO = "be9b0186-7dfd-448a-a944-f771029105bf";
private const string PublicCloudConfidentialClientIDOBO = "23c64cd8-21e4-41dd-9756-ab9e2c23f58c";
private const string PublicCloudConfidentialClientID = "16dab2ba-145d-4b1b-8569-bf4b9aed4dc8";
private const string ArlingtonConfidentialClientIDOBO = "c0555d2d-02f2-4838-802e-3463422e571d";
private const string ArlingtonPublicClientIDOBO = "cb7faed4-b8c0-49ee-b421-f5ed16894c83";
private const string ArlingtonAuthority = "https://login.microsoftonline.us/45ff0c17-f8b5-489b-b7fd-2fedebbec0c4";

private const string PublicCloudHost = "https://login.microsoftonline.com/";
private const string ArlingtonCloudHost = "https://login.microsoftonline.us/";

private const string RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
private const string TestAuthority = "https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47";
private const string PublicCloudTestAuthority = "https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47";
private const string AdfsCertName = "IDLABS-APP-Confidential-Client-Cert-OnPrem";
private KeyVaultSecretsProvider _keyVault;
private string _ccaSecret;
private static string _publicCloudCcaSecret;
private static string _arlingtonCCASecret;

[ClassInitialize]
public static void ClassInitialize(TestContext context)
Expand All @@ -58,7 +68,8 @@ public void TestInitialize()
if (_keyVault == null)
{
_keyVault = new KeyVaultSecretsProvider();
_ccaSecret = _keyVault.GetSecret(TestConstants.MsalCCAKeyVaultUri).Value;
_publicCloudCcaSecret = _keyVault.GetSecret(TestConstants.MsalCCAKeyVaultUri).Value;
_arlingtonCCASecret = _keyVault.GetSecret(TestConstants.MsalArlingtonCCAKeyVaultUri).Value;
}
}

Expand All @@ -67,7 +78,7 @@ public void TestInitialize()
public async Task GetAuthorizationRequestUrl_ReturnsUri_Async()
{
var cca = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(PublicCloudConfidentialClientID)
.WithRedirectUri(RedirectUri)
.Build();

Expand All @@ -82,7 +93,7 @@ public async Task GetAuthorizationRequestUrl_ReturnsUri_Async()

CoreAssert.AreEqual("offline_access openid profile User.Read", uriParams1["scope"], uriParams2["scope"]);
CoreAssert.AreEqual("code", uriParams1["response_type"], uriParams2["response_type"]);
CoreAssert.AreEqual(ConfidentialClientID, uriParams1["client_id"], uriParams2["client_id"]);
CoreAssert.AreEqual(PublicCloudConfidentialClientID, uriParams1["client_id"], uriParams2["client_id"]);
CoreAssert.AreEqual(RedirectUri, uriParams1["redirect_uri"], uriParams2["redirect_uri"]);
CoreAssert.AreEqual("select_account", uriParams1["prompt"], uriParams2["prompt"]);

Expand All @@ -98,10 +109,10 @@ public async Task ConfidentialClientWithCertificateTestAsync()
AuthenticationResult authResult;
IConfidentialClientApplication confidentialApp;
X509Certificate2 cert = GetCertificate();
var confidentialClientAuthority = TestAuthority;
var confidentialClientAuthority = PublicCloudTestAuthority;

confidentialApp = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(PublicCloudConfidentialClientID)
.WithAuthority(new Uri(confidentialClientAuthority), true)
.WithCertificate(cert)
.Build();
Expand Down Expand Up @@ -134,10 +145,10 @@ public async Task ConfidentialClientWithRSACertificateTestAsync()
AuthenticationResult authResult;
IConfidentialClientApplication confidentialApp;
X509Certificate2 cert = GetCertificate(true);
var confidentialClientAuthority = TestAuthority;
var confidentialClientAuthority = PublicCloudTestAuthority;

confidentialApp = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(PublicCloudConfidentialClientID)
.WithAuthority(new Uri(confidentialClientAuthority), true)
.WithCertificate(cert)
.Build();
Expand Down Expand Up @@ -166,12 +177,27 @@ public async Task ConfidentialClientWithRSACertificateTestAsync()
[TestMethod]
public async Task ConfidentialClientWithClientSecretTestAsync()
{
var confidentialClientAuthority = TestAuthority;
await RunTestWithClientSecretAsync(PublicCloudConfidentialClientID,
PublicCloudTestAuthority,
_publicCloudCcaSecret).ConfigureAwait(false);
}

[TestMethod]
public async Task ArlingtonConfidentialClientWithClientSecretTestAsync()
{
await RunTestWithClientSecretAsync(ArlingtonConfidentialClientIDOBO,
ArlingtonAuthority,
_arlingtonCCASecret).ConfigureAwait(false);
}

public async Task RunTestWithClientSecretAsync(string clientID, string authority, string secret)
{
var confidentialClientAuthority = authority;

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(clientID)
.WithAuthority(new Uri(confidentialClientAuthority), true)
.WithClientSecret(_ccaSecret)
.WithClientSecret(secret)
.Build();
var appCacheRecorder = confidentialApp.AppTokenCache.RecordAccess();

Expand All @@ -196,13 +222,13 @@ public async Task ConfidentialClientWithClientSecretTestAsync()
[TestMethod]
public async Task ConfidentialClientWithNoDefaultClaimsTestAsync()
{
var confidentialClientAuthority = TestAuthority;
var confidentialClientAuthority = PublicCloudTestAuthority;
var claims = GetClaims();

X509Certificate2 cert = GetCertificate();

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(PublicCloudConfidentialClientID)
.WithAuthority(new Uri(confidentialClientAuthority), true)
.WithClientClaims(cert, claims, false)
.Build();
Expand All @@ -219,13 +245,13 @@ public async Task ConfidentialClientWithNoDefaultClaimsTestAsync()
[TestMethod]
public async Task ConfidentialClientWithDefaultClaimsTestAsync()
{
var confidentialClientAuthority = TestAuthority;
var confidentialClientAuthority = PublicCloudTestAuthority;
var claims = GetClaims(false);

X509Certificate2 cert = GetCertificate();

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(PublicCloudConfidentialClientID)
.WithAuthority(new Uri(confidentialClientAuthority), true)
.WithClientClaims(cert, claims)
.Build();
Expand All @@ -247,13 +273,13 @@ public async Task ConfidentialClientWithDefaultClaimsTestAsync()
[TestMethod]
public async Task ConfidentialClientWithSignedAssertionTestAsync()
{
var confidentialClientAuthority = TestAuthority;
var confidentialClientAuthority = PublicCloudTestAuthority;
var claims = GetClaims();

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(ConfidentialClientID)
.Create(PublicCloudConfidentialClientID)
.WithAuthority(new Uri(confidentialClientAuthority), true)
.WithClientAssertion(GetSignedClientAssertionUsingMsalInternal(ConfidentialClientID, claims))
.WithClientAssertion(GetSignedClientAssertionUsingMsalInternal(PublicCloudConfidentialClientID, claims))
.Build();

var appCacheRecorder = confidentialApp.AppTokenCache.RecordAccess();
Expand Down Expand Up @@ -312,10 +338,10 @@ private static IDictionary<string, string> GetClaims(bool useDefaultClaims = tru
{
{ "aud", TestConstants.ClientCredentialAudience },
{ "exp", exp.ToString(CultureInfo.InvariantCulture) },
{ "iss", ConfidentialClientID.ToString(CultureInfo.InvariantCulture) },
{ "iss", PublicCloudConfidentialClientID.ToString(CultureInfo.InvariantCulture) },
{ "jti", Guid.NewGuid().ToString() },
{ "nbf", nbf.ToString(CultureInfo.InvariantCulture) },
{ "sub", ConfidentialClientID.ToString(CultureInfo.InvariantCulture) },
{ "sub", PublicCloudConfidentialClientID.ToString(CultureInfo.InvariantCulture) },
{ "ip", "192.168.2.1" }
};
}
Expand Down Expand Up @@ -361,6 +387,12 @@ public async Task WebAPIAccessingGraphOnBehalfOfUserTestAsync()
}

[TestMethod]
public async Task ArlingtonWebAPIAccessingGraphOnBehalfOfUserTestAsync()
{
var labResponse = await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false);
await RunOnBehalfOfTestAsync(labResponse).ConfigureAwait(false);
}

[TestCategory(TestCategories.ADFS)]
public async Task WebAPIAccessingGraphOnBehalfOfADFS2019UserTestAsync()
{
Expand Down Expand Up @@ -470,25 +502,52 @@ private static string GetSignedClientAssertionUsingWilson(

private async Task RunOnBehalfOfTestAsync(LabResponse labResponse)
{
var user = labResponse.User;
LabUser user = labResponse.User;
string oboHost;
string secret;
string authority;
string publicClientID;
string confidentialClientID;
string[] oboScope;

switch (labResponse.User.AzureEnvironment)
{
case AzureEnvironment.azureusgovernment:
oboHost = ArlingtonCloudHost;
secret = _keyVault.GetSecret(TestConstants.MsalArlingtonOBOKeyVaultUri).Value;
authority = labResponse.Lab.Authority + "organizations";
publicClientID = ArlingtonPublicClientIDOBO;
confidentialClientID = ArlingtonConfidentialClientIDOBO;
oboScope = s_arlingtonOBOServiceScope;
break;
default:
oboHost = PublicCloudHost;
secret = _keyVault.GetSecret(TestConstants.MsalOBOKeyVaultUri).Value;
authority = TestConstants.AuthorityOrganizationsTenant;
publicClientID = PublicCloudPublicClientIDOBO;
confidentialClientID = PublicCloudConfidentialClientIDOBO;
oboScope = s_publicCloudOBOServiceScope;
break;
}

var secret = _keyVault.GetSecret(TestConstants.MsalOBOKeyVaultUri).Value;
//TODO: acquire scenario specific client ids from the lab resonse
var publicClientID = "be9b0186-7dfd-448a-a944-f771029105bf";
var oboConfidentialClientID = "23c64cd8-21e4-41dd-9756-ab9e2c23f58c";

SecureString securePassword = new NetworkCredential("", user.GetOrFetchPassword()).SecurePassword;

var msalPublicClient = PublicClientApplicationBuilder.Create(publicClientID).WithAuthority(TestConstants.AuthorityOrganizationsTenant).WithRedirectUri(TestConstants.RedirectUri).Build();
var msalPublicClient = PublicClientApplicationBuilder.Create(publicClientID)
.WithAuthority(authority)
.WithRedirectUri(TestConstants.RedirectUri)
.Build();

AuthenticationResult authResult = await msalPublicClient
.AcquireTokenByUsernamePassword(s_oboServiceScope, user.Upn, securePassword)
.ExecuteAsync(CancellationToken.None)
.ConfigureAwait(false);
var builder = msalPublicClient.AcquireTokenByUsernamePassword(oboScope, user.Upn, securePassword);

builder.WithAuthority(authority);

var authResult = await builder.ExecuteAsync().ConfigureAwait(false);

var confidentialApp = ConfidentialClientApplicationBuilder
.Create(oboConfidentialClientID)
.WithAuthority(new Uri("https://login.microsoftonline.com/" + authResult.TenantId), true)
.Create(confidentialClientID)
.WithAuthority(new Uri(oboHost + authResult.TenantId), true)
.WithClientSecret(secret)
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
using Microsoft.Identity.Test.Common.Core.Helpers;
using Microsoft.Identity.Test.Integration.net45.Infrastructure;
using Microsoft.Identity.Test.LabInfrastructure;
using Microsoft.Identity.Test.Unit;
using Microsoft.Identity.Test.Unit;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Identity.Test.Integration.HeadlessTests
Expand Down Expand Up @@ -59,6 +59,20 @@ public async Task ROPC_AAD_Async()
await RunHappyPathTestAsync(labResponse).ConfigureAwait(false);
}

[TestMethod]
public async Task ARLINGTON_ROPC_AAD_Async()
{
var labResponse = await LabUserHelper.GetArlingtonUserAsync().ConfigureAwait(false);
await RunHappyPathTestAsync(labResponse).ConfigureAwait(false);
}

[TestMethod]
public async Task ARLINGTON_ROPC_ADFS_Async()
{
var labResponse = await LabUserHelper.GetArlingtonADFSUserAsync().ConfigureAwait(false);
await RunHappyPathTestAsync(labResponse).ConfigureAwait(false);
}

[TestMethod]
public async Task ROPC_ADFSv4Federated_Async()
{
Expand All @@ -82,8 +96,8 @@ public async Task AcquireTokenFromAdfsUsernamePasswordAsync()
var user = labResponse.User;

SecureString securePassword = new NetworkCredential("", user.GetOrFetchPassword()).SecurePassword;

var msalPublicClient = PublicClientApplicationBuilder.Create(Adfs2019LabConstants.PublicClientId).WithAdfsAuthority(Adfs2019LabConstants.Authority).Build();

var msalPublicClient = PublicClientApplicationBuilder.Create(Adfs2019LabConstants.PublicClientId).WithAdfsAuthority(Adfs2019LabConstants.Authority).Build();
AuthenticationResult authResult = await msalPublicClient.AcquireTokenByUsernamePassword(s_scopes, user.Upn, securePassword).ExecuteAsync().ConfigureAwait(false);
Assert.IsNotNull(authResult);
Assert.IsNotNull(authResult.AccessToken);
Expand Down Expand Up @@ -172,7 +186,7 @@ private async Task CheckTelemetryHeadersAsync(
Assert.IsNotNull(authResult.AccessToken);
Assert.IsNotNull(authResult.IdToken);
Assert.IsTrue(string.Equals(labResponse.User.Upn, authResult.Account.Username, StringComparison.InvariantCultureIgnoreCase));
AssertTelemetryHeaders(factory, true);
AssertTelemetryHeaders(factory, true, labResponse);
}

private async Task RunAcquireTokenWithUsernameIncorrectPasswordAsync(
Expand Down Expand Up @@ -209,8 +223,8 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse)
var factory = new HttpSnifferClientFactory();
var msalPublicClient = PublicClientApplicationBuilder
.Create(labResponse.App.AppId)
.WithAuthority(Authority)
.WithHttpClientFactory(factory)
.WithAuthority(labResponse.Lab.Authority, "organizations")
.Build();

AuthenticationResult authResult = await msalPublicClient
Expand All @@ -223,7 +237,7 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse)
Assert.IsNotNull(authResult.AccessToken);
Assert.IsNotNull(authResult.IdToken);
Assert.IsTrue(string.Equals(labResponse.User.Upn, authResult.Account.Username, StringComparison.InvariantCultureIgnoreCase));
AssertTelemetryHeaders(factory, false);
AssertTelemetryHeaders(factory, false, labResponse);
// If test fails with "user needs to consent to the application, do an interactive request" error,
// Do the following:
// 1) Add in code to pull the user's password before creating the SecureString, and put a breakpoint there.
Expand All @@ -233,9 +247,9 @@ private async Task RunHappyPathTestAsync(LabResponse labResponse)
// 4) After successful log-in, remove the password line you added in with step 1, and run the integration test again.
}

private void AssertTelemetryHeaders(HttpSnifferClientFactory factory, bool IsFailure)
private void AssertTelemetryHeaders(HttpSnifferClientFactory factory, bool IsFailure, LabResponse labResponse)
{
var (req, res) = factory.RequestsAndResponses.Single(x => x.Item1.RequestUri.AbsoluteUri == "https://login.microsoftonline.com/organizations/oauth2/v2.0/token" &&
var (req, res) = factory.RequestsAndResponses.Single(x => x.Item1.RequestUri.AbsoluteUri == labResponse.Lab.Authority + "organizations/oauth2/v2.0/token" &&
x.Item2.StatusCode == HttpStatusCode.OK);

var telemetryLastValue = req.Headers.Single(h => h.Key == TelemetryConstants.XClientLastTelemetry).Value;
Expand Down
Loading

0 comments on commit 068f6cb

Please sign in to comment.